summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf/dwarf/common
diff options
context:
space:
mode:
authorRichard Lowe <richlowe@richlowe.net>2011-06-08 17:36:48 -0400
committerRichard Lowe <richlowe@richlowe.net>2011-06-08 17:36:48 -0400
commit49d3bc91e27cd871b950d56c01398fa2f2e12ab4 (patch)
treeb7edaae89f4db21b8980ec0d3f15185433374cfd /usr/src/tools/ctf/dwarf/common
parent10a2419a4aad5cd9407427cea2b24d9572bca16d (diff)
downloadillumos-gate-49d3bc91e27cd871b950d56c01398fa2f2e12ab4.tar.gz
1057 should correctly integrate libdwarf sources
Reviewed by: Gordon Ross <gwr@nexenta.com> Reviewed by: Garrett D'Amore <garrett@nexenta.com> Approved by: Eric Schrock <eric.schrock@delphix.com> --HG-- rename : usr/src/tools/ctf/dwarf/dwarf.h => usr/src/tools/ctf/dwarf/common/dwarf.h rename : usr/src/tools/ctf/dwarf/libdwarf.h => usr/src/tools/ctf/dwarf/common/libdwarf.h
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common')
-rw-r--r--usr/src/tools/ctf/dwarf/common/acconfig.h68
-rw-r--r--usr/src/tools/ctf/dwarf/common/cmplrs/dwarf_addr_finder.h55
-rw-r--r--usr/src/tools/ctf/dwarf/common/config.h144
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf.h721
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c248
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h45
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c686
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_alloc.c1122
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_alloc.h167
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_arange.c623
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_arange.h63
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_base_types.h107
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c765
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h56
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_error.c378
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_error.h43
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_form.c694
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_frame.c2448
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_frame.h207
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_funcs.c121
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_funcs.h42
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_global.c464
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_global.h104
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_incl.h57
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c809
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_leb.c149
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_line.c1548
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_line.h230
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_loc.c912
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_loc.h46
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_macro.c409
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_macro.h44
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_opaque.h269
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c666
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_query.c609
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c727
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_string.c82
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_stubs.c50
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_types.c123
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_types.h41
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_util.c383
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_util.h267
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_vars.c123
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_vars.h41
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_weaks.c122
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_weaks.h41
-rw-r--r--usr/src/tools/ctf/dwarf/common/libdwarf.h1602
-rw-r--r--usr/src/tools/ctf/dwarf/common/libdwarfdefs.h85
-rw-r--r--usr/src/tools/ctf/dwarf/common/mapfile-vers199
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_alloc.c71
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_alloc.h40
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_arange.c336
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_arange.h62
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_die.c390
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_die.h68
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_encode_nm.c123
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_encode_nm.h48
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_error.c97
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_error.h52
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_expr.c550
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_expr.h45
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_finish.c55
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_forms.c857
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_frame.c552
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_frame.h126
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_funcs.c62
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_incl.h73
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_init.c249
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_line.c300
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_line.h111
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_macinfo.c472
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_macinfo.h40
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_opaque.h493
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_pubnames.c63
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_reloc.c268
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_reloc.h47
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c298
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h63
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.c299
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.h55
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_section.c1958
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_section.h112
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_types.c294
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_types.h44
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_util.h107
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_vars.c62
-rw-r--r--usr/src/tools/ctf/dwarf/common/pro_weaks.c61
87 files changed, 28008 insertions, 0 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/acconfig.h b/usr/src/tools/ctf/dwarf/common/acconfig.h
new file mode 100644
index 0000000000..e45940454b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/acconfig.h
@@ -0,0 +1,68 @@
+/*
+
+ Copyright (C) 2000,2003,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., 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
+
+*/
+
+
+
+/* Define to 1 if the elf64_getshdr function is in libelf.a */
+#undef HAVE_ELF64_GETSHDR
+
+/* Define to 1 if the elf64_getehdr function is in libelf.a */
+#undef HAVE_ELF64_GETEHDR
+
+
+/* see if __uint32_t is predefined in the compiler */
+#undef HAVE___UINT32_T
+
+/* see if __uint64_t is predefined in the compiler */
+#undef HAVE___UINT64_T
+
+/* Define 1 if sys/types.h defines __uint32_t */
+#undef HAVE___UINT32_T_IN_SYS_TYPES_H
+
+/* Define 1 if R_IA_64_DIR32LSB is defined (might be enum value) */
+#undef HAVE_R_IA_64_DIR32LSB
+
+/* Define 1 if sys/ia64/elf.h exists*/
+#undef HAVE_SYS_IA64_ELF_H
+
+/* Define 1 if want to build with 32/64bit section offsets for ia64 */
+/* per the dwarf2 committee proposal adopted Dec 1999 */
+#undef HAVE_DWARF2_99_EXTENSION
+
+/* Define 1 if want only 32bit section offsets per pure dwarf2.0.0 spec */
+/* Only one of HAVE_OLD_DWARF2_32BIT_OFFSET or HAVE_DWARF2_99_EXTENSION */
+/* may be defined */
+#undef HAVE_OLD_DWARF2_32BIT_OFFSET
+
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
new file mode 100644
index 0000000000..6cd4ff7445
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/cmplrs/dwarf_addr_finder.h
@@ -0,0 +1,55 @@
+/*
+ dwarf_addr_finder.h
+ $Source: /plroot/cmplrs.src/v7.4.2m/.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
new file mode 100644
index 0000000000..03a76150a0
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/config.h
@@ -0,0 +1,144 @@
+/* config.h. Generated by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+/*
+
+ Copyright (C) 2000,2003,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., 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
+
+*/
+
+
+
+/* Define to 1 if the elf64_getshdr function is in libelf.a */
+#define HAVE_ELF64_GETSHDR 1
+
+/* Define to 1 if the elf64_getehdr function is in libelf.a */
+#define HAVE_ELF64_GETEHDR 1
+
+
+/* see if __uint32_t is predefined in the compiler */
+/* #undef HAVE___UINT32_T */
+
+/* see if __uint64_t is predefined in the compiler */
+/* #undef HAVE___UINT64_T */
+
+/* Define 1 if sys/types.h defines __uint32_t */
+/* #undef HAVE___UINT32_T_IN_SYS_TYPES_H */
+
+/* Define 1 if R_IA_64_DIR32LSB is defined (might be enum value) */
+/* #undef HAVE_R_IA_64_DIR32LSB */
+
+/* Define 1 if sys/ia64/elf.h exists*/
+/* #undef HAVE_SYS_IA64_ELF_H */
+
+/* Define 1 if want to build with 32/64bit section offsets for ia64 */
+/* per the dwarf2 committee proposal adopted Dec 1999 */
+/* #undef HAVE_DWARF2_99_EXTENSION */
+
+/* Define 1 if want only 32bit section offsets per pure dwarf2.0.0 spec */
+/* Only one of HAVE_OLD_DWARF2_32BIT_OFFSET or HAVE_DWARF2_99_EXTENSION */
+/* may be defined */
+/* #undef HAVE_OLD_DWARF2_32BIT_OFFSET */
+
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <elfaccess.h> header file. */
+/* #undef HAVE_ELFACCESS_H */
+
+/* Define to 1 if you have the <elf.h> header file. */
+#define HAVE_ELF_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <libelf.h> header file. */
+#define HAVE_LIBELF_H 1
+
+/* Define to 1 if you have the <libelf/libelf.h> header file. */
+/* #undef HAVE_LIBELF_LIBELF_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <sgidefs.h> header file. */
+/* #undef HAVE_SGIDEFS_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/ia64/elf.h> header file. */
+/* #undef HAVE_SYS_IA64_ELF_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* 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 version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#if defined(__sparc)
+#define WORDS_BIGENDIAN 1
+#else
+#undef WORDS_BIGENDIAN
+#endif
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf.h b/usr/src/tools/ctf/dwarf/common/dwarf.h
new file mode 100644
index 0000000000..1b96ec9d69
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf.h
@@ -0,0 +1,721 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ 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
+
+*/
+
+
+#ifndef __DWARF_H
+#define __DWARF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ dwarf.h DWARF debugging information values
+ $Revision: 1.29 $ $Date: 2003/02/05 22:57:01 $
+
+ The comment "DWARF3" appears where there are
+ new entries from DWARF3.
+
+*/
+
+
+#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
+ /* Previous 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 */
+#define DW_TAG_mutable_type 0x3e /* DWARF3 */
+#define DW_TAG_lo_user 0x4080
+#define DW_TAG_MIPS_loop 0x4081
+#define DW_TAG_hi_user 0xffff
+
+/* The following 3 are GNU extensions
+ The TAG names are as if the extensions were dwarf standard,
+ not extensions.
+*/
+#define DW_TAG_format_label 0x4101 /* for FORTRAN 77, Fortran 90 */
+#define DW_TAG_function_template 0x4102 /* for C++ */
+#define DW_TAG_class_template 0x4103 /* for C++ */
+
+/* The following are SUN extensions */
+#define DW_TAG_SUN_function_template 0x4201
+#define DW_TAG_SUN_class_template 0x4202
+#define DW_TAG_SUN_struct_template 0x4203
+#define DW_TAG_SUN_union_template 0x4204
+#define DW_TAG_SUN_virtual_inheritance 0x4205
+#define DW_TAG_SUN_codeflags 0x4206
+#define DW_TAG_SUN_memop_info 0x4207
+#define DW_TAG_SUN_omp_child_func 0x4208
+
+/* 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 */
+
+#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_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_stride_size 0x2e
+#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_stride 0x51 /* DWARF3 */
+#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_lo_user 0x2000
+#define DW_AT_MIPS_fde 0x2001
+#define DW_AT_MIPS_loop_begin 0x2002
+#define DW_AT_MIPS_tail_loop_begin 0x2003
+#define DW_AT_MIPS_epilog_begin 0x2004
+#define DW_AT_MIPS_loop_unroll_factor 0x2005
+#define DW_AT_MIPS_software_pipeline_depth 0x2006
+#define DW_AT_MIPS_linkage_name 0x2007
+#define DW_AT_MIPS_stride 0x2008
+#define DW_AT_MIPS_abstract_name 0x2009
+#define DW_AT_MIPS_clone_origin 0x200a
+#define DW_AT_MIPS_has_inlines 0x200b
+#define DW_AT_MIPS_stride_byte 0x200c
+#define DW_AT_MIPS_stride_elem 0x200d
+#define DW_AT_MIPS_ptr_dopetype 0x200e
+#define DW_AT_MIPS_allocatable_dopetype 0x200f
+#define DW_AT_MIPS_assumed_shape_dopetype 0x2010
+#define DW_AT_MIPS_assumed_size 0x2011
+
+
+/* GNU extensions, currently not used in dwarf2 by egcs
+ Mostly dwarf1 extensions not needed in dwarf2?
+*/
+#define DW_AT_sf_names 0x2101
+#define DW_AT_src_info 0x2102
+#define DW_AT_mac_info 0x2103
+#define DW_AT_src_coords 0x2104
+#define DW_AT_body_begin 0x2105
+#define DW_AT_body_end 0x2106
+/* UPC extension */
+#define DW_AT_upc_threads_scaled 0x3210 /* UPC */
+
+/* Sun extensions */
+#define DW_AT_SUN_template 0x2201
+#define DW_AT_SUN_alignment 0x2202
+#define DW_AT_SUN_vtable 0x2203
+#define DW_AT_SUN_count_guarantee 0x2204
+#define DW_AT_SUN_command_line 0x2205
+#define DW_AT_SUN_vbase 0x2206
+#define DW_AT_SUN_compile_options 0x2207
+#define DW_AT_SUN_language 0x2208
+#define DW_AT_SUN_browser_file 0x2209
+#define DW_AT_SUN_vtable_abi 0x2210
+#define DW_AT_SUN_func_offsets 0x2211
+#define DW_AT_SUN_cf_kind 0x2212
+#define DW_AT_SUN_vtable_index 0x2213
+#define DW_AT_SUN_omp_tpriv_addr 0x2214
+#define DW_AT_SUN_omp_child_func 0x2215
+#define DW_AT_SUN_func_offset 0x2216
+#define DW_AT_SUN_memop_type_ref 0x2217
+#define DW_AT_SUN_profile_id 0x2218
+#define DW_AT_SUN_memop_signature 0x2219
+#define DW_AT_SUN_obj_dir 0x2220
+#define DW_AT_SUN_obj_file 0x2221
+#define DW_AT_SUN_original_name 0x2222
+
+
+#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_lo_user 0xe0
+#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_lo_user 0x80
+
+/* 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
+
+/* 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
+#define DW_ATCF_SUN_mop_bitfield 0x41
+#define DW_ATCF_SUN_mop_spill 0x42
+#define DW_ATCF_SUN_mop_scopy 0x43
+#define DW_ATCF_SUN_func_start 0x44
+#define DW_ATCF_SUN_end_ctors 0x45
+#define DW_ATCF_SUN_branch_target 0x46
+#define DW_ATCF_SUN_mop_stack_probe 0x47
+#define DW_ATCF_hi_user 0xff
+
+#define DW_ACCESS_public 1
+#define DW_ACCESS_protected 2
+#define DW_ACCESS_private 3
+
+#define DW_VIS_local 1
+#define DW_VIS_exported 2
+#define DW_VIS_qualified 3
+
+#define DW_VIRTUALITY_none 0
+#define DW_VIRTUALITY_virtual 1
+#define DW_VIRTUALITY_pure_virtual 2
+
+#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_lo_user 0x8000
+#define DW_LANG_Mips_Assembler 0x8001
+#define DW_LANG_Upc 0x8765 /* UPC */
+
+/* Sun extensions */
+#define DW_LANG_SUN_Assembler 0x9001
+
+#define DW_LANG_hi_user 0xffff
+
+
+#define DW_ID_case_sensitive 0
+#define DW_ID_up_case 1
+#define DW_ID_down_case 2
+#define DW_ID_case_insensitive 3
+
+#define DW_CC_normal 0x1
+#define DW_CC_program 0x2
+#define DW_CC_nocall 0x3
+#define DW_CC_lo_user 0x40
+#define DW_CC_hi_user 0xff
+
+#define DW_INL_not_inlined 0
+#define DW_INL_inlined 1
+#define DW_INL_declared_not_inlined 2
+#define DW_INL_declared_inlined 3
+
+#define DW_ORD_row_major 0
+#define DW_ORD_col_major 1
+
+#define DW_DSC_label 0
+#define DW_DSC_range 1
+
+#define DW_LNS_copy 1
+#define DW_LNS_advance_pc 2
+#define DW_LNS_advance_line 3
+#define DW_LNS_set_file 4
+#define DW_LNS_set_column 5
+#define DW_LNS_negate_stmt 6
+#define DW_LNS_set_basic_block 7
+#define DW_LNS_const_add_pc 8
+#define DW_LNS_fixed_advance_pc 9
+#define DW_LNS_set_prologue_end 10 /* DWARF3 */
+#define DW_LNS_set_epilogue_begin 11 /* DWARF3 */
+#define DW_LNS_set_isa 12 /* DWARF3 */
+
+#define DW_LNE_end_sequence 1
+#define DW_LNE_set_address 2
+#define DW_LNE_define_file 3
+#define DW_LNE_lo_user 128 /* DWARF3 */
+#define DW_LNE_hi_user 255 /* DWARF3 */
+
+#define DW_MACINFO_define 1
+#define DW_MACINFO_undef 2
+#define DW_MACINFO_start_file 3
+#define DW_MACINFO_end_file 4
+#define DW_MACINFO_vendor_ext 255
+
+#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_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_low_user 0x1c
+#define DW_CFA_MIPS_advance_loc8 0x1d
+
+/* the following two from egcs-1.1.2 */
+#define DW_CFA_GNU_window_save 0x2d
+#define DW_CFA_GNU_args_size 0x2e
+
+#define DW_CFA_high_user 0x3f
+
+
+/* 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 (simultaneously) 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.
+
+ Rule describes:
+*/
+#define DW_FRAME_CFA_COL 0 /* column used for CFA */
+#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 */
+
+#define DW_FRAME_RA_COL 64 /* column recording ra */
+
+#define DW_FRAME_STATIC_LINK 65 /* column recording static link*/
+ /* applicable to up-level */
+ /* addressing, as in mp code, */
+ /* pascal, etc */
+
+/* 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 */
+#define DW_FRAME_LAST_REG_NUM (DW_FRAME_STATIC_LINK + 1)
+
+
+/*
+ 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
new file mode 100644
index 0000000000..da051e6225
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.c
@@ -0,0 +1,248 @@
+/*
+
+ 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#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;
+ Dwarf_Small *abbrev_section_end;
+ Dwarf_Half attr;
+ Dwarf_Half attr_form;
+ Dwarf_Abbrev ret_abbrev;
+ Dwarf_Unsigned labbr_count = 0;
+ Dwarf_Unsigned utmp;
+
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (dbg->de_debug_abbrev == 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_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_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 + offset;
+ abbrev_section_end =
+ dbg->de_debug_abbrev + dbg->de_debug_abbrev_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_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ if (length != NULL)
+ *length = abbrev_ptr - dbg->de_debug_abbrev - 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);
+}
+
+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;
+ Dwarf_Byte_Ptr abbrev_end;
+ Dwarf_Byte_Ptr mark_abbrev_ptr;
+ Dwarf_Half attr;
+ Dwarf_Half attr_form;
+
+ 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 +
+ abbrev->ab_dbg->de_debug_abbrev_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;
+
+ *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
new file mode 100644
index 0000000000..f9ea435000
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_abbrev.h
@@ -0,0 +1,45 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+struct Dwarf_Abbrev_s {
+ Dwarf_Word ab_code;
+ Dwarf_Half ab_tag;
+ 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
new file mode 100644
index 0000000000..ba04a84916
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_addr_finder.c
@@ -0,0 +1,686 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#include <dwarf.h>
+#include <libdwarf.h>
+#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 <cmplrs/dwarf_addr_finder.h>
+#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, &ltag, &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;
+
+ 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
new file mode 100644
index 0000000000..ae94c8b355
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_alloc.c
@@ -0,0 +1,1122 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.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, 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.
+
+ If this is n32, we want the sizes to be 64-bit aligned
+ so that longlong in the structure we return to user
+ is aligned properly. Thus the _dw_fac of 2
+
+ Only long longs need to be properly aligned: we don't
+ have long double and don't align for that.
+
+*/
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+#define _DW_FAC 2
+#define _DW_PS sizeof(void *)
+#else
+#define _DW_FAC 1
+#define _DW_PS sizeof(void *)
+#endif
+#define _DW_RESERVE (_DW_FAC * _DW_PS)
+
+/* 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)
+#define BASE_ALLOC 64
+#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;
+};
+
+static const
+struct ial_s index_into_allocated[ALLOC_AREA_INDEX_TABLE_MAX] = {
+ {0, 1, 1}, /* none */
+ {0, 1, 1,}, /* 1 DW_DLA_STRING */
+ {1, sizeof(Dwarf_Loc), BASE_ALLOC}
+ , /* 2 DW_DLA_LOC */
+ {2, sizeof(Dwarf_Locdesc), BASE_ALLOC}
+ , /* 3 DW_DLA_LOCDESC */
+ {0, 1, 1}
+ , /* not used *//* 4 DW_DLA_ELLIST */
+ {0, 1, 1}
+ , /* not used *//* 5 DW_DLA_BOUNDS */
+ {3, sizeof(Dwarf_Block), BASE_ALLOC}
+ , /* 6 DW_DLA_BLOCK */
+ {0, 1, 1}
+ , /* the actual dwarf_debug structure *//* 7 DW_DLA_DEBUG */
+ {4, sizeof(struct Dwarf_Die_s), BIG_ALLOC}, /* 8 DW_DLA_DIE */
+ {5, sizeof(struct Dwarf_Line_s), BIG_ALLOC}, /* 9
+ DW_DLA_LINE */
+ {6, sizeof(struct Dwarf_Attribute_s), BIG_ALLOC * 2},
+ /* 10 DW_DLA_ATTR */
+ {0, 1, 1}, /* not used *//* 11 DW_DLA_TYPE */
+ {0, 1, 1}, /* not used *//* 12 DW_DLA_SUBSCR */
+ {7, sizeof(struct Dwarf_Global_s), BIG_ALLOC}, /* 13
+ DW_DLA_GLOBAL
+ */
+ {8, sizeof(struct Dwarf_Error_s), BASE_ALLOC}, /* 14
+ DW_DLA_ERROR
+ */
+ {0, 1, 1}, /* 15 DW_DLA_LIST */
+ {0, 1, 1}, /* not used *//* 16 DW_DLA_LINEBUF */
+ {9, sizeof(struct Dwarf_Arange_s), BASE_ALLOC}, /* 17
+ DW_DLA_ARANGE
+ */
+ {10, sizeof(struct Dwarf_Abbrev_s), BIG_ALLOC}, /* 18
+ DW_DLA_ABBREV
+ */
+ {11, sizeof(Dwarf_Frame_Op), BIG_ALLOC}
+ , /* 19 DW_DLA_FRAME_OP */
+ {12, sizeof(struct Dwarf_Cie_s), BASE_ALLOC}, /* 20
+ DW_DLA_CIE */
+ {13, sizeof(struct Dwarf_Fde_s), BASE_ALLOC}, /* 21
+ DW_DLA_FDE */
+ {0, 1, 1}, /* 22 DW_DLA_LOC_BLOCK */
+ {0, 1, 1}, /* 23 DW_DLA_FRAME_BLOCK */
+ {14, sizeof(struct Dwarf_Global_s), BIG_ALLOC}, /* 24
+ DW_DLA_FUNC */
+ {15, sizeof(struct Dwarf_Global_s), BIG_ALLOC}, /* 25
+ DW_DLA_TYPENAME
+ */
+ {16, sizeof(struct Dwarf_Global_s), BIG_ALLOC}, /* 26
+ DW_DLA_VAR */
+ {17, sizeof(struct Dwarf_Global_s), BASE_ALLOC}, /* 27
+ DW_DLA_WEAK */
+ {0, 1, 1}, /* 28 DW_DLA_ADDR */
+ {18, sizeof(struct Dwarf_Abbrev_List_s), BIG_ALLOC},
+ /* 29 DW_DLA_ABBREV_LIST */
+ {19, sizeof(struct Dwarf_Chain_s), BIG_ALLOC}, /* 30
+ DW_DLA_CHAIN
+ */
+ {20, sizeof(struct Dwarf_CU_Context_s), BASE_ALLOC},
+ /* 31 DW_DLA_CU_CONTEXT */
+ {21, sizeof(struct Dwarf_Frame_s), BASE_ALLOC}, /* 32
+ DW_DLA_FRAME
+ */
+ {22, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
+ /* 33 DW_DLA_GLOBAL_CONTEXT */
+ {23, sizeof(struct Dwarf_File_Entry_s), BASE_ALLOC},
+ /* 34 DW_DLA_FILE_ENTRY */
+ {24, sizeof(struct Dwarf_Line_Context_s), BASE_ALLOC},
+ /* 35 DW_DLA_LINE_CONTEXT */
+ {25, sizeof(struct Dwarf_Loc_Chain_s), BASE_ALLOC},
+ /* 36 DW_DLA_LOC_CHAIN */
+ {26, ABBREV_HASH_TABLE_SIZE * 2 * sizeof(Dwarf_Abbrev_List),
+ BASE_ALLOC}
+ ,
+ /* 37 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 are left in existence,
+ with unchanged numbers.
+*/
+ {27, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
+ /* 38 DW_DLA_FUNC_CONTEXT */
+ {28, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
+ /* 39 DW_DLA_TYPENAME_CONTEXT */
+ {29, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
+ /* 40 DW_DLA_VAR_CONTEXT */
+ {30, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC},
+ /* 41 DW_DLA_WEAK_CONTEXT */
+};
+
+#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, 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_ADDR) {
+ size = count *
+ (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
+ sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
+ } else if (alloc_type == DW_DLA_ERROR) {
+ return _dwarf_special_no_dbg_error_malloc();
+ } 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
+ return (_dwarf_find_memory(alloc_hdr));
+#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. */
+ return _dwarf_special_no_dbg_error_malloc();
+ } 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,
+ alloc_type);
+#endif
+ if (ret_mem != NULL)
+ memset(ret_mem,0, size);
+
+ 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.
+
+ 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 (alloc_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);
+ 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[alloc_type].ia_al_num;
+ /*
+ A string pointer may point into .debug_info or .debug_string.
+ Otherwise, they are directly malloc'ed. */
+ if (index == 0) {
+ if (alloc_type == DW_DLA_STRING) {
+ if ((Dwarf_Small *) space >= dbg->de_debug_info &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_info + dbg->de_debug_info_size)
+ return;
+
+ if (dbg->de_debug_line != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_line &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_line + dbg->de_debug_line_size)
+ return;
+
+ if (dbg->de_debug_pubnames != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_pubnames &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_pubnames + dbg->de_debug_pubnames_size)
+ return;
+
+ if (dbg->de_debug_frame != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_frame &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_frame + dbg->de_debug_frame_size)
+ return;
+
+ if (dbg->de_debug_str != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_str &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_str + dbg->de_debug_str_size)
+ return;
+
+ if (dbg->de_debug_funcnames != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_funcnames &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_funcnames + dbg->de_debug_funcnames_size)
+ return;
+
+ if (dbg->de_debug_typenames != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_typenames &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_typenames + dbg->de_debug_typenames_size)
+ return;
+
+ if (dbg->de_debug_varnames != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_varnames &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_varnames + dbg->de_debug_varnames_size)
+ return;
+
+ if (dbg->de_debug_weaknames != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_weaknames &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_weaknames + dbg->de_debug_weaknames_size)
+ return;
+
+ free(space);
+ return;
+ }
+
+ if (alloc_type == DW_DLA_LIST ||
+ alloc_type == DW_DLA_FRAME_BLOCK ||
+ alloc_type == DW_DLA_LOC_BLOCK ||
+ alloc_type == DW_DLA_ADDR) {
+
+ 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;
+
+ }
+
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_delete_from_list(dbg, space, alloc_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 %x %x area ptr %x\n",
+ (int) alloc_type,
+ (int) alloc_area->aa_alloc_hdr,
+ (int) alloc_hdr, (int) 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 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.
+
+
+
+
+*/
+/*
+** Set up all the Dwarf_Alloc_Hdr records.
+*/
+
+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_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"
+ };
+
+ 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 function is used to recursively
+ free 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
+
+/*
+ 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;
+
+ if (dbg == NULL)
+ return (DW_DLV_ERROR);
+
+#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;
+ dbg->de_simple_malloc_current = 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
+
+ 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)
+{
+}
+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_current) {
+ /* First entry to this routine. */
+ dbg->de_simple_malloc_current =
+ malloc(sizeof(struct simple_malloc_record_s));
+ if(!dbg->de_simple_malloc_current) {
+ return; /* no memory, give up */
+ }
+ memset(dbg->de_simple_malloc_current,
+ 0,
+ sizeof(struct simple_malloc_record_s));
+ dbg->de_simple_malloc_base = dbg->de_simple_malloc_current;
+ }
+ cur = dbg->de_simple_malloc_current;
+
+ 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) {
+ 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_current = 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 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).
+
+ 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
new file mode 100644
index 0000000000..4240d69d35
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_alloc.h
@@ -0,0 +1,167 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+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;
+
+#define ALLOC_AREA_INDEX_TABLE_MAX 42
+#define ALLOC_AREA_REAL_TABLE_MAX 31
+
+/*
+ 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
new file mode 100644
index 0000000000..f14f5daedc
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_arange.c
@@ -0,0 +1,623 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_arange.h"
+
+
+/*
+ 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)
+{
+ /* Sweeps the .debug_aranges section. */
+ Dwarf_Small *arange_ptr;
+
+ /*
+ Start of arange header. Used for rounding offset of arange_ptr
+ to twice the tuple size. Libdwarf requirement. */
+ Dwarf_Small *header_ptr;
+
+
+ /* Version of .debug_aranges header. */
+ Dwarf_Half version;
+
+ /* Offset of current set of aranges into .debug_info. */
+ Dwarf_Off info_offset;
+
+ /* Size in bytes of addresses in target. */
+ Dwarf_Small address_size;
+
+ /* Size in bytes of segment offsets in target. */
+ Dwarf_Small segment_size;
+
+ Dwarf_Small remainder;
+
+ /* Count of total number of aranges. */
+ Dwarf_Unsigned arange_count = 0;
+
+ /* Start address of arange. */
+ Dwarf_Addr range_address;
+
+ /* Length of arange. */
+ Dwarf_Unsigned range_length;
+
+ Dwarf_Arange arange, *arange_block;
+
+ Dwarf_Unsigned i;
+
+ /* Used to chain Dwarf_Aranges structs. */
+ Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
+
+ int res;
+
+ /* ***** 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_index,
+ &dbg->de_debug_aranges,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ arange_ptr = dbg->de_debug_aranges;
+ do {
+ /* Length of current set of aranges. */
+ Dwarf_Unsigned length;
+ Dwarf_Small *arange_ptr_past_end = 0;
+
+ int local_length_size;
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ int local_extension_size;
+
+ 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_size) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ address_size = *(Dwarf_Small *) arange_ptr;
+ if (address_size != dbg->de_pointer_size) {
+ /* Internal error of some kind */
+ _dwarf_error(dbg, error, DW_DLE_BADBITC);
+ return (DW_DLV_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);
+ }
+
+ /* Round arange_ptr offset to next multiple of address_size. */
+ remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
+ (2 * address_size);
+ if (remainder != 0) {
+ arange_ptr = arange_ptr + (2 * address_size) - remainder;
+ length = length - ((2 * address_size) - remainder);
+ }
+
+ do {
+ 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;
+
+ if (range_address != 0 || range_length != 0) {
+
+ 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_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;
+ }
+ }
+ } while (range_address != 0 || range_length != 0);
+
+ /* A compiler could emit some padding bytes here.
+ dwarf2/3 (dwarf3 draft8 sec 7.20) does not clearly make
+ extra padding bytes illegal. */
+ if(arange_ptr_past_end < arange_ptr) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ /* 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 + dbg->de_debug_aranges_size);
+
+ if (arange_ptr !=
+ dbg->de_debug_aranges + dbg->de_debug_aranges_size) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ 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)
+{
+ /* Sweeps the .debug_aranges section. */
+ Dwarf_Small *arange_ptr;
+ Dwarf_Small *arange_start_ptr;
+
+ /*
+ Start of arange header. Used for rounding offset of arange_ptr
+ to twice the tuple size. Libdwarf requirement. */
+ Dwarf_Small *header_ptr;
+
+ /* Length of current set of aranges. */
+ Dwarf_Unsigned length;
+
+ /* Version of .debug_aranges header. */
+ Dwarf_Half version;
+
+ /* Offset of current set of aranges into .debug_info. */
+ Dwarf_Off info_offset;
+
+ /* Size in bytes of addresses in target. */
+ Dwarf_Small address_size;
+
+ /* Size in bytes of segment offsets in target. */
+ Dwarf_Small segment_size;
+
+ Dwarf_Small remainder;
+
+ /* Count of total number of aranges. */
+ Dwarf_Unsigned arange_count = 0;
+
+ /* Start address of arange. */
+ Dwarf_Addr range_address;
+
+ /* Length of arange. */
+ Dwarf_Unsigned range_length;
+
+ Dwarf_Arange arange;
+
+ Dwarf_Unsigned i;
+
+ /* Used to chain Dwarf_Aranges structs. */
+ Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
+
+ Dwarf_Addr *arange_addrs;
+ Dwarf_Off *arange_offsets;
+
+ int res;
+
+ /* ***** 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_index,
+ &dbg->de_debug_aranges,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ arange_ptr = dbg->de_debug_aranges;
+ do {
+ int local_length_size;
+ /*REFERENCED*/ /* not used in this instance of the macro */
+ int local_extension_size;
+
+ 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);
+
+
+ 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_size) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ address_size = *(Dwarf_Small *) arange_ptr;
+ 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);
+ }
+
+ /* Round arange_ptr offset to next multiple of address_size. */
+ remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
+ (2 * address_size);
+ if (remainder != 0) {
+ arange_ptr = arange_ptr + (2 * address_size) - remainder;
+ length = length - ((2 * address_size) - remainder);
+ }
+
+ do {
+ arange_start_ptr = arange_ptr;
+ READ_UNALIGNED(dbg, range_address, Dwarf_Addr,
+ arange_ptr, dbg->de_pointer_size);
+ arange_ptr += dbg->de_pointer_size;
+ length = length - dbg->de_pointer_size;
+
+ READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned,
+ arange_ptr, local_length_size);
+ arange_ptr += local_length_size;
+ length = length - local_length_size;
+
+ if (range_address != 0 || range_length != 0) {
+
+ 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_address = range_address;
+ arange->ar_length = range_length;
+ arange->ar_info_offset =
+ arange_start_ptr - dbg->de_debug_aranges;
+ 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;
+ }
+ }
+ } while (range_address != 0 || range_length != 0);
+
+ if (length != 0) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ } while (arange_ptr <
+ dbg->de_debug_aranges + dbg->de_debug_aranges_size);
+
+ if (arange_ptr !=
+ dbg->de_debug_aranges + dbg->de_debug_aranges_size) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ 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;
+ Dwarf_Unsigned i;
+
+ 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;
+ Dwarf_Off offset;
+
+ 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) {
+ 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.
+*/
+int
+dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
+ Dwarf_Off * cu_header_offset_returned,
+ Dwarf_Error * error)
+{
+ if (arange == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *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.
+*/
+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) {
+ 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
new file mode 100644
index 0000000000..3ea1fe1416
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_arange.h
@@ -0,0 +1,63 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+/* This structure is used to read an arange into. */
+struct Dwarf_Arange_s {
+
+ /* 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;
+};
+
+
+
+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
new file mode 100644
index 0000000000..a956c3c57b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_base_types.h
@@ -0,0 +1,107 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "libdwarfdefs.h"
+
+#define true 1
+#define false 0
+
+/* to identify a cie */
+#define DW_CIE_ID ~(0x0)
+#define DW_CIE_VERSION 1
+#define ABBREV_HASH_TABLE_SIZE 10
+
+
+/*
+ These are allocation type codes for structs that
+ are internal to the Libdwarf Consumer library.
+*/
+#define DW_DLA_ABBREV_LIST DW_DLA_ADDR + 1
+#define DW_DLA_CHAIN DW_DLA_ADDR + 2
+#define DW_DLA_CU_CONTEXT DW_DLA_ADDR + 3
+#define DW_DLA_FRAME DW_DLA_ADDR + 4
+#define DW_DLA_GLOBAL_CONTEXT DW_DLA_ADDR + 5
+#define DW_DLA_FILE_ENTRY DW_DLA_ADDR + 6
+#define DW_DLA_LINE_CONTEXT DW_DLA_ADDR + 7
+#define DW_DLA_LOC_CHAIN DW_DLA_ADDR + 8
+#define DW_DLA_HASH_TABLE DW_DLA_ADDR + 9
+#define DW_DLA_FUNC_CONTEXT DW_DLA_ADDR + 10
+#define DW_DLA_TYPENAME_CONTEXT DW_DLA_ADDR + 11
+#define DW_DLA_VAR_CONTEXT DW_DLA_ADDR + 12
+#define DW_DLA_WEAK_CONTEXT DW_DLA_ADDR + 13
+
+/* Maximum number of allocation types for allocation routines. */
+#define MAX_DW_DLA DW_DLA_WEAK_CONTEXT
+
+/*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 __uint32_t Dwarf_ufixed64;
+typedef __int32_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_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
new file mode 100644
index 0000000000..e87a3640a2
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.c
@@ -0,0 +1,765 @@
+/*
+
+ Copyright (C) 2000,2001,2002,2003 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#include <stdio.h>
+#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;
+
+ 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;
+
+ 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;
+ Dwarf_Unsigned length;
+ Dwarf_Signed abbrev_offset;
+ Dwarf_Byte_Ptr cu_ptr;
+ int local_extension_size = 0;
+ int local_length_size;
+
+ 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 + 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_size)) {
+
+ _dwarf_error(dbg, error, DW_DLE_CU_LENGTH_ERROR);
+ return (NULL);
+ }
+
+ if (cu_context->cc_address_size != dbg->de_pointer_size) {
+ _dwarf_error(dbg, error, DW_DLE_CU_ADDRESS_SIZE_BAD);
+ return (NULL);
+ }
+
+ if (cu_context->cc_version_stamp != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (NULL);
+ }
+
+ if (abbrev_offset >= dbg->de_debug_abbrev_size) {
+ _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.
+*/
+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)
+{
+ /* Offset for current and new CU. */
+ Dwarf_Unsigned new_offset;
+
+ /* CU Context for current CU. */
+ Dwarf_CU_Context cu_context;
+
+ /* ***** 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) {
+ 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_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;
+
+ 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.
+*/
+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;
+ Dwarf_Byte_Ptr abbrev_ptr;
+ Dwarf_Word abbrev_code;
+ Dwarf_Abbrev_List abbrev_list;
+ Dwarf_Half attr;
+ Dwarf_Half attr_form;
+ Dwarf_Unsigned offset;
+ Dwarf_Word leb128_length;
+ Dwarf_Unsigned utmp;
+ Dwarf_Debug dbg;
+
+ 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;
+
+ /* READ_UNALIGNED does update 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(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;
+ default:
+ return (NULL);
+ }
+
+ /* Reset *has_die_child to indicate children skipped. */
+ *has_die_child = false;
+
+ if (cu_info_start + offset > die_info_end) {
+ return (NULL);
+ } else {
+ return (cu_info_start + offset);
+ }
+ }
+
+ if (attr_form != 0) {
+ info_ptr += _dwarf_get_size_of_val(cu_context->cc_dbg,
+ attr_form, info_ptr,
+ cu_context->
+ cc_length_size);
+ if (info_ptr > die_info_end) {
+ 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;
+ Dwarf_Byte_Ptr die_info_ptr;
+ Dwarf_Byte_Ptr cu_info_start = 0;
+ Dwarf_Byte_Ptr die_info_end = 0;
+ Dwarf_Half abbrev_code;
+ Dwarf_Unsigned utmp;
+
+
+ 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 +
+ off2 + _dwarf_length_of_cu_header(dbg, off2);
+ } else {
+ /* Find sibling die. */
+ Dwarf_Bool has_child;
+ Dwarf_Sword child_depth;
+
+ /* 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 +
+ 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);
+ }
+
+ if ((*die_info_ptr) == 0 && has_child) {
+ die_info_ptr++;
+ has_child = false;
+ }
+
+ if ((*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);
+ }
+
+ 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_Half) utmp;
+ if (abbrev_code == 0) {
+ /* Zero means a null DIE */
+ return (DW_DLV_NO_ENTRY);
+ }
+ 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_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;
+ Dwarf_Byte_Ptr die_info_end;
+ Dwarf_Die ret_die;
+ Dwarf_Bool has_die_child;
+ Dwarf_Debug dbg;
+ Dwarf_Half abbrev_code;
+ Dwarf_Unsigned utmp;
+
+
+ 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 +
+ 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_Half) 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;
+ return DW_DLV_NO_ENTRY;
+ }
+ ret_die->di_abbrev_list =
+ _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code);
+ if (ret_die->di_abbrev_list == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ *caller_ret_die = ret_die;
+ return (DW_DLV_OK);
+}
+
+/*
+ Given a 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;
+ Dwarf_Off new_cu_offset = 0;
+ Dwarf_Die die;
+ Dwarf_Byte_Ptr info_ptr;
+ Dwarf_Half abbrev_code;
+ Dwarf_Unsigned utmp;
+
+ 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_cu_context_list_end != NULL)
+ new_cu_offset =
+ dbg->de_cu_context_list_end->cc_debug_info_offset +
+ dbg->de_cu_context_list_end->cc_length +
+ dbg->de_cu_context_list_end->cc_length_size +
+ dbg->de_cu_context_list_end->cc_extension_size;
+
+ do {
+ if ((new_cu_offset +
+ _dwarf_length_of_cu_header_simple(dbg)) >=
+ dbg->de_debug_info_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 + offset;
+ die->di_debug_info_ptr = info_ptr;
+ DECODE_LEB128_UWORD(info_ptr, utmp)
+ abbrev_code = (Dwarf_Half) utmp;
+ if (abbrev_code == 0) {
+ /* we are at a null DIE (or there is a bug). */
+ *new_die = 0;
+ return DW_DLV_NO_ENTRY;
+ }
+
+ die->di_abbrev_list =
+ _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
+ if (die->di_abbrev_list == NULL) {
+ _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
new file mode 100644
index 0000000000..58548f7897
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_die_deliv.h
@@ -0,0 +1,56 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+/*
+ 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_Word 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_error.c b/usr/src/tools/ctf/dwarf/common/dwarf_error.c
new file mode 100644
index 0000000000..fd0c922d3e
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_error.c
@@ -0,0 +1,378 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+/* 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)",
+
+
+
+};
+
+
+
+
+/*
+ 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
new file mode 100644
index 0000000000..49096785e7
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/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., 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
+
+*/
+
+
+
+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
new file mode 100644
index 0000000000..2bdf7ebedf
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_form.c
@@ -0,0 +1,694 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#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;
+
+ 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);
+}
+
+int
+dwarf_whatform(Dwarf_Attribute attr,
+ Dwarf_Half * return_form, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context;
+
+ 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;
+
+ 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;
+}
+
+
+/*
+ DW_FORM_ref_addr is considered an incorrect form
+ for this call because this function returns an
+ offset within the local CU thru the pointer.
+
+ DW_FORM_ref_addr has a value which is an address-size value which
+ is a global-offset into the debug_info section.
+ A DW_FORM_ref_addr cannot be returned by this interface:
+ see dwarf_global_formref();
+
+*/
+int
+dwarf_formref(Dwarf_Attribute attr,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+ Dwarf_Unsigned offset;
+ Dwarf_CU_Context cu_context;
+
+
+ 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;
+}
+
+/*
+ Since this returns section-relative debug_info offsets,
+ this can represent all REFERENCE forms correctly
+ and allows all forms.
+
+*/
+int
+dwarf_global_formref(Dwarf_Attribute attr,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+ Dwarf_Unsigned offset;
+ Dwarf_Addr ref_addr;
+ Dwarf_CU_Context cu_context;
+
+ 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;
+ 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;
+
+ case DW_FORM_ref_addr:
+ /* This offset is defined to be debug_info global already, so
+ use this value unaltered. */
+ READ_UNALIGNED(dbg, ref_addr, Dwarf_Addr,
+ attr->ar_debug_info_ptr,
+ cu_context->cc_length_size);
+ offset = ref_addr;
+ 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. */
+
+ *ret_offset = (offset);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_formaddr(Dwarf_Attribute attr,
+ Dwarf_Addr * return_addr, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+ Dwarf_Addr ret_addr;
+ Dwarf_CU_Context cu_context;
+
+ 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, dbg->de_pointer_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;
+
+ 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) {
+ *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;
+ Dwarf_Debug dbg;
+ Dwarf_CU_Context cu_context;
+
+ 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;
+
+ 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;
+ }
+
+ 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;
+ Dwarf_Debug dbg;
+ Dwarf_CU_Context cu_context;
+
+ 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;
+
+ case DW_FORM_data2:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ 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_Unsigned,
+ attr->ar_debug_info_ptr,
+ sizeof(Dwarf_sfixed));
+ *return_sval = (Dwarf_Sword) ret_value;
+ return DW_DLV_OK;
+ }
+
+ case DW_FORM_data8:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ 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;
+ Dwarf_Debug dbg;
+ Dwarf_Unsigned length;
+ Dwarf_Small *data;
+ Dwarf_Word leb128_length;
+ Dwarf_Block *ret_block;
+
+ 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 + 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;
+
+
+ *return_block = ret_block;
+ return (DW_DLV_OK);
+}
+
+
+int
+dwarf_formstring(Dwarf_Attribute attr,
+ char **return_str, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context;
+ Dwarf_Debug dbg;
+ Dwarf_Unsigned offset;
+ int res;
+
+ 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 +
+ 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_index,
+ &dbg->de_debug_str, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ *return_str = (char *) (dbg->de_debug_str + offset);
+ return DW_DLV_OK;
+ }
+
+ _dwarf_error(dbg, error, DW_DLE_ATTR_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
new file mode 100644
index 0000000000..be671d6639
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_frame.c
@@ -0,0 +1,2448 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_frame.h"
+#include "dwarf_arange.h" /* using Arange as a way to build a
+ list */
+
+
+static 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_length,
+ Dwarf_Unsigned cie_id_value,
+ int use_gnu_cie_calc,
+ Dwarf_Error * error);
+
+/*
+ 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.
+*/
+static int
+_dwarf_exec_frame_instr(Dwarf_Bool make_instr, /* Make list of frame
+ instr? */
+ Dwarf_Frame_Op ** ret_frame_instr, /* Ptr
+ to
+ list
+ of
+ ptrs
+ to
+ fr
+ instrs
+ */
+ Dwarf_Bool search_pc, /* Search for a pc
+ value? */
+ Dwarf_Addr search_pc_val, /* Search for
+ this pc
+ value */
+ Dwarf_Addr loc, /* initial location value */
+ Dwarf_Small * start_instr_ptr, /* Ptr to start
+ of frame
+ instrs. */
+ Dwarf_Small * final_instr_ptr, /* Ptr just
+ past frame
+ instrs. */
+ Dwarf_Frame table, /* Ptr to struct with
+ last row. */
+ Dwarf_Cie cie, /* Ptr to Cie used by the Fde.
+ */
+ Dwarf_Debug dbg, /* Associated
+ Dwarf_Debug */
+ Dwarf_Sword * returned_count,
+ int *returned_error)
+{
+ /* Sweeps the frame instructions. */
+ Dwarf_Small *instr_ptr;
+
+ /* Obvious from the documents. */
+ Dwarf_Small instr, opcode;
+ Dwarf_Small reg_no, reg_noA, reg_noB;
+ Dwarf_Unsigned factored_N_value;
+ Dwarf_Addr new_loc; /* must be min de_pointer_size bytes */
+ Dwarf_Unsigned adv_loc; /* must be min de_pointer_size bytes
+ and must be at least sizeof
+ Dwarf_ufixed */
+
+ struct Dwarf_Reg_Rule_s reg[DW_FRAME_LAST_REG_NUM];
+
+
+ /* This is used to end executing frame instructions. */
+ /* Becomes true when search_pc is true and 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;
+
+ /* 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;
+ Dwarf_Half fp_register;
+ 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;
+ 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 */
+ struct Dwarf_Reg_Rule_s *t1reg;
+ struct Dwarf_Reg_Rule_s *t1end;
+ struct Dwarf_Reg_Rule_s *t2reg;
+
+
+ t1reg = reg;
+ t1end = t1reg + DW_FRAME_LAST_REG_NUM;
+ if (cie != NULL && cie->ci_initial_table != NULL) {
+ t2reg = cie->ci_initial_table->fr_reg;
+ for (; t1reg < t1end; t1reg++, t2reg++) {
+ *t1reg = *t2reg;
+ }
+ } else { /* initialize with same_value */
+ for (; t1reg < t1end; t1reg++) {
+ t1reg->ru_is_off = 0;
+ t1reg->ru_register = DW_FRAME_SAME_VAL;
+ t1reg->ru_offset = 0;
+ }
+ }
+
+ /*
+ 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)) {
+
+
+ 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) {
+
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ adv_pc = adv_pc * code_alignment_factor;
+
+ search_over = search_pc &&
+ (loc + adv_pc > search_pc_val);
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over)
+ loc = loc + adv_pc;
+ break;
+ }
+
+ case DW_CFA_offset:{ /* base op */
+ reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = DW_DLE_DF_REG_NUM_TOO_HIGH;
+ return DW_DLV_ERROR;
+ }
+
+ 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) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+
+ reg[reg_no].ru_is_off = 1;
+ reg[reg_no].ru_register = DW_FRAME_CFA_COL;
+ reg[reg_no].ru_offset = factored_N_value *
+ data_alignment_factor;
+
+ break;
+ }
+
+ case DW_CFA_restore:{ /* base op */
+ reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+ fp_register = reg_no;
+
+ if (cie != NULL && cie->ci_initial_table != NULL)
+ reg[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
+ else if (!make_instr) {
+ *returned_error = (DW_DLE_DF_MAKE_INSTR_NO_INIT);
+ return DW_DLV_ERROR;
+ }
+
+ break;
+ }
+ case DW_CFA_set_loc:{
+ READ_UNALIGNED(dbg, new_loc, Dwarf_Addr,
+ instr_ptr, dbg->de_pointer_size);
+ instr_ptr += dbg->de_pointer_size;
+ if (new_loc <= loc) {
+ *returned_error = (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC);
+ return DW_DLV_ERROR;
+ }
+
+ search_over = search_pc && (new_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over)
+ 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) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ adv_loc *= code_alignment_factor;
+
+ search_over = search_pc &&
+ (loc + adv_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over)
+ loc = 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) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ adv_loc *= code_alignment_factor;
+
+ search_over = search_pc &&
+ (loc + adv_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over)
+ loc = 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) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ adv_loc *= code_alignment_factor;
+
+ search_over = search_pc &&
+ (loc + adv_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over)
+ loc = loc + adv_loc;
+ break;
+ }
+
+ case DW_CFA_offset_extended:{
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg)
+ reg_no = (Dwarf_Small) lreg;
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ reg[reg_no].ru_is_off = 1;
+ reg[reg_no].ru_register = DW_FRAME_CFA_COL;
+ reg[reg_no].ru_offset = 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 = (Dwarf_Small) lreg;
+
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+ if (cie != NULL && cie->ci_initial_table != NULL) {
+ reg[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
+ } else {
+ if (!make_instr) {
+ *returned_error =
+ (DW_DLE_DF_MAKE_INSTR_NO_INIT);
+ return DW_DLV_ERROR;
+ }
+ }
+
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_undefined:{
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg)
+ reg_no = (Dwarf_Small) lreg;
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+ reg[reg_no].ru_is_off = 0;
+ reg[reg_no].ru_register = DW_FRAME_UNDEFINED_VAL;
+ reg[reg_no].ru_offset = 0;
+
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_same_value:{
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg)
+ reg_no = (Dwarf_Small) lreg;
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+ reg[reg_no].ru_is_off = 0;
+ reg[reg_no].ru_register = DW_FRAME_SAME_VAL;
+ reg[reg_no].ru_offset = 0;
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_register:{
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg)
+ reg_noA = (Dwarf_Small) lreg;
+
+ if (reg_noA > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg)
+ reg_noB = (Dwarf_Small) lreg;
+
+ if (reg_noB > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+
+ reg[reg_noA].ru_is_off = 0;
+ reg[reg_noA].ru_register = reg_noB;
+
+ reg[reg_noA].ru_offset = 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) {
+ *returned_error = (DW_DLE_DF_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+
+ for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
+ stack_table->fr_reg[i] = reg[i];
+
+ if (top_stack != NULL)
+ stack_table->fr_next = top_stack;
+ top_stack = stack_table;
+
+ break;
+ }
+
+ case DW_CFA_restore_state:{
+ if (top_stack == NULL) {
+ *returned_error = (DW_DLE_DF_POP_EMPTY_STACK);
+ return DW_DLV_ERROR;
+ }
+ stack_table = top_stack;
+ top_stack = stack_table->fr_next;
+
+ for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
+ reg[i] = stack_table->fr_reg[i];
+
+ 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 = (Dwarf_Small) lreg;
+
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return (DW_DLV_ERROR);
+ }
+
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ reg[DW_FRAME_CFA_COL].ru_is_off = 1;
+ reg[DW_FRAME_CFA_COL].ru_register = reg_no;
+ reg[DW_FRAME_CFA_COL].ru_offset = 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 = (Dwarf_Small) lreg;
+
+ if (reg_no > DW_FRAME_LAST_REG_NUM) {
+ *returned_error = (DW_DLE_DF_REG_NUM_TOO_HIGH);
+ return DW_DLV_ERROR;
+ }
+
+ reg[DW_FRAME_CFA_COL].ru_is_off = 0;
+ reg[DW_FRAME_CFA_COL].ru_register = reg_no;
+ reg[DW_FRAME_CFA_COL].ru_offset = 0;
+ 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) {
+ *returned_error = (DW_DLE_DF_NO_CIE_AUGMENTATION);
+ return DW_DLV_ERROR;
+ }
+ reg[DW_FRAME_CFA_COL].ru_offset = factored_N_value;
+
+ fp_offset = factored_N_value;
+ break;
+ }
+
+ case DW_CFA_nop:{
+ break;
+ }
+
+#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 = (Dwarf_Small) lreg;
+
+ break;
+ }
+#endif
+ }
+
+ if (make_instr) {
+ instr_count++;
+
+ curr_instr = (Dwarf_Frame_Op *)
+ _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1);
+ if (curr_instr == NULL) {
+ *returned_error = (DW_DLE_DF_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+
+ 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) {
+ *returned_error = (DW_DLE_DF_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+
+ 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) {
+ *returned_error = (DW_DLE_DF_FRAME_DECODING_ERROR);
+ return DW_DLV_ERROR;
+ }
+
+ /* Create the last row generated. */
+ if (table != NULL) {
+ t1reg = reg;
+ t1end = t1reg + DW_FRAME_LAST_REG_NUM;
+ table->fr_loc = loc;
+ t2reg = table->fr_reg;
+ for (; t1reg < t1end; t1reg++, t2reg++) {
+ *t2reg = *t1reg;
+ }
+ }
+
+ /* 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) {
+ *returned_error = DW_DLE_DF_ALLOC_FAIL;
+ return DW_DLV_ERROR;
+ }
+
+ /*
+ 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;
+ }
+ return DW_DLV_OK;
+}
+
+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;
+}
+
+/*
+ * This function expects as input a pointer to Dwarf_Debug (dbg) and a
+ * a pointer to Cie. It finds the augmentation string and returns after
+ * setting *augmentation to point to it.
+ */
+static int
+get_augmentation_string(Dwarf_Debug dbg,
+ Dwarf_Small * cie_ptr,
+ Dwarf_Unsigned cie_id_value,
+ Dwarf_Small ** augmentation,
+ Dwarf_Error * error)
+{
+ Dwarf_Unsigned cie_id; /* must be min de_length_size bytes in
+ size */
+ Dwarf_Small version;
+ int local_length_size;
+ Dwarf_Unsigned length;
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ int local_extension_size;
+
+
+ /* READ_AREA_LENGTH updates cie_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ cie_ptr, local_length_size, local_extension_size);
+
+
+
+ /* Read the Cie Id field. */
+ READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
+ cie_ptr, local_length_size);
+ SIGN_EXTEND(cie_id, local_length_size);
+ if (cie_id != cie_id_value) {
+ /* 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 */
+ _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
+ return (DW_DLV_ERROR);
+ }
+ cie_ptr += local_length_size;
+
+
+ /* Read the version. */
+ version = *(Dwarf_Small *) cie_ptr;
+ cie_ptr++;
+ if (version != DW_CIE_VERSION) {
+ _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* At this point, cie_ptr is pointing at the augmentation string. */
+ *augmentation = cie_ptr;
+ return DW_DLV_OK;
+}
+
+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;
+
+}
+
+/*
+ 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;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_frame_eh_gnu_index,
+ &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,
+ dbg->de_debug_frame_size_eh_gnu,
+ /* 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;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_frame_index,
+ &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,
+ dbg->de_debug_frame_size,
+ DW_CIE_ID,
+ /* use_gnu_cie_calc= */ 0,
+ error);
+ return res;
+}
+
+static 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_length,
+ Dwarf_Unsigned cie_id_value,
+ int use_gnu_cie_calc, Dwarf_Error * error)
+{
+ /* Scans the debug_frame section. */
+ Dwarf_Small *frame_ptr = 0;
+
+ /* Points to the start of the current Fde or Cie. */
+ Dwarf_Small *start_frame_ptr = 0;
+
+ /* Points to the start of the augmented entries of Fde or Cie. */
+ Dwarf_Small *saved_frame_ptr = 0;
+
+ /* Fields for the current Cie being read. */
+ Dwarf_Unsigned length = 0; /* READ_UNALIGNED needs min
+ de_length_size byte dest */
+ Dwarf_Unsigned cie_base_offset = 0; /* needs to be min
+ de_length_size byte dest */
+ Dwarf_Unsigned cie_id;
+ Dwarf_Small version = 0;
+ Dwarf_Small *augmentation = 0;
+ Dwarf_Word code_alignment_factor = 4;
+ Dwarf_Sword data_alignment_factor = -1;
+ Dwarf_Small return_address_register = 31;
+ Dwarf_Word length_of_augmented_fields = 0;
+
+ /*
+ New_cie points to the Cie being read, and head_cie_ptr and
+ cur_cie_ptr are used for chaining them up in sequence. */
+ Dwarf_Cie new_cie;
+ Dwarf_Cie head_cie_ptr = NULL;
+ Dwarf_Cie cur_cie_ptr;
+ Dwarf_Word cie_count = 0;
+
+ /*
+ Points to a list of contiguous pointers to Dwarf_Cie
+ structures. */
+ Dwarf_Cie *cie_list_ptr;
+
+ /* Fields for the current Fde being read. */
+ Dwarf_Addr initial_location; /* must be min de_pointer_size
+ bytes in size */
+ Dwarf_Addr address_range; /* must be min de_pointer_size bytes in
+ size */
+
+ /*
+ New_fde points to the current Fde being read, and head_fde_ptr
+ and cur_fde_ptr are used to chain them up. */
+ Dwarf_Fde new_fde;
+ Dwarf_Fde head_fde_ptr = NULL;
+ Dwarf_Fde cur_fde_ptr;
+ Dwarf_Word fde_count = 0;
+
+ /*
+ Points to a list of contiguous pointers to Dwarf_Fde
+ structures. */
+ Dwarf_Fde *fde_list_ptr;
+
+ /*
+ Is used to check the offset field in the Fde by checking for a
+ Cie at this address. */
+ Dwarf_Small *fde_cie_ptr;
+
+ Dwarf_Word leb128_length;
+ Dwarf_Word i, j;
+ int res;
+ Dwarf_Word last_cie_index;
+
+
+ Dwarf_Small *prev_augmentation_cie_ptr = 0;
+ Dwarf_Small *prev_augmentation_ptr = 0;
+
+
+ frame_ptr = section_ptr;
+
+ if (frame_ptr == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+
+ while (frame_ptr < section_ptr + section_length) {
+ Dwarf_Small *cie_ptr_addr = 0;
+ int local_extension_size = 0;
+ int local_length_size = 0;
+
+ start_frame_ptr = frame_ptr;
+
+ /* 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 % local_length_size != 0) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ 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. */
+ break;
+ }
+
+ cie_ptr_addr = frame_ptr;
+ READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
+ frame_ptr, local_length_size);
+ SIGN_EXTEND(cie_id, local_length_size);
+ cie_base_offset = cie_id; /* if this is a CIE, this is
+ ignored. If it is an FDE,
+ this is the section offset
+ that allows us to get to the
+ cie of this fde. Save it for
+ the fde part of the 'if'
+ below */
+
+ frame_ptr += local_length_size;
+
+ if (cie_id == cie_id_value) {
+ /* 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 */
+
+
+
+ /* this is a CIE, Common Information Entry: See the dwarf
+ spec, section 6.4.1 */
+ version = *(Dwarf_Small *) frame_ptr;
+ frame_ptr++;
+ if (version != DW_CIE_VERSION) {
+ _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;
+ if ((strcmp((char *) augmentation,
+ DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
+ (strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
+
+ Dwarf_Unsigned lreg;
+
+ 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_Small *) frame_ptr;
+ if (return_address_register > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(dbg, error,
+ DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ frame_ptr++;
+ } else if (augmentation[0] == 'z') {
+ /* The augmentation starts with a known prefix. See the
+ dwarf_frame.h for details on the layout. */
+
+ Dwarf_Unsigned lreg;
+
+ 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_Small *) frame_ptr;
+ if (return_address_register > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(dbg, error,
+ DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ frame_ptr++;
+
+ /* 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;
+ } else if (0 == strcmp((const char *) augmentation, "eh")) {
+
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ 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;
+
+ code_alignment_factor =
+ (Dwarf_Word) _dwarf_decode_s_leb128(frame_ptr,
+ &leb128_length);
+ frame_ptr = frame_ptr + leb128_length;
+
+
+ data_alignment_factor =
+ (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
+ &leb128_length);
+
+ frame_ptr = frame_ptr + leb128_length;
+
+ return_address_register = *(Dwarf_Small *) frame_ptr;
+ if (return_address_register > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(dbg, error,
+ DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ frame_ptr++;
+
+ } else {
+ /* We do not understand the augmentation string. No
+ assumption can be made about any fields other than
+ what we have already read. */
+ frame_ptr = start_frame_ptr + length + local_length_size
+ + 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. */
+ }
+
+ 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_initial_table = NULL;
+ new_cie->ci_length = (Dwarf_Word) length;
+ new_cie->ci_length_size = local_length_size;
+ new_cie->ci_extension_size = 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 = start_frame_ptr;
+ new_cie->ci_cie_instr_start = frame_ptr;
+ new_cie->ci_dbg = dbg;
+
+ cie_count++;
+ if (head_cie_ptr == NULL)
+ head_cie_ptr = cur_cie_ptr = new_cie;
+ else {
+ cur_cie_ptr->ci_next = new_cie;
+ cur_cie_ptr = new_cie;
+ }
+ } else {
+
+
+
+ /* this is an FDE, Frame Description Entry, see the Dwarf
+ Spec, section 6.4.1 */
+ Dwarf_Small *cieptr;
+
+ 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;
+
+ READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
+ frame_ptr, dbg->de_pointer_size);
+ frame_ptr += dbg->de_pointer_size;
+
+ READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
+ frame_ptr, dbg->de_pointer_size);
+ frame_ptr += dbg->de_pointer_size;
+ /* Get the augmentation string from Cie to identify the
+ layout of this Fde. */
+ 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_base_offset to look *as if* it was from real
+ dwarf. */
+ cieptr = cie_ptr_addr - cie_base_offset;
+ cie_base_offset = cieptr - section_ptr;
+ } else {
+ /* Traditional dwarf section offset is in cie_id */
+ cieptr =
+ (Dwarf_Small *) (section_ptr + cie_base_offset);
+ }
+
+
+ if (prev_augmentation_cie_ptr == cieptr &&
+ prev_augmentation_ptr != NULL) {
+ augmentation = prev_augmentation_ptr;
+ } else {
+ res = get_augmentation_string(dbg,
+ cieptr,
+ cie_id_value,
+ &augmentation, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ prev_augmentation_cie_ptr = cieptr;
+ prev_augmentation_ptr = augmentation;
+ }
+ if ((strcmp((char *) augmentation,
+ DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
+ (strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
+ /* We are pointing at the start of instructions. Do
+ nothing. */
+ } else if (augmentation[0] == 'z') {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(frame_ptr, lreg)
+ length_of_augmented_fields = (Dwarf_Word) lreg;
+
+ saved_frame_ptr = frame_ptr;
+ if (strcmp((char *) augmentation,
+ DW_CIE_AUGMENTER_STRING_V0) == 0) {
+ /* The first word is an offset into execption
+ tables. */
+ /* ?? THis presumes that the offset is always 32
+ bits */
+ 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 += local_length_size;
+ }
+ frame_ptr =
+ saved_frame_ptr + length_of_augmented_fields;
+ } else if (strcmp((const char *) augmentation, "eh") == 0) {
+ /* gnu eh fde case. we do not need to do anything */
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ Dwarf_Unsigned exception_table_addr;
+
+ READ_UNALIGNED(dbg, exception_table_addr,
+ Dwarf_Unsigned, frame_ptr,
+ dbg->de_pointer_size);
+ frame_ptr += dbg->de_pointer_size;
+ } else {
+ /* We do not understand the augmentation string. No
+ assumption can be made about if the instructions is
+ present. */
+ /* FIX -- The old code assumed that the instruction
+ table starts at the location pointed to by
+ frame_ptr, clearly incorrect. */
+ }
+ 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 = (Dwarf_Word) length;
+ new_fde->fd_length_size = local_length_size;
+ new_fde->fd_extension_size = local_extension_size;
+ new_fde->fd_cie_offset = cie_base_offset;
+ 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 = start_frame_ptr;
+ new_fde->fd_fde_instr_start = frame_ptr;
+ new_fde->fd_dbg = dbg;
+ new_fde->fd_offset_into_exception_tables =
+ offset_into_exception_tables;
+
+ fde_count++;
+ if (head_fde_ptr == NULL)
+ head_fde_ptr = cur_fde_ptr = new_fde;
+ else {
+ cur_fde_ptr->fd_next = new_fde;
+ cur_fde_ptr = new_fde;
+ }
+ }
+
+ /* Skip over instructions to start of next frame. */
+ frame_ptr = start_frame_ptr + length + local_length_size +
+ local_extension_size;
+ }
+
+ if (cie_count > 0) {
+ cie_list_ptr = (Dwarf_Cie *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
+ } else {
+ return (DW_DLV_NO_ENTRY);
+ }
+ if (cie_list_ptr == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ /* Return arguments. */
+ *cie_data = cie_list_ptr;
+ *cie_element_count = cie_count;
+ dbg->de_cie_data = cie_list_ptr;
+ dbg->de_cie_count = cie_count;
+
+ 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;
+ }
+
+ if (fde_count > 0) {
+ fde_list_ptr = (Dwarf_Fde *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
+ } else {
+ return (DW_DLV_NO_ENTRY);
+ }
+ if (fde_list_ptr == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ /* Return arguments. */
+ *fde_data = fde_list_ptr;
+ *fde_element_count = fde_count;
+ dbg->de_fde_data = fde_list_ptr;
+ dbg->de_fde_count = fde_count;
+ last_cie_index = 0;
+
+ cur_fde_ptr = head_fde_ptr;
+ for (i = 0; i < fde_count; i++) {
+ Dwarf_Sword new_cie_index = (Dwarf_Sword) cie_count;
+
+ *(fde_list_ptr + i) = cur_fde_ptr;
+
+ fde_cie_ptr = (Dwarf_Small *) (section_ptr +
+ cur_fde_ptr->fd_cie_offset);
+
+
+ /* we assume that the next fde has the same cie as the ** last
+ fde and resume the search where we left off */
+ for (j = last_cie_index; j < cie_count; j++) {
+ Dwarf_Cie ciep = (Dwarf_Cie) * (cie_list_ptr + j);
+
+ if (ciep->ci_cie_start == fde_cie_ptr) {
+ new_cie_index = (Dwarf_Sword) j;
+ break;
+ }
+ }
+ /* did not find it above, start from 0 and try again */
+ if (new_cie_index == cie_count) {
+ for (j = 0; j < last_cie_index; ++j) {
+ Dwarf_Cie ciep = (Dwarf_Cie) * (cie_list_ptr + j);
+
+ if (ciep->ci_cie_start == fde_cie_ptr) {
+ new_cie_index = (Dwarf_Sword) j;
+ break;
+ }
+ }
+ }
+ j = new_cie_index;
+ last_cie_index = new_cie_index;
+ if (j == cie_count) {
+ _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
+ return (DW_DLV_ERROR);
+ } else {
+ cur_fde_ptr->fd_cie_index = (Dwarf_Sword) j;
+ cur_fde_ptr->fd_cie = *(cie_list_ptr + j);
+ }
+
+ cur_fde_ptr = cur_fde_ptr->fd_next;
+ }
+
+ /* sort the list by the address, so that dwarf_get_fde_at_pc() can
+ binary search this list. */
+ qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
+ qsort_compare);
+
+ return (DW_DLV_OK);
+}
+
+/*
+ Only works on dwarf sections, not eh_frame
+*/
+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;
+ Dwarf_Signed signdval;
+ Dwarf_Unsigned length; /* must be min de_length_size bytes */
+ Dwarf_Signed signed_offset; /* must be min de_length_size bytes */
+ Dwarf_Addr initial_location; /* must be min de_pointer_size
+ bytes */
+ Dwarf_Addr address_range; /* must be min de_pointer_size bytes */
+ Dwarf_Fde new_fde;
+ unsigned char *fde_ptr;
+ Dwarf_Small *saved_fde_ptr;
+ unsigned char *cie_ptr;
+ unsigned char *start_cie_ptr;
+ Dwarf_Cie new_cie;
+
+ /* Fields for the current Cie being read. */
+ Dwarf_Small version;
+ Dwarf_Small *augmentation;
+ Dwarf_Word code_alignment_factor;
+ Dwarf_Sword data_alignment_factor;
+ Dwarf_Small return_address_register;
+ Dwarf_Word length_of_augmented_fields;
+ Dwarf_Signed offset_into_exception_tables =
+ (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
+ int res;
+ int resattr;
+ int sdatares;
+ int fde_local_extension_size = 0;
+ int fde_local_length_size = 0;
+ int cie_local_extension_size = 0;
+ int cie_local_length_size = 0;
+
+
+ Dwarf_Word leb128_length;
+
+ 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_index,
+ &dbg->de_debug_frame,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ fde_offset = signdval;
+ fde_ptr = (dbg->de_debug_frame + fde_offset);
+
+ /* READ_AREA_LENGTH updates fde_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ fde_ptr, fde_local_length_size,
+ fde_local_extension_size);
+
+
+ if (length % fde_local_length_size != 0) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, signed_offset, Dwarf_Signed,
+ fde_ptr, fde_local_length_size);
+ SIGN_EXTEND(signed_offset, fde_local_length_size);
+ fde_ptr += fde_local_length_size;
+
+ READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
+ fde_ptr, dbg->de_pointer_size);
+ fde_ptr += dbg->de_pointer_size;
+
+ READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
+ fde_ptr, dbg->de_pointer_size);
+ fde_ptr += dbg->de_pointer_size;
+
+ res = get_augmentation_string(dbg,
+ (Dwarf_Small *) (dbg->de_debug_frame +
+ signed_offset),
+ DW_CIE_ID, &augmentation, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ if ((strcmp((char *) augmentation, DW_DEBUG_FRAME_AUGMENTER_STRING)
+ == 0) ||
+ (strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
+ /* Do nothing. The fde_ptr is pointing at start of
+ instructions. */
+ } else if (augmentation[0] == 'z') {
+ /* The augmentation starts with a known prefix. See the
+ dwarf_frame.h for details on the layout. */
+
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(fde_ptr, lreg)
+ length_of_augmented_fields = (Dwarf_Word) lreg;
+
+ saved_fde_ptr = fde_ptr;
+ if (strcmp((char *) augmentation, DW_CIE_AUGMENTER_STRING_V0) ==
+ 0) {
+ /* The first word is an offset into execption tables. */
+ READ_UNALIGNED(dbg, offset_into_exception_tables,
+ Dwarf_Signed, fde_ptr, sizeof(Dwarf_sfixed));
+ SIGN_EXTEND(offset_into_exception_tables,
+ sizeof(Dwarf_sfixed));
+ fde_ptr += sizeof(Dwarf_sfixed);
+ }
+ fde_ptr = saved_fde_ptr + length_of_augmented_fields;
+ } else {
+ /* We do not understand the augmentation string. No assumption
+ can be made about if the instructions is present. */
+ /* FIX -- The old code assumed that the instruction table
+ starts at location pointed to by fde_ptr, clearly incorrect.
+ */
+ }
+
+ 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 = (Dwarf_Word) length;
+ new_fde->fd_length_size = fde_local_length_size;
+ new_fde->fd_extension_size = fde_local_extension_size;
+ new_fde->fd_cie_offset = signed_offset;
+ new_fde->fd_initial_location = initial_location;
+ new_fde->fd_address_range = address_range;
+ new_fde->fd_fde_start = dbg->de_debug_frame + fde_offset;
+ new_fde->fd_fde_instr_start = (Dwarf_Small *) fde_ptr;
+ new_fde->fd_dbg = dbg;
+ new_fde->fd_offset_into_exception_tables =
+ offset_into_exception_tables;
+
+ /* now read the cie corresponding to the fde */
+ cie_ptr = (dbg->de_debug_frame + signed_offset);
+ start_cie_ptr = cie_ptr;
+
+ /* READ_AREA_LENGTH updates cie_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ cie_ptr, cie_local_length_size,
+ cie_local_extension_size);
+
+
+ if (length % cie_local_length_size != 0) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, signed_offset, Dwarf_Signed,
+ cie_ptr, cie_local_length_size);
+ SIGN_EXTEND(signed_offset, cie_local_length_size);
+ cie_ptr += cie_local_length_size;
+
+ if (signed_offset == DW_CIE_ID) {
+
+ version = *(Dwarf_Small *) cie_ptr;
+ cie_ptr++;
+ if (version != DW_CIE_VERSION) {
+ _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ augmentation = cie_ptr;
+ cie_ptr = cie_ptr + strlen((char *) cie_ptr) + 1;
+ if ((strcmp((char *) augmentation,
+ DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
+ (strcmp((char *) augmentation, DW_EMPTY_STRING) == 0)) {
+
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(cie_ptr, lreg)
+ code_alignment_factor = (Dwarf_Word) lreg;
+
+
+ data_alignment_factor = (Dwarf_Sword)
+ _dwarf_decode_s_leb128(cie_ptr, &leb128_length);
+ cie_ptr = cie_ptr + leb128_length;
+
+ return_address_register = *(Dwarf_Small *) cie_ptr;
+ if (return_address_register > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ cie_ptr++;
+ } else if (augmentation[0] == 'z') {
+ /* The augmentation starts with a known prefix. We can
+ asssume that the first field is the length of the
+ augmented fields. */
+
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(cie_ptr, lreg)
+ code_alignment_factor = (Dwarf_Word) lreg;
+ data_alignment_factor = (Dwarf_Sword)
+ _dwarf_decode_s_leb128(cie_ptr, &leb128_length);
+ cie_ptr = cie_ptr + leb128_length;
+
+ return_address_register = *(Dwarf_Small *) cie_ptr;
+ if (return_address_register > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ cie_ptr++;
+ /* Decode the length of augmented fields. */
+ DECODE_LEB128_UWORD(cie_ptr, lreg)
+ length_of_augmented_fields = (Dwarf_Word) lreg;
+
+ /* set the cie_ptr to point at the instruction start. */
+ cie_ptr += length_of_augmented_fields;
+ } else if (strcmp((const char *) augmentation, "eh") == 0) {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(cie_ptr, lreg)
+ code_alignment_factor = (Dwarf_Word) lreg;
+
+
+ data_alignment_factor = (Dwarf_Sword)
+ _dwarf_decode_s_leb128(cie_ptr, &leb128_length);
+ cie_ptr = cie_ptr + leb128_length;
+
+ return_address_register = *(Dwarf_Small *) cie_ptr;
+ if (return_address_register > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ cie_ptr++;
+
+ } else {
+ /* We do not understand the augmentation string. No
+ assumption can be made about any fields other than what
+ we have already read. */
+ cie_ptr = start_cie_ptr + length + cie_local_length_size
+ + cie_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.
+ */
+ }
+
+ 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_initial_table = NULL;
+ new_cie->ci_length = (Dwarf_Word) length;
+ new_cie->ci_length_size = cie_local_length_size;
+ new_cie->ci_extension_size = cie_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 = start_cie_ptr;
+ new_cie->ci_cie_instr_start = cie_ptr;
+ new_cie->ci_dbg = dbg;
+ } else {
+ _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
+ return (DW_DLV_ERROR);
+ }
+ new_fde->fd_cie = new_cie;
+
+ *ret_fde = new_fde;
+ return DW_DLV_OK;
+}
+
+
+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)
+{
+ int res;
+ 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);
+ }
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_frame_index,
+ &dbg->de_debug_frame,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ 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 - dbg->de_debug_frame;
+
+ return DW_DLV_OK;
+}
+
+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;
+}
+
+
+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,
+ 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 (version != NULL)
+ *version = DW_CIE_VERSION;
+ 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);
+}
+
+static int
+_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Frame table, Dwarf_Error * error)
+/* Return the register rules for all registers at a given pc. */
+{
+ Dwarf_Debug dbg;
+ Dwarf_Cie cie;
+ Dwarf_Sword i;
+ int dw_err;
+ Dwarf_Sword icount;
+ int res;
+
+ 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);
+ }
+ for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++) {
+ cie->ci_initial_table->fr_reg[i].ru_is_off = 0;
+ cie->ci_initial_table->fr_reg[i].ru_register =
+ DW_FRAME_SAME_VAL;
+ cie->ci_initial_table->fr_reg[i].ru_offset = 0;
+ }
+
+ 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,
+ &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;
+ }
+ }
+
+ 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,
+ fde->fd_fde_start + fde->fd_length +
+ fde->fd_length_size +
+ fde->fd_extension_size,
+ table, cie, dbg, &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;
+}
+
+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)
+{
+
+ struct Dwarf_Frame_s fde_table;
+ Dwarf_Sword i;
+ int 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, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ for (i = 0; i < DW_REG_TABLE_SIZE; i++) {
+ reg_table->rules[i].dw_offset_relevant =
+ fde_table.fr_reg[i].ru_is_off;
+ reg_table->rules[i].dw_regnum = fde_table.fr_reg[i].ru_register;
+ reg_table->rules[i].dw_offset = fde_table.fr_reg[i].ru_offset;
+ }
+
+ if (row_pc != NULL)
+ *row_pc = fde_table.fr_loc;
+
+ return DW_DLV_OK;
+}
+
+
+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;
+
+
+ if (table_column > DW_FRAME_LAST_REG_NUM) {
+ _dwarf_error(NULL, 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,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ 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;
+ if (row_pc != NULL)
+ *row_pc = fde_table.fr_loc;
+
+ *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off);
+ 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;
+ unsigned char *instrs;
+ Dwarf_Debug dbg;
+
+ if (inFde == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = inFde->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, 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;
+}
+
+int
+dwarf_get_fde_n(Dwarf_Fde * fde_data,
+ Dwarf_Unsigned fde_index,
+ Dwarf_Fde * returned_fde, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+
+ if (fde_data == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (*fde_data == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = (*fde_data)->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (fde_index >= dbg->de_fde_count) {
+ 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;
+ Dwarf_Fde fde = NULL;
+
+ if (fde_data == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (*fde_data == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = (*fde_data)->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ {
+ /* The fde's are sorted by their addresses. Binary search to
+ find correct fde. */
+ int low = 0;
+ int high = dbg->de_fde_count - 1;
+ int 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);
+}
+
+
+int
+dwarf_expand_frame_instructions(Dwarf_Debug dbg,
+ 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;
+ int dw_err;
+
+ if (dbg == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ 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_ptr */ NULL,
+ dbg, &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 rqs. 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.
+
+*/
+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;
+ 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_index,
+ &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;
+ int dw_err;
+
+ ciep = cie_data[i];
+ instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame;
+ 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, &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;
+ int dw_err;
+
+ fdep = fde_data[i];
+ off = fdep->fd_initial_loc_pos - dbg->de_debug_frame;
+ 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;
+ 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, &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;
+}
+
+/* Used by dwarfdump -v to print offsets, for debugging
+ dwarf info
+*/
+/* 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)
+{
+ int res;
+ char *start;
+ char *loc;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_frame_index,
+ &dbg->de_debug_frame,
+ err);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ start = (char *) dbg->de_debug_frame;
+ 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
+*/
+/* ARGSUSED 4 */
+int
+_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
+ Dwarf_Off * cie_off, Dwarf_Error * err)
+{
+ int res;
+ char *start;
+ char *loc;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_frame_index,
+ &dbg->de_debug_frame,
+ err);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ start = (char *) dbg->de_debug_frame;
+ loc = (char *) in_cie->ci_cie_start;
+
+ *cie_off = (loc - start);
+ return DW_DLV_OK;
+}
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame.h b/usr/src/tools/ctf/dwarf/common/dwarf_frame.h
new file mode 100644
index 0000000000..5338ce678c
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_frame.h
@@ -0,0 +1,207 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+/* 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).
+ * This implementation of libdwarf will assume that the length of
+ * augmented fields follow the augmenter string when the augmentation
+ * starts with the string "z". It will skip over any augmented fields
+ * that it does not understand to the start of initial instructions
+ * (in case of CIE) or the instruction table (in case of FDE).
+ *
+ * Future sgi versions of cie or fde should use "z1", "z2" as the
+ * augmenter strings and it should guarantee that all the above fields
+ * are laid out in the same fashion. Older libraries will continue to be able
+ * to read all the old data, skipping over newly added data items.
+ *
+ * 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 exception handling tables.
+ */
+
+#define DW_DEBUG_FRAME_VERSION 1
+#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. 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;
+
+ /* Register involved in this rule. */
+ Dwarf_Half ru_register;
+
+ /* Offset to add to register, if indicated by ru_is_offset. */
+ Dwarf_Addr ru_offset;
+};
+
+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.
+*/
+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_reg[DW_FRAME_LAST_REG_NUM];
+
+ 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;
+};
+
+/*
+ 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_Word 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;
+};
+
+/*
+ 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_Word fd_length;
+ Dwarf_Addr fd_cie_offset;
+ Dwarf_Sword 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;
+ Dwarf_Signed fd_offset_into_exception_tables;
+ Dwarf_Fde fd_next;
+ Dwarf_Small fd_length_size;
+ Dwarf_Small fd_extension_size;
+};
+
+
+int
+ _dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
+ Dwarf_Off ** offsetlist,
+ Dwarf_Signed * returncount,
+ Dwarf_Error * err);
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_funcs.c b/usr/src/tools/ctf/dwarf/common/dwarf_funcs.c
new file mode 100644
index 0000000000..a7f3fee702
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_funcs.c
@@ -0,0 +1,121 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#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;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_funcnames_index,
+ &dbg->de_debug_funcnames,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ return _dwarf_internal_get_pubnames_like_data(dbg, dbg->de_debug_funcnames, dbg->de_debug_funcnames_size, (Dwarf_Global **) funcs, /* type
+ punning,
+ Dwarf_Type
+ is never
+ a
+ completed
+ type */
+ ret_func_count,
+ error,
+ DW_DLA_FUNC_CONTEXT,
+ DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR);
+
+}
+
+
+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
new file mode 100644
index 0000000000..e3ca667307
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_funcs.h
@@ -0,0 +1,42 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..6ba561ef5b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_global.c
@@ -0,0 +1,464 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_global.h"
+
+int
+dwarf_get_globals(Dwarf_Debug dbg,
+ Dwarf_Global ** globals,
+ Dwarf_Signed * return_count, Dwarf_Error * error)
+{
+ int res;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_pubnames_index,
+ &dbg->de_debug_pubnames,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->
+ de_debug_pubnames,
+ dbg->
+ de_debug_pubnames_size,
+ globals, return_count,
+ error,
+ DW_DLA_GLOBAL_CONTEXT,
+ DW_DLE_PUBNAMES_LENGTH_BAD,
+ DW_DLE_PUBNAMES_VERSION_ERROR);
+
+}
+
+
+/* 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 allocation_code,
+ int length_err_num,
+ int version_err_num)
+{
+
+
+ Dwarf_Small *pubnames_like_ptr;
+
+
+
+ /*
+ 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;
+
+ Dwarf_Half version;
+
+ /*
+ Offset from the start of compilation-unit for the current
+ global. */
+ Dwarf_Off die_offset_in_cu;
+
+ Dwarf_Unsigned global_count = 0;
+
+ /* Points to the current global read. */
+ Dwarf_Global global;
+
+ /*
+ Used to chain the Dwarf_Global_s structs for creating contiguous
+ list of pointers to the structs. */
+ Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
+
+ /* Points to contiguous block of Dwarf_Global's to be returned. */
+ Dwarf_Global *ret_globals;
+
+ /* Temporary counter. */
+ Dwarf_Unsigned i;
+
+
+
+
+ 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) {
+ 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;
+ int local_extension_size;
+ int local_length_size;
+
+ /* 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, allocation_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;
+
+
+ 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;
+
+ /* 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, DW_DLA_GLOBAL, 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;
+ 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 = (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;
+
+ 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.
+*/
+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;
+ Dwarf_Debug dbg;
+ Dwarf_Off off;
+
+ 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;
+ if (die_offset != NULL) {
+ *die_offset = global->gl_named_die_offset_within_cu + off;
+ }
+
+ dbg = con->pu_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (cu_die_offset != NULL) {
+ int res = _dwarf_load_debug_info(dbg,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
+ }
+
+ *ret_name = (char *) global->gl_name;
+
+ 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.
+*/
+
+/* 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;
+}
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_global.h b/usr/src/tools/ctf/dwarf/common/dwarf_global.h
new file mode 100644
index 0000000000..a0c7382bf8
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_global.h
@@ -0,0 +1,104 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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.
+
+*/
+struct Dwarf_Global_Context_s {
+
+ /*
+ Length in .debug_pubnames of a set of pubnames 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 allocation_code,
+ int length_err_num,
+ int version_err_num);
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_incl.h b/usr/src/tools/ctf/dwarf/common/dwarf_incl.h
new file mode 100644
index 0000000000..1b6dfc52a8
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_incl.h
@@ -0,0 +1,57 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#ifndef DWARF_INCL_H
+#define DWARF_INCL_H
+
+#include "libdwarfdefs.h"
+#include <string.h>
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+
+#include <limits.h>
+#include <libdwarf.h>
+#include <dwarf.h>
+
+#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
new file mode 100644
index 0000000000..9b6321f4f3
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_init_finish.c
@@ -0,0 +1,809 @@
+/*
+
+ Copyright (C) 2000,2002,2003 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#ifdef __SGI_FAST_LIBELF
+#include <libelf_sgi.h>
+#else
+#ifdef HAVE_LIBELF_H
+#include <libelf.h>
+#else
+#ifdef HAVE_LIBELF_LIBELF_H
+#include <libelf/libelf.h>
+#endif
+#endif
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+#include <gelf.h>
+#include <strings.h>
+#include <sys/elf_386.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#include "dwarf_incl.h"
+
+#define DWARF_DBG_ERROR(dbg,errval,retval) \
+ _dwarf_error(dbg, error, errval); return(retval);
+
+#define FALSE 0
+#define TRUE 1
+
+#ifdef __SGI_FAST_LIBELF
+#else
+#ifdef HAVE_ELF64_GETEHDR
+extern Elf64_Ehdr *elf64_getehdr(Elf *);
+#endif
+#ifdef HAVE_ELF64_GETSHDR
+extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
+#endif
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+
+/* 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;
+
+
+int
+dwarf_set_stringcheck(int newval)
+{
+ int oldval = _dwarf_assume_string_bad;
+
+ _dwarf_assume_string_bad = newval;
+ return oldval;
+}
+
+#ifdef __SGI_FAST_LIBELF
+/*
+ This function translates an elf_sgi error code into a libdwarf
+ code.
+ */
+static int
+_dwarf_error_code_from_elf_sgi_error_code(enum elf_sgi_error_type val)
+{
+ switch (val) {
+ case ELF_SGI_ERROR_OK: return DW_DLE_NE;
+ case ELF_SGI_ERROR_BAD_ALLOC: return DW_DLE_MAF;
+ case ELF_SGI_ERROR_FORMAT: return DW_DLE_MDE;
+ case ELF_SGI_ERROR_ERRNO: return DW_DLE_IOF;
+ case ELF_SGI_ERROR_TOO_BIG: return DW_DLE_MOF;
+ default: return DW_DLE_LEE;
+ }
+}
+#endif
+
+/*
+ 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_elf_handle elf, Dwarf_Error * error)
+{
+#ifdef __SGI_FAST_LIBELF
+ Elf64_Ehdr ehdr;
+ Elf64_Shdr shdr;
+ enum elf_sgi_error_type sres;
+ unsigned char const* ehdr_ident;
+#else
+ Elf32_Ehdr *ehdr32;
+
+#ifdef HAVE_ELF64_GETEHDR
+ Elf64_Ehdr *ehdr64;
+#endif
+ Elf32_Shdr *shdr32;
+
+#ifdef HAVE_ELF64_GETSHDR
+ Elf64_Shdr *shdr64;
+#endif
+ Elf_Scn *scn;
+ char *ehdr_ident;
+#endif /* !defined(__SGI_FAST_LIBELF) */
+ Dwarf_Half machine;
+ char *scn_name;
+ int is_64bit;
+ int foundDwarf;
+
+ Dwarf_Unsigned section_size;
+ Dwarf_Unsigned section_count;
+ Dwarf_Half section_index;
+
+ foundDwarf = FALSE;
+ dbg->de_elf = elf;
+
+ dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad;
+
+#ifdef __SGI_FAST_LIBELF
+ sres = elf_sgi_ehdr(elf, &ehdr);
+ if (sres != ELF_SGI_ERROR_OK) {
+ DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
+ DW_DLV_ERROR);
+ }
+ ehdr_ident = ehdr.e_ident;
+ section_count = ehdr.e_shnum;
+ machine = ehdr.e_machine;
+#else
+ if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETIDENT_ERROR, DW_DLV_ERROR);
+ }
+#endif
+
+ is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
+
+
+ dbg->de_same_endian = 1;
+ dbg->de_copy_word = memcpy;
+#ifdef WORDS_BIGENDIAN
+ dbg->de_big_endian_object = 1;
+ if (ehdr_ident[EI_DATA] == ELFDATA2LSB) {
+ 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 (ehdr_ident[EI_DATA] == ELFDATA2MSB) {
+ 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 appoximate one at that. */
+ dbg->de_length_size = is_64bit ? 8 : 4;
+ dbg->de_pointer_size = is_64bit ? 8 : 4;
+
+
+#ifdef __SGI_FAST_LIBELF
+ /* We've already loaded the ELF header, so there's nothing to do here */
+#else
+#ifdef HAVE_ELF64_GETEHDR
+ if (is_64bit) {
+ ehdr64 = elf64_getehdr(elf);
+ if (ehdr64 == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR,
+ DW_DLV_ERROR);
+ }
+ section_count = ehdr64->e_shnum;
+ machine = ehdr64->e_machine;
+ } else
+#endif
+ {
+ ehdr32 = elf32_getehdr(elf);
+ if (ehdr32 == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR,
+ DW_DLV_ERROR);
+ }
+ section_count = ehdr32->e_shnum;
+ machine = ehdr32->e_machine;
+ }
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+ dbg->de_nelfsecs = section_count;
+
+ if (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. */
+ dbg->de_length_size = 4;
+ }
+
+ /* We start at index 1 to skip the initial empty section. */
+ for (section_index = 1; section_index < section_count; ++section_index) {
+
+#ifdef __SGI_FAST_LIBELF
+ sres = elf_sgi_shdr(elf, section_index, &shdr);
+ if (sres != ELF_SGI_ERROR_OK) {
+ DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
+ DW_DLV_ERROR);
+ }
+
+ section_size = shdr.sh_size;
+
+ sres = elf_sgi_string(elf, ehdr.e_shstrndx, shdr.sh_name, (char const** )&scn_name);
+ if (sres != ELF_SGI_ERROR_OK) {
+ DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
+ DW_DLV_ERROR);
+ }
+#else /* !defined(__SGI_FAST_LIBELF) */
+ scn = elf_getscn(elf, section_index);
+ if (scn == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_MDE,
+ DW_DLV_ERROR);
+ }
+
+#ifdef HAVE_ELF64_GETSHDR
+ if (is_64bit) {
+ shdr64 = elf64_getshdr(scn);
+ if (shdr64 == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR,
+ DW_DLV_ERROR);
+ }
+
+ section_size = shdr64->sh_size;
+
+ if ((scn_name = elf_strptr(elf, ehdr64->e_shstrndx,
+ shdr64->sh_name))
+ == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR,
+ DW_DLV_ERROR);
+ }
+ } else
+#endif /* HAVE_ELF64_GETSHDR */
+ {
+ if ((shdr32 = elf32_getshdr(scn)) == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR, 0);
+ }
+
+ section_size = shdr32->sh_size;
+
+ if ((scn_name = elf_strptr(elf, ehdr32->e_shstrndx,
+ shdr32->sh_name)) == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR,
+ DW_DLV_ERROR);
+ }
+ }
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+ if (strncmp(scn_name, ".debug_", 7)
+ && strcmp(scn_name, ".eh_frame")
+ )
+ continue;
+
+ else if (strcmp(scn_name, ".debug_info") == 0) {
+ if (dbg->de_debug_info != NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* Know no reason to allow empty debug_info section */
+ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_NULL,
+ DW_DLV_ERROR);
+ }
+ foundDwarf = TRUE;
+ dbg->de_debug_info_index = section_index;
+ dbg->de_debug_info_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_abbrev") == 0) {
+ if (dbg->de_debug_abbrev != NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* Know no reason to allow empty debug_abbrev section */
+ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_NULL,
+ DW_DLV_ERROR);
+ }
+ dbg->de_debug_abbrev_index = section_index;
+ dbg->de_debug_abbrev_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_aranges") == 0) {
+ if (dbg->de_debug_aranges_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_ARANGES_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_aranges_index = section_index;
+ dbg->de_debug_aranges_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_line") == 0) {
+ if (dbg->de_debug_line_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_LINE_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_line_index = section_index;
+ dbg->de_debug_line_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_frame") == 0) {
+ if (dbg->de_debug_frame_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_FRAME_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_frame_index = section_index;
+ dbg->de_debug_frame_size = section_size;
+ foundDwarf = TRUE;
+ } else if (strcmp(scn_name, ".eh_frame") == 0) {
+ /* gnu egcs-1.1.2 data */
+ if (dbg->de_debug_frame_eh_gnu_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_FRAME_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_frame_eh_gnu_index = section_index;
+ dbg->de_debug_frame_size_eh_gnu = section_size;
+ foundDwarf = TRUE;
+ }
+
+ else if (strcmp(scn_name, ".debug_loc") == 0) {
+ if (dbg->de_debug_loc_index != 0) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_LOC_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_loc_index = section_index;
+ dbg->de_debug_loc_size = section_size;
+ }
+
+
+ else if (strcmp(scn_name, ".debug_pubnames") == 0) {
+ if (dbg->de_debug_pubnames_index != 0) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_PUBNAMES_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_pubnames_index = section_index;
+ dbg->de_debug_pubnames_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_str") == 0) {
+ if (dbg->de_debug_str_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_STR_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_str_index = section_index;
+ dbg->de_debug_str_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_funcnames") == 0) {
+ if (dbg->de_debug_funcnames_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_funcnames_index = section_index;
+ dbg->de_debug_funcnames_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_typenames") == 0) {
+ if (dbg->de_debug_typenames_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_TYPENAMES_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_typenames_index = section_index;
+ dbg->de_debug_typenames_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_varnames") == 0) {
+ if (dbg->de_debug_varnames_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_VARNAMES_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_varnames_index = section_index;
+ dbg->de_debug_varnames_size = section_size;
+ }
+
+ else if (strcmp(scn_name, ".debug_weaknames") == 0) {
+ if (dbg->de_debug_weaknames_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_weaknames_index = section_index;
+ dbg->de_debug_weaknames_size = section_size;
+ } else if (strcmp(scn_name, ".debug_macinfo") == 0) {
+ if (dbg->de_debug_macinfo_index != 0) {
+ DWARF_DBG_ERROR(dbg,
+ DW_DLE_DEBUG_MACINFO_DUPLICATE,
+ DW_DLV_ERROR);
+ }
+ if (section_size == 0) {
+ /* a zero size section is just empty. Ok, no error */
+ continue;
+ }
+ dbg->de_debug_macinfo_index = section_index;
+ dbg->de_debug_macinfo_size = section_size;
+ }
+ }
+ if (foundDwarf) {
+ return DW_DLV_OK;
+ }
+
+ return (DW_DLV_NO_ENTRY);
+}
+
+
+/*
+ The basic dwarf initializer function for consumers.
+ Return NULL on error.
+*/
+int
+dwarf_init(int fd,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+ struct stat fstat_buf;
+ dwarf_elf_handle elf;
+ int res;
+#ifdef __SGI_FAST_LIBELF
+ enum elf_sgi_error_type sres;
+#else
+ Elf_Cmd what_kind_of_elf_read;
+#endif
+
+ 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;
+
+ if (fstat(fd, &fstat_buf) != 0) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_FSTAT_ERROR, DW_DLV_ERROR);
+ }
+ if (!S_ISREG(fstat_buf.st_mode)) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_FSTAT_MODE_ERROR, DW_DLV_ERROR);
+ }
+
+ if (access != DW_DLC_READ) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
+ }
+ dbg->de_access = access;
+
+#ifdef __SGI_FAST_LIBELF
+ elf = elf_sgi_new();
+ if (elf == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_ERROR);
+ }
+
+ sres = elf_sgi_begin_fd(elf, fd, 0);
+ if (sres != ELF_SGI_ERROR_OK) {
+ DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
+ DW_DLV_ERROR);
+ }
+#else
+ 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;
+#else
+ /* ELF_C_READ is a portable value */
+ what_kind_of_elf_read = ELF_C_READ;
+#endif
+
+ if ((elf = elf_begin(fd, what_kind_of_elf_read, 0)) == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_ELF_BEGIN_ERROR, DW_DLV_ERROR);
+ }
+#endif /* !defined(__SGI_FAST_LIBELF) */
+
+ dbg->de_elf_must_close = 1;
+ if ((res = _dwarf_setup(dbg, elf, error)) != DW_DLV_OK) {
+ free(dbg);
+ return (res);
+ }
+
+ /* call cannot fail: no malloc or free involved */
+ _dwarf_setup_debug(dbg);
+
+ *ret_dbg = dbg;
+ return (DW_DLV_OK);
+}
+
+
+/*
+ The alternate dwarf setup call for consumers
+*/
+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)
+{
+ Dwarf_Debug dbg;
+ int res;
+
+ 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;
+
+ if (access != DW_DLC_READ) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
+ }
+ dbg->de_access = access;
+
+ dbg->de_elf_must_close = 0;
+ if ((res = _dwarf_setup(dbg, elf_file_pointer, error)) != DW_DLV_OK) {
+ free(dbg);
+ return (res);
+ }
+
+ /* this call cannot fail: allocates nothing, releases nothing */
+ _dwarf_setup_debug(dbg);
+
+ *ret_dbg = dbg;
+ return (DW_DLV_OK);
+}
+
+
+/*
+ Frees all memory that was not previously freed
+ by dwarf_dealloc.
+ Aside from certain categories.
+*/
+int
+dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+ int res = DW_DLV_OK;
+ if(dbg->de_elf_must_close) {
+ /* Must do this *before* _dwarf_free_all_of_one_debug()
+ as that zeroes out dbg contents
+ */
+#ifdef __SGI_FAST_LIBELF
+ elf_sgi_free(dbg->de_elf);
+#else
+ elf_end(dbg->de_elf);
+#endif
+ }
+
+ res = _dwarf_free_all_of_one_debug(dbg);
+ if (res == DW_DLV_ERROR) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
+ }
+
+ return res;
+
+
+}
+
+
+/*
+ This function returns the Elf * pointer
+ associated with a Dwarf_Debug.
+*/
+int
+dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle* elf, Dwarf_Error * error)
+{
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *elf = dbg->de_elf;
+ return (DW_DLV_OK);
+}
+
+#if defined(__i386)
+static Dwarf_Small *
+_dwarf_reloc_section(Dwarf_Debug dbg, Dwarf_Half scnidx, Elf_Data *scndata,
+ Dwarf_Error *error)
+{
+ Elf_Data *reldata;
+ GElf_Rela rela;
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+ char *newdata;
+ int ridx, rscnidx;
+
+ for (rscnidx = 0; rscnidx < dbg->de_nelfsecs; rscnidx++) {
+ if ((scn = elf_getscn(dbg->de_elf, rscnidx)) == NULL ||
+ gelf_getshdr(scn, &shdr) == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_LEE);
+ return (NULL);
+ }
+
+ if (shdr.sh_type == SHT_RELA &&
+ shdr.sh_info == scnidx)
+ break;
+ }
+
+ if (rscnidx == dbg->de_nelfsecs)
+ return (scndata->d_buf);
+
+ if ((reldata = elf_getdata(scn, NULL)) == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_LEE);
+ return (NULL);
+ }
+
+ if ((newdata = malloc(scndata->d_size)) == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_MAF);
+ return (NULL);
+ }
+
+ bcopy(scndata->d_buf, newdata, scndata->d_size);
+
+ for (ridx = 0; ridx < shdr.sh_size / sizeof (GElf_Rela); ridx++) {
+ if (gelf_getrela(reldata, ridx, &rela) == NULL)
+ continue;
+
+ if (GELF_R_TYPE(rela.r_info) != R_386_32 &&
+ GELF_R_TYPE(rela.r_info) != R_386_GOTPC) {
+ fprintf(stderr, "achtung: tell simmonmt@eng about "
+ "unexpected reloc type %d\n",
+ GELF_R_TYPE(rela.r_info));
+ continue;
+ }
+
+ *(uint32_t *)(newdata + rela.r_offset) = rela.r_addend;
+ }
+
+ return ((Dwarf_Small *)newdata);
+}
+#endif
+
+/*
+ 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,
+ Dwarf_Half section_index,
+ Dwarf_Small ** section_data,
+ Dwarf_Error * error)
+{
+ if (section_index == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+
+ /* check to see if the section is already loaded */
+ if (*section_data != NULL) {
+ return DW_DLV_OK;
+ }
+
+ {
+#ifdef __SGI_FAST_LIBELF
+ enum elf_sgi_error_type sres;
+
+ sres = elf_sgi_section(dbg->de_elf,
+ section_index,
+ (void**) section_data);
+ if (sres != ELF_SGI_ERROR_OK) {
+ DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
+ DW_DLV_ERROR);
+ }
+#else
+ Elf_Scn* scn;
+ Elf_Data* data;
+
+ scn = elf_getscn(dbg->de_elf, section_index);
+ if (scn == NULL) {
+ _dwarf_error(dbg, 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) {
+ _dwarf_error(dbg, error, DW_DLE_MDE);
+ return DW_DLV_ERROR;
+ }
+
+#if defined(__i386)
+ if ((*section_data = _dwarf_reloc_section(dbg, section_index, data,
+ error)) == NULL)
+ return (DW_DLV_ERROR); /* _dwarf_error is set for us */
+#else
+ *section_data = data->d_buf;
+#endif
+
+#endif /* !defined(__SGI_FAST_LIBELF) */
+ }
+
+ 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
new file mode 100644
index 0000000000..f759642f56
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_leb.c
@@ -0,0 +1,149 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+
+
+/*
+ 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
new file mode 100644
index 0000000000..6e5556ef85
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_line.c
@@ -0,0 +1,1548 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_line.h"
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+
+/*
+ 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;
+
+ /*
+ This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end;
+
+ /*
+ 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 *check_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;
+
+ /* Some of the fields of the statement program header. */
+ Dwarf_Unsigned total_length = 0;
+ Dwarf_Half version = 0;
+ Dwarf_Unsigned prologue_length = 0;
+ Dwarf_Small special_opcode_base= 0;
+
+ /* File name excluding included directory. */
+ char *file_name = 0;
+
+ /* Name of directory that the file is in. */
+ char *dir_name = 0;
+
+ /* Name concatenating both directory and file name. */
+ char *full_name = 0;
+
+ /*
+ This is the directory index for the file. The compilation
+ directory is 0, and the first included directory is 1. */
+ Dwarf_Sword dir_index = 0;
+
+ Dwarf_Small *include_directories = 0;
+
+ Dwarf_Sword i = 0;
+ Dwarf_Sword file_count = 0;
+ Dwarf_Sword directories_count = 0;
+
+ /*
+ This is the current opcode read from the statement program. */
+
+ Dwarf_Word leb128_length;
+
+ /* This is the length of an extended opcode instr. */
+
+ /*
+ 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;
+
+ /* Used to chain the file names. */
+ Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
+ int resattr;
+ int lres;
+
+ int local_length_size = 0;
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ int local_extension_size = 0;
+
+ int res;
+
+ /* ***** 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_index == 0) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_line_index,
+ &dbg->de_debug_line,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (line_offset >= dbg->de_debug_line_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ line_ptr = dbg->de_debug_line + 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;
+ char *cdir;
+
+ 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);
+ }
+
+ /*
+ Following is a straightforward decoding of the statement
+ program prologue information. */
+ /* 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;
+ if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
+ line_ptr, local_length_size);
+ line_ptr += local_length_size;
+ check_line_ptr = line_ptr;
+
+ /* Skip over minimum instruction length. */
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ /* Skip over default_is_stmt. */
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ /* Skip over line_base. */
+ line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
+
+ /* Skip over line_ptr. */
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ special_opcode_base = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ for (i = 1; i < special_opcode_base; i++) {
+ /* Skip over opcode lengths for standard opcodes. */
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+ }
+
+ directories_count = 0;
+ include_directories = line_ptr;
+ while ((*(char *) line_ptr) != '\0') {
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ directories_count++;
+ }
+ line_ptr++;
+
+ file_count = 0;
+ while (*(char *) line_ptr != '\0') {
+ Dwarf_Unsigned utmp;
+
+ file_name = (char *) 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, error, DW_DLE_DIR_INDEX_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ if (dir_index == 0)
+ dir_name = (char *) comp_dir;
+ else {
+ dir_name = (char *) include_directories;
+ for (i = 1; i < dir_index; i++)
+ /* FIX: this is probably very slow: redoing strlen!
+ davea 9/94 */
+ dir_name = dir_name + strlen(dir_name) + 1;
+ }
+
+ /* dir_name can be NULL if there is no DW_AT_comp_dir */
+ if ((*file_name) == '/' || dir_name == 0)
+ 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_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ strcpy(full_name, dir_name);
+ strcat(full_name, "/");
+ strcat(full_name, file_name);
+ }
+
+ /* Skip over time of last modification. */
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ /* Skip over file length. */
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ 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 = full_name;
+
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+
+ file_count++;
+ }
+ line_ptr++;
+
+ if (line_ptr != check_line_ptr + prologue_length) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ if (file_count == 0) {
+ *srcfiles = NULL;
+ *srcfilecount = 0;
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ ret_files = (char **)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, file_count);
+ if (ret_files == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain = head_chain;
+ for (i = 0; i < file_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 = file_count;
+ 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;
+
+ /*
+ This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end;
+
+ /*
+ 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 *check_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 = NULL;
+
+ /*
+ Offset into .debug_line specified by a DW_AT_stmt_list
+ attribute. */
+ Dwarf_Unsigned line_offset;
+
+ /* These are the fields of the statement program header. */
+ Dwarf_Unsigned total_length;
+ Dwarf_Half version;
+ Dwarf_Unsigned prologue_length;
+ Dwarf_Small minimum_instruction_length;
+ Dwarf_Small default_is_stmt;
+ Dwarf_Sbyte line_base;
+ Dwarf_Small line_range;
+ Dwarf_Small special_opcode_base;
+
+ Dwarf_Small *opcode_length;
+ Dwarf_Small *include_directories;
+ Dwarf_File_Entry file_entries;
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address;
+ Dwarf_Word file;
+ Dwarf_Word line;
+ Dwarf_Word column;
+ Dwarf_Bool is_stmt;
+ Dwarf_Bool basic_block;
+ Dwarf_Bool end_sequence;
+
+ /*
+ 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, file_entry_count, include_directories_count;
+
+ /*
+ This is the current opcode read from the statement program. */
+ Dwarf_Small opcode;
+
+ /*
+ 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;
+
+ /*
+ This is a pointer to the current line being added to the line
+ matrix. */
+ Dwarf_Line curr_line;
+
+ /*
+ 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;
+ Dwarf_Word leb128_length;
+ Dwarf_Sword advance_line;
+
+ /*
+ This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc;
+
+ /*
+ 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;
+ Dwarf_Small ext_opcode;
+
+ /*
+ 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, head_chain = NULL, curr_chain;
+
+ /*
+ This points to a block of Dwarf_Lines, a pointer to which is
+ returned in linebuf. */
+ Dwarf_Line *block_line;
+
+ /* The Dwarf_Debug this die belongs to. */
+ Dwarf_Debug dbg;
+ int resattr;
+ int lres;
+ int local_length_size = 0;
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ int local_extension_size = 0;
+
+ int res;
+
+ /* ***** 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_index,
+ &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;
+ }
+
+
+
+ lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+
+ if (line_offset >= dbg->de_debug_line_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ line_ptr = dbg->de_debug_line + 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;
+ char *cdir;
+
+ 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);
+ }
+
+ /*
+ Following is a straightforward decoding of the statement
+ program prologue information. */
+ /* 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;
+ if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
+ line_ptr, local_length_size);
+ line_ptr += local_length_size;
+ check_line_ptr = line_ptr;
+
+ minimum_instruction_length = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ default_is_stmt = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ line_base = *(Dwarf_Sbyte *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
+
+ line_range = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ special_opcode_base = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ opcode_length = (Dwarf_Small *)
+ alloca(sizeof(Dwarf_Small) * special_opcode_base);
+ for (i = 1; i < special_opcode_base; i++) {
+ opcode_length[i] = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+ }
+
+ include_directories_count = 0;
+ include_directories = line_ptr;
+ while ((*(char *) line_ptr) != '\0') {
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ include_directories_count++;
+ }
+ line_ptr++;
+
+ file_entry_count = 0;
+ file_entries = prev_file_entry = NULL;
+ while (*(char *) line_ptr != '\0') {
+
+ cur_file_entry = (Dwarf_File_Entry)
+ _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
+ if (cur_file_entry == NULL) {
+ _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++;
+ }
+ line_ptr++;
+
+ if (line_ptr != check_line_ptr + prologue_length) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* 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_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Initialize the state machine. */
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+
+ /* 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, special_opcode_base,
+ opcode_length, line_ptr);
+
+
+
+ if (type == LOP_DISCARD) {
+ /* 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) */
+
+ opcode = opcode - special_opcode_base;
+ address = address + minimum_instruction_length *
+ (opcode / line_range);
+ line = line + line_base + opcode % line_range;
+
+ if (dolines) {
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ _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;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ _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 (opcode_length[DW_LNS_copy] != 0) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ if (dolines) {
+
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg,
+ DW_DLA_LINE,
+ 1);
+ if (curr_line == NULL) {
+ _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;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ _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;
+ break;
+ }
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_advance_pc] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ leb128_num = (Dwarf_Word) utmp2;
+ address =
+ address +
+ minimum_instruction_length * leb128_num;
+ break;
+ }
+
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp;
+
+ if (opcode_length[DW_LNS_advance_line] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_SWORD(line_ptr, stmp)
+ advance_line = (Dwarf_Sword) stmp;
+ line = line + advance_line;
+ break;
+ }
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_set_file] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ file = (Dwarf_Word) utmp2;
+ break;
+ }
+
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_set_column] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ column = (Dwarf_Word) utmp2;
+ break;
+ }
+
+ case DW_LNS_negate_stmt:{
+ if (opcode_length[DW_LNS_negate_stmt] != 0) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ is_stmt = !is_stmt;
+ break;
+ }
+
+ case DW_LNS_set_basic_block:{
+ if (opcode_length[DW_LNS_set_basic_block] != 0) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ basic_block = true;
+ break;
+ }
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - special_opcode_base;
+ address = address + minimum_instruction_length *
+ (opcode / line_range);
+
+ break;
+ }
+
+ case DW_LNS_fixed_advance_pc:{
+ if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ 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_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 =
+ 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;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ _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 = default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+
+ break;
+ }
+
+ case DW_LNE_set_address:{
+ if (instr_length - 1 == dbg->de_pointer_size) {
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr, dbg->de_pointer_size);
+ if (doaddrs) {
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg,
+ DW_DLA_LINE,
+ 1);
+ if (curr_line == NULL) {
+ _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;
+
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ _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 += dbg->de_pointer_size;
+ } else {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_SET_ADDR_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ 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_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:{
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_EXT_OPCODE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ }
+ }
+
+ block_line = (Dwarf_Line *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
+ if (block_line == NULL) {
+ _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 = include_directories;
+ line_context->lc_include_directories_count =
+ include_directories_count;
+ line_context->lc_line_count = line_count;
+ line_context->lc_compilation_directory = comp_dir;
+ line_context->lc_dbg = dbg;
+ *count = line_count;
+
+ *linebuf = block_line;
+ return (DW_DLV_OK);
+}
+
+int
+dwarf_srclines(Dwarf_Die die,
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed * linecount, Dwarf_Error * error)
+{
+ Dwarf_Signed count;
+ int res;
+
+ res = _dwarf_internal_srclines(die, linebuf,
+ &count, /* addrlist= */ false,
+ /* linelist= */ true, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ *linecount = count;
+ return res;
+}
+
+
+
+
+
+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;
+}
+
+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;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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;
+ Dwarf_File_Entry file_entry;
+ Dwarf_Small *name_buffer;
+ Dwarf_Small *include_directories;
+ Dwarf_Debug dbg;
+ unsigned int comp_dir_len;
+
+ 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);
+ }
+
+ file_entry = line->li_context->lc_file_entries;
+ 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);
+ }
+
+ if (*(char *) file_entry->fi_file_name == '/') {
+ *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;
+ }
+
+ name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING,
+ (*include_directories == '/' ?
+ 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_directories != '/') {
+ 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 (name_buffer[comp_dir_len - 1] != '/') {
+ /* Here we provide the / separator */
+ name_buffer[comp_dir_len] = '/'; /* overwrite
+ previous nul
+ terminator
+ with needed
+ / */
+ 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;
+}
+
+
+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
+
+
+/*
+ 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_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_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_dealloc(dbg, linebuf[i], DW_DLA_LINE);
+ }
+ dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
+ *returncount = lcount;
+ *offs = loffsets;
+ *addrs = laddrs;
+ return DW_DLV_OK;
+}
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_line.h b/usr/src/tools/ctf/dwarf/common/dwarf_line.h
new file mode 100644
index 0000000000..b824dcb774
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_line.h
@@ -0,0 +1,230 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#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 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. */
+ 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;
+};
+
+
+/*
+ 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 */
+ Dwarf_Sword li_line; /* source file line number. */
+ Dwarf_Half li_column; /* source file column number */
+ Dwarf_Small li_is_stmt; /* indicate start of stmt */
+ Dwarf_Small li_basic_block; /* indicate start basic block */
+ Dwarf_Small li_end_sequence; /* first post sequence
+ instr */
+ } 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);
+
+
+/* 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 process 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.
+*/
+#define LOP_EXTENDED 1
+#define LOP_DISCARD 2
+#define LOP_STANDARD 3
+#define LOP_SPECIAL 4
+
+#define HIGHEST_STANDARD_OPCODE DW_LNS_fixed_advance_pc
+
+#define WHAT_IS_OPCODE(type,opcode,base,opcode_length,line_ptr) \
+ 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_STANDARD_OPCODE+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. \
+ */ \
+ int opcnt = opcode_length[opcode]; \
+ int oc; \
+ 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) \
+ } \
+ /* Done processing this, do not \
+ do the switch , nor do \
+ special op code processing. \
+ */ \
+ 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
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_loc.c b/usr/src/tools/ctf/dwarf/common/dwarf_loc.c
new file mode 100644
index 0000000000..b8f75b90e2
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_loc.c
@@ -0,0 +1,912 @@
+/*
+
+ Copyright (C) 2000,2003 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include "dwarf_loc.h"
+
+
+/*
+ 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_Addr lowpc,
+ Dwarf_Addr highpc, Dwarf_Error * error)
+{
+ /* Size of the block containing the location expression. */
+ Dwarf_Unsigned loc_len;
+
+ /* Sweeps the block containing the location expression. */
+ Dwarf_Small *loc_ptr;
+
+ /* Current location operator. */
+ Dwarf_Small atom;
+
+ /* Offset of current operator from start of block. */
+ Dwarf_Unsigned offset;
+
+ /* Operands of current location operator. */
+ Dwarf_Unsigned operand1, operand2;
+
+ /* Used to chain the Dwarf_Loc_Chain_s structs. */
+ Dwarf_Loc_Chain curr_loc, prev_loc, head_loc = NULL;
+
+ /* Count of the number of location operators. */
+ Dwarf_Unsigned op_count;
+
+ /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */
+ Dwarf_Loc *block_loc;
+
+ /* Dwarf_Locdesc pointer to be returned. */
+ Dwarf_Locdesc *locdesc;
+
+ Dwarf_Word leb128_length;
+ Dwarf_Unsigned i;
+
+ /* ***** 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, dbg->de_pointer_size);
+ loc_ptr += dbg->de_pointer_size;
+ offset += dbg->de_pointer_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;
+ 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);
+ 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);
+ 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;
+
+ 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_Error * error)
+{
+ Dwarf_Small *beg = dbg->de_debug_loc + sec_offset;
+ int address_size = dbg->de_pointer_size;
+
+ 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_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_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_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;
+
+ return DW_DLV_OK;
+
+}
+static int
+_dwarf_get_loclist_count(Dwarf_Debug dbg,
+ Dwarf_Off loclist_offset,
+ 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, 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_Half * form_ret, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Half form = 0;
+ int blkres;
+
+ 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);
+ }
+
+ 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 secload = 0;
+ int blkres = dwarf_formudata(attr, loclist_offset, error);
+
+ if (blkres != DW_DLV_OK) {
+ return (blkres);
+ }
+
+ if (!dbg->de_debug_loc) {
+ secload = _dwarf_load_section(dbg,
+ dbg->de_debug_loc_index,
+ &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;
+
+ int blkres;
+ int setup_res;
+
+ /* ***** BEGIN CODE ***** */
+ setup_res = _dwarf_setup_loc(attr, &dbg, &form, error);
+ if (setup_res != DW_DLV_OK) {
+ return setup_res;
+ }
+ /* 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 (form == DW_FORM_data4 || form == DW_FORM_data8) {
+
+ /* A reference to .debug_loc, with an offset in .debug_loc of a
+ loclist */
+ Dwarf_Unsigned loclist_offset = 0;
+ int off_res;
+ int count_res;
+ 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,
+ &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, error);
+ if (blkres != DW_DLV_OK) {
+ _dwarf_cleanup_llbuf(dbg, llbuf, lli);
+ return (blkres);
+ }
+ locdesc = _dwarf_get_locdesc(dbg, &loc_block,
+ 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,
+ 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;
+
+ int blkres;
+ int setup_res;
+
+ /* ***** BEGIN CODE ***** */
+ setup_res = _dwarf_setup_loc(attr, &dbg, &form, error);
+ if (setup_res != DW_DLV_OK) {
+ return setup_res;
+ }
+ /* 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 (form == DW_FORM_data4 || form == DW_FORM_data8) {
+
+ /* A reference to .debug_loc, with an offset in .debug_loc of a
+ loclist */
+ Dwarf_Unsigned loclist_offset = 0;
+ int off_res;
+
+ 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, 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. FIXME: doing this once
+ is wrong, needs to handle low/hi pc sets. */
+ locdesc = _dwarf_get_locdesc(dbg, &loc_block, 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.
+
+*/
+
+ /*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;
+ Dwarf_Addr highpc;
+ int res;
+
+ if (!dbg->de_debug_loc) {
+ int secload = _dwarf_load_section(dbg,
+ dbg->de_debug_loc_index,
+ &dbg->de_debug_loc,
+ error);
+
+ if (secload != DW_DLV_OK) {
+ return secload;
+ }
+ }
+
+ res = _dwarf_read_loc_section(dbg,
+ &b, &lowpc, &highpc, offset, 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
new file mode 100644
index 0000000000..c79921f64c
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_loc.h
@@ -0,0 +1,46 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+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
new file mode 100644
index 0000000000..5c8aace1ec
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_macro.c
@@ -0,0 +1,409 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <limits.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.
+*/
+static Dwarf_Signed *st_base;
+static long max;
+static long next_to_use;
+static int was_fault = 0;
+
+#define STARTERMAX 10
+static void
+_dwarf_reset_index_stack(void)
+{
+ next_to_use = 0;
+ was_fault = 0;
+}
+static int
+_dwarf_mac_push_index(Dwarf_Debug dbg, Dwarf_Signed indx)
+{
+ Dwarf_Signed *newbase;
+
+ if (next_to_use >= max) {
+ long new_size;
+
+ if (max == 0) {
+ max = STARTERMAX;
+ }
+ new_size = 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 */
+ was_fault = 1;
+ return DW_DLV_ERROR;
+ }
+ memcpy(newbase, st_base, next_to_use * sizeof(Dwarf_Signed));
+ dwarf_dealloc(dbg, st_base, DW_DLA_STRING);
+ st_base = newbase;
+ max = new_size;
+ }
+ st_base[next_to_use] = indx;
+ ++next_to_use;
+ return DW_DLV_OK;
+}
+static Dwarf_Signed
+_dwarf_mac_pop_index(void)
+{
+ if (was_fault) {
+ return -1;
+ }
+ if (next_to_use > 0) {
+ next_to_use--;
+ return (*(st_base + next_to_use));
+ }
+ 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;
+ Dwarf_Small *pnext;
+ Dwarf_Unsigned endloc;
+ unsigned char uc;
+ unsigned long depth;
+
+ int res;
+
+ /* count space used by strings */
+ unsigned long str_space = 0;
+ int done = 0;
+ unsigned long space_needed;
+ unsigned long string_offset;
+ Dwarf_Small *return_data;
+ Dwarf_Small *pdata;
+ unsigned long final_count = 0;
+ Dwarf_Signed fileindex = -1;
+ Dwarf_Small *latest_str_loc;
+
+ unsigned long count;
+ unsigned long max_count = (unsigned long) maximum_count;
+
+ _dwarf_reset_index_stack();
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_macinfo_index,
+ &dbg->de_debug_macinfo,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ macro_base = dbg->de_debug_macinfo;
+ if (macro_base == NULL) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ if (macro_offset >= dbg->de_debug_macinfo_size) {
+ 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_size) {
+ if (endloc == dbg->de_debug_macinfo_size) {
+ /* normal: found last entry */
+ return DW_DLV_NO_ENTRY;
+ }
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+ 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_size) {
+ _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_size) {
+ _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_size) {
+ _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_size) {
+ _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;
+ }
+ break; /* no string or number here */
+ case 0:
+ /* end of cu's entries */
+ done = 1;
+ break;
+ default:
+ _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_size) {
+ done = 1;
+ } else if (endloc > dbg->de_debug_macinfo_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ if (count == 0) {
+ _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) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
+ return (DW_DLV_ERROR);
+ }
+ pnext = macro_base + macro_offset;
+
+ done = 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_size) {
+ _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_size) {
+ _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_size) {
+ _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 */
+ v1 = _dwarf_decode_u_leb128(pnext, &len);
+ pdmd->dmd_lineno = v1;
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
+ _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_mac_push_index(dbg, fileindex);
+ /* 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_size) {
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ break;
+
+ case DW_MACINFO_end_file:
+ fileindex = _dwarf_mac_pop_index();
+ break; /* no string or number here */
+ case 0:
+ /* end of cu's entries */
+ done = 1;
+ break;
+ default:
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ /* bogus macinfo! */
+ }
+ }
+ *entry_count = count;
+ *details = (Dwarf_Macro_Details *) return_data;
+
+ 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
new file mode 100644
index 0000000000..a54923dd67
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_macro.h
@@ -0,0 +1,44 @@
+/*
+
+ 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., 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
+
+*/
+
+
+/*
+
+
+ dwarf_macro.h
+
+ $Revision: 1.3 $ $Date: 2001/09/18 19:23:55 $
+
+*/
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_opaque.h b/usr/src/tools/ctf/dwarf/common/dwarf_opaque.h
new file mode 100644
index 0000000000..5873259df8
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_opaque.h
@@ -0,0 +1,269 @@
+/*
+
+ Copyright (C) 2000,2002,2003 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
+
+*/
+
+#include <stddef.h>
+
+
+struct Dwarf_Die_s {
+ /*
+ Points to the start of the portion corresponding to this Die in
+ the .debug_info section. */
+ Dwarf_Byte_Ptr di_debug_info_ptr;
+
+ Dwarf_Abbrev_List di_abbrev_list;
+
+ /* Points to cu context for this die. */
+ Dwarf_CU_Context di_cu_context;
+};
+
+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.
+
+ **Updated by dwarf_next_cu_header in dwarf_die_deliv.c
+*/
+struct Dwarf_CU_Context_s {
+ Dwarf_Debug cc_dbg;
+ Dwarf_Word cc_length;
+ Dwarf_Small cc_length_size;
+ Dwarf_Small cc_extension_size;
+ Dwarf_Half cc_version_stamp;
+ Dwarf_Sword cc_abbrev_offset;
+ Dwarf_Small cc_address_size;
+ 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;
+};
+
+
+struct Dwarf_Debug_s {
+ dwarf_elf_handle de_elf; /* see de_elf_must_close at end of struct */
+ unsigned int de_nelfsecs;
+
+ Dwarf_Unsigned de_access;
+ 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;
+ struct simple_malloc_record_s * de_simple_malloc_current;
+#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;
+ /*
+ 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;
+
+ Dwarf_Small *de_debug_info;
+ Dwarf_Small *de_debug_abbrev;
+ Dwarf_Small *de_debug_line;
+ Dwarf_Small *de_debug_loc;
+ Dwarf_Small *de_debug_aranges;
+ Dwarf_Small *de_debug_macinfo;
+ Dwarf_Small *de_debug_pubnames;
+ Dwarf_Small *de_debug_str;
+ Dwarf_Small *de_debug_frame;
+ Dwarf_Small *de_debug_frame_eh_gnu; /* gnu for the g++ eh_frame
+ section */
+
+ Dwarf_Small *de_debug_funcnames;
+ Dwarf_Small *de_debug_typenames;
+ Dwarf_Small *de_debug_varnames;
+ Dwarf_Small *de_debug_weaknames;
+
+ Dwarf_Unsigned de_debug_info_size;
+ Dwarf_Unsigned de_debug_abbrev_size;
+ Dwarf_Unsigned de_debug_line_size;
+ Dwarf_Unsigned de_debug_loc_size;
+ Dwarf_Unsigned de_debug_aranges_size;
+ Dwarf_Unsigned de_debug_macinfo_size;
+ Dwarf_Unsigned de_debug_pubnames_size;
+ Dwarf_Unsigned de_debug_str_size;
+
+
+ Dwarf_Unsigned de_debug_frame_size;
+
+ Dwarf_Unsigned de_debug_frame_size_eh_gnu; /* gnu for the g++
+ eh_frame section */
+
+ Dwarf_Unsigned de_debug_funcnames_size;
+ Dwarf_Unsigned de_debug_typenames_size;
+ Dwarf_Unsigned de_debug_varnames_size;
+ Dwarf_Unsigned de_debug_weaknames_size;
+
+ 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() */
+
+ /*
+ The following are used for storing section indicies.
+
+ After a Dwarf_Debug is initialized, a zero for any of
+ these indicies indicates an absent section.
+
+ If the ELF spec is ever changed to permit 32-bit section
+ indicies, these will need to be changed.
+ */
+ Dwarf_Half de_debug_aranges_index;
+ Dwarf_Half de_debug_line_index;
+ Dwarf_Half de_debug_loc_index;
+ Dwarf_Half de_debug_macinfo_index;
+ Dwarf_Half de_debug_pubnames_index;
+ Dwarf_Half de_debug_funcnames_index;
+ Dwarf_Half de_debug_typenames_index;
+ Dwarf_Half de_debug_varnames_index;
+ Dwarf_Half de_debug_weaknames_index;
+ Dwarf_Half de_debug_frame_index;
+ Dwarf_Half de_debug_frame_eh_gnu_index;
+ Dwarf_Half de_debug_str_index;
+ Dwarf_Half de_debug_info_index;
+ Dwarf_Half de_debug_abbrev_index;
+ unsigned char de_big_endian_object; /* non-zero if big-endian
+ object opened. */
+};
+
+typedef struct Dwarf_Chain_s *Dwarf_Chain;
+struct Dwarf_Chain_s {
+ void *ch_item;
+ Dwarf_Chain ch_next;
+};
+
+#define CURRENT_VERSION_STAMP 2
+
+ /* 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,
+ Dwarf_Half,
+ Dwarf_Small **,
+ Dwarf_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
new file mode 100644
index 0000000000..0e31d231ab
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_print_lines.c
@@ -0,0 +1,666 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <time.h>
+#include "dwarf_line.h"
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+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");
+}
+
+static void
+print_line_detail(char *prefix,
+ int opcode,
+ unsigned long long address,
+ unsigned long file,
+ unsigned long line,
+ unsigned long column,
+ int is_stmt, int basic_block, int end_sequence)
+{
+ printf("%-15s %2d 0x%08llx "
+ "%2lu %4lu %2lu %1d %1d %1d\n",
+ prefix,
+ (int) opcode,
+ (long long) 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
+*/
+int
+_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error)
+{
+ /*
+ This pointer is used to scan the portion of the .debug_line
+ section for the current cu. */
+ Dwarf_Small *line_ptr;
+ Dwarf_Small *orig_line_ptr;
+
+ /*
+ This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end;
+
+ /*
+ 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 *check_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 = NULL;
+
+ /*
+ Offset into .debug_line specified by a DW_AT_stmt_list
+ attribute. */
+ Dwarf_Unsigned line_offset;
+
+ /* These are the fields of the statement program header. */
+ Dwarf_Unsigned total_length;
+ Dwarf_Half version;
+ Dwarf_Unsigned prologue_length;
+ Dwarf_Small minimum_instruction_length;
+ Dwarf_Small default_is_stmt;
+ Dwarf_Sbyte line_base;
+ Dwarf_Small line_range;
+ Dwarf_Small opcode_base;
+
+ Dwarf_Small *opcode_length;
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address;
+ Dwarf_Word file;
+ Dwarf_Word line;
+ Dwarf_Word column;
+ Dwarf_Bool is_stmt;
+ Dwarf_Bool basic_block;
+ Dwarf_Bool end_sequence;
+
+ Dwarf_Sword i, file_entry_count, include_directories_count;
+
+ /*
+ This is the current opcode read from the statement program. */
+ Dwarf_Small opcode;
+
+ /*
+ 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;
+
+
+ /*
+ 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;
+ Dwarf_Word leb128_length;
+ Dwarf_Sword advance_line;
+
+ /*
+ This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc;
+
+ /* This is the length of an extended opcode instr. */
+ Dwarf_Word instr_length;
+ Dwarf_Small ext_opcode;
+ int local_length_size;
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ int local_extension_size;
+
+ /* The Dwarf_Debug this die belongs to. */
+ Dwarf_Debug dbg;
+ int resattr;
+ int lres;
+
+ int res;
+
+ /* ***** 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_index,
+ &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;
+ }
+
+
+
+ lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+
+ if (line_offset >= dbg->de_debug_line_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ orig_line_ptr = dbg->de_debug_line;
+ line_ptr = dbg->de_debug_line + 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;
+ char *cdir;
+
+ 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);
+ }
+
+ /*
+ Following is a straightforward decoding of the statement
+ program prologue information. */
+
+ /* 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;
+ if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ printf("total line info length %ld bytes, "
+ "line offset 0x%llx %lld\n",
+ (long) total_length,
+ (long long) line_offset, (long long) line_offset);
+ printf("compilation_directory %s\n",
+ comp_dir ? ((char *) comp_dir) : "");
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
+ line_ptr, local_length_size);
+ line_ptr += local_length_size;
+ check_line_ptr = line_ptr;
+
+ minimum_instruction_length = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ default_is_stmt = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ line_base = *(Dwarf_Sbyte *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
+
+ line_range = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ opcode_base = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+ printf(" min instruction length %d\n",
+ (int) minimum_instruction_length);
+ printf(" default is stmt %d\n", (int) default_is_stmt);
+ printf(" line base %d\n", (int) line_base);
+ printf(" line_range %d\n", (int) line_range);
+
+ opcode_length = (Dwarf_Small *)
+ alloca(sizeof(Dwarf_Small) * opcode_base);
+
+ for (i = 1; i < opcode_base; i++) {
+ opcode_length[i] = *(Dwarf_Small *) line_ptr;
+ printf(" opcode[%d] length %d\n", (int) i,
+ (int) opcode_length[i]);
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+ }
+
+ include_directories_count = 0;
+ while ((*(char *) line_ptr) != '\0') {
+ printf(" include dir[%d] %s\n",
+ (int) include_directories_count, line_ptr);
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ include_directories_count++;
+ }
+ line_ptr++;
+
+ file_entry_count = 0;
+ while (*(char *) line_ptr != '\0') {
+
+ Dwarf_Unsigned tlm2;
+ Dwarf_Unsigned di;
+ Dwarf_Unsigned fl;
+
+ printf(" file[%d] %s\n",
+ (int) file_entry_count, (char *) 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;
+
+ tlm2 = _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(" 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);
+
+
+ file_entry_count++;
+ }
+ line_ptr++;
+
+ if (line_ptr != check_line_ptr + prologue_length) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* 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_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ printf(" statement prog offset in section: %lld 0x%llx\n",
+ (long long) (line_ptr - orig_line_ptr),
+ (long long) (line_ptr - orig_line_ptr));
+
+ /* Initialize the state machine. */
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+
+ print_line_header();
+ /* Start of statement program. */
+ while (line_ptr < line_ptr_end) {
+ int type;
+
+ printf(" [0x%06llx] ", (long long) (line_ptr - orig_line_ptr));
+ opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ /* 'type' is the output */
+ WHAT_IS_OPCODE(type, opcode, opcode_base,
+ opcode_length, line_ptr);
+
+
+
+ if (type == LOP_DISCARD) {
+ /* 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 - opcode_base;
+ address = address + minimum_instruction_length *
+ (opcode / line_range);
+ line = line + line_base + opcode % line_range;
+
+ sprintf(special, "Specialop %3u", origop);
+ print_line_detail(special,
+ opcode, address, (int) file, line, column,
+ is_stmt, basic_block, end_sequence);
+
+ basic_block = false;
+
+ } else if (type == LOP_STANDARD) {
+ switch (opcode) {
+
+ case DW_LNS_copy:{
+ if (opcode_length[DW_LNS_copy] != 0) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ print_line_detail("DW_LNS_copy",
+ opcode, address, file, line,
+ column, is_stmt, basic_block,
+ end_sequence);
+
+ basic_block = false;
+ break;
+ }
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_advance_pc] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ printf("DW_LNS_advance_pc val %lld 0x%llx\n",
+ (long long) (Dwarf_Word) utmp2,
+ (long long) (Dwarf_Word) utmp2);
+ leb128_num = (Dwarf_Word) utmp2;
+ address =
+ address +
+ minimum_instruction_length * leb128_num;
+ break;
+ }
+
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp;
+
+ if (opcode_length[DW_LNS_advance_line] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_SWORD(line_ptr, stmp)
+ advance_line = (Dwarf_Sword) stmp;
+ printf("DW_LNS_advance_line val %lld 0x%llx\n",
+ (long long) advance_line,
+ (long long) advance_line);
+ line = line + advance_line;
+ break;
+ }
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_set_file] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ 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;
+
+ if (opcode_length[DW_LNS_set_column] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ column = (Dwarf_Word) utmp2;
+ printf("DW_LNS_set_column val %lld 0x%llx\n",
+ (long long) column, (long long) column);
+ break;
+ }
+
+ case DW_LNS_negate_stmt:{
+ if (opcode_length[DW_LNS_negate_stmt] != 0) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ is_stmt = !is_stmt;
+ printf("DW_LNS_negate_stmt\n");
+ break;
+ }
+
+ case DW_LNS_set_basic_block:{
+ if (opcode_length[DW_LNS_set_basic_block] != 0) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ printf("DW_LNS_set_basic_block\n");
+ basic_block = true;
+ break;
+ }
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - opcode_base;
+ address = address + minimum_instruction_length *
+ (opcode / line_range);
+
+ printf("DW_LNS_const_add_pc new address 0x%llx\n",
+ (long long) address);
+ break;
+ }
+
+ case DW_LNS_fixed_advance_pc:{
+ if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ 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 %lld 0x%llx"
+ " new address 0x%llx\n",
+ (long long) fixed_advance_pc,
+ (long long) fixed_advance_pc,
+ (long long) address);
+ 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;
+
+ print_line_detail("DW_LNE_end_sequence extended",
+ opcode, address, file, line,
+ column, is_stmt, basic_block,
+ end_sequence);
+
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+
+ break;
+ }
+
+ case DW_LNE_set_address:{
+ if (instr_length - 1 == dbg->de_pointer_size) {
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr, dbg->de_pointer_size);
+
+ line_ptr += dbg->de_pointer_size;
+ printf("DW_LNE_set_address address 0x%llx\n",
+ (long long) address);
+ } else {
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_SET_ADDR_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ break;
+ }
+
+ case DW_LNE_define_file:{
+
+
+ Dwarf_Small *fn;
+ Dwarf_Signed di;
+ Dwarf_Signed tlm;
+ Dwarf_Unsigned fl;
+
+ 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:{
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_EXT_OPCODE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ }
+ }
+
+ return (DW_DLV_OK);
+}
+
+/*
+ Caller passes in compilation unit DIE.
+*/
+int
+_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
+{
+ int res;
+
+ res = _dwarf_internal_printlines(die, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ return res;
+}
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_query.c b/usr/src/tools/ctf/dwarf/common/dwarf_query.c
new file mode 100644
index 0000000000..8573f4be9c
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_query.c
@@ -0,0 +1,609 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_die_deliv.h"
+
+int
+dwarf_get_address_size(Dwarf_Debug dbg,
+ Dwarf_Half * ret_addr_size, Dwarf_Error * error)
+{
+ Dwarf_Half address_size;
+
+ if (dbg == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ /* length size same as address size */
+ address_size = dbg->de_pointer_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);
+ 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;
+
+ 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 -
+ cu_context->cc_debug_info_offset);
+ 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;
+ Dwarf_Half attr;
+ Dwarf_Half attr_form;
+ Dwarf_Byte_Ptr abbrev_ptr;
+ Dwarf_Abbrev_List abbrev_list;
+ Dwarf_Attribute new_attr;
+ Dwarf_Attribute head_attr = NULL, curr_attr;
+ Dwarf_Attribute *attr_ptr;
+ Dwarf_Debug dbg;
+ Dwarf_Byte_Ptr info_ptr;
+
+ 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;
+
+ info_ptr += _dwarf_get_size_of_val(dbg, attr_form, info_ptr,
+ die->di_cu_context->
+ cc_length_size);
+
+ 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;
+ Dwarf_Abbrev_List abbrev_list;
+ Dwarf_Half curr_attr;
+ Dwarf_Half curr_attr_form;
+ Dwarf_Byte_Ptr info_ptr;
+
+ 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, 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;
+ Dwarf_Debug dbg;
+ Dwarf_Byte_Ptr info_ptr;
+ Dwarf_Unsigned string_offset;
+ int res;
+
+ 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_size) {
+ _dwarf_error(dbg, error, DW_DLE_STRING_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_str_index,
+ &dbg->de_debug_str,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ *ret_name = (char *) (dbg->de_debug_str + 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;
+
+ 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;
+ Dwarf_Attribute attrib;
+ Dwarf_Byte_Ptr info_ptr;
+ 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) {
+ 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;
+ Dwarf_Byte_Ptr info_ptr;
+ Dwarf_Half attr_form;
+ Dwarf_Debug dbg;
+
+ CHECK_DIE(die, DW_DLV_ERROR)
+
+ dbg = die->di_cu_context->cc_dbg;
+ 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, dbg->de_pointer_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;
+ Dwarf_Byte_Ptr info_ptr;
+ Dwarf_Half attr_form;
+ Dwarf_Debug dbg;
+
+ CHECK_DIE(die, DW_DLV_ERROR)
+
+ dbg = die->di_cu_context->cc_dbg;
+ 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, dbg->de_pointer_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;
+ 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;
+ int res;
+
+ 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;
+ int res;
+
+ 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;
+ int res;
+
+ 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;
+ int res;
+
+ 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;
+
+ CHECK_DIE(die, DW_DLV_ERROR)
+
+ attroff = (attr->ar_debug_info_ptr -
+ die->di_cu_context->cc_dbg->de_debug_info);
+ *offset = attroff;
+ return DW_DLV_OK;
+}
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c b/usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c
new file mode 100644
index 0000000000..64b08029ee
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_sort_line.c
@@ -0,0 +1,727 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_line.h"
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#include <malloc.h>
+
+#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 */
+ int ala_entry_num; /* to guarantee stable sort */
+ struct a_line_area *ala_next;
+};
+
+
+
+/*
+ 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.
+
+
+*/
+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. */
+}
+
+
+/*
+ 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;
+
+ /*
+ 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 *check_line_ptr;
+
+ Dwarf_Small *orig_line_ptr;
+
+ /* These are the fields of the statement program header. */
+ Dwarf_Unsigned total_length;
+ Dwarf_Half version;
+ Dwarf_Unsigned prologue_length;
+ Dwarf_Small minimum_instruction_length;
+ Dwarf_Small default_is_stmt;
+ Dwarf_Sbyte line_base;
+ Dwarf_Small line_range;
+ Dwarf_Small opcode_base;
+ struct Dwarf_Debug_s dbg_data;
+ Dwarf_Debug dbg = &dbg_data;
+
+ Dwarf_Small *opcode_length = 0;
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address;
+ Dwarf_Word line;
+ Dwarf_Bool is_stmt;
+
+ 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;
+
+ Dwarf_Sword i;
+ Dwarf_Sword file_entry_count;
+ Dwarf_Sword include_directories_count;
+
+ /*
+ This is the current opcode read from the statement program. */
+ Dwarf_Small opcode;
+
+
+ /*
+ 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;
+ Dwarf_Word leb128_length;
+ Dwarf_Sword advance_line;
+
+ /*
+ This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc;
+
+ /* This is the length of an extended opcode instr. */
+ Dwarf_Word instr_length;
+ Dwarf_Small ext_opcode;
+
+
+
+ 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);
+ }
+
+ READ_UNALIGNED(dbg, total_length, Dwarf_Unsigned,
+ line_ptr, length_size);
+ line_ptr += length_size;
+ line_ptr_end = line_ptr + total_length;
+ if (line_ptr_end > line_ptr + remaining_bytes) {
+ *err_code = DW_DLE_DEBUG_LINE_LENGTH_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ *new_line_ptr = line_ptr_end;
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ *err_code = DW_DLE_VERSION_STAMP_ERROR;
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
+ line_ptr, length_size);
+ line_ptr += length_size;
+ check_line_ptr = line_ptr;
+
+ minimum_instruction_length = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ default_is_stmt = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ line_base = *(Dwarf_Sbyte *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
+
+ line_range = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ opcode_base = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ opcode_length = (Dwarf_Small *)
+ alloca(sizeof(Dwarf_Small) * opcode_base);
+ for (i = 1; i < opcode_base; i++) {
+ opcode_length[i] = *(Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+ }
+
+ include_directories_count = 0;
+ while ((*(char *) line_ptr) != '\0') {
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ include_directories_count++;
+ }
+ line_ptr++;
+
+ file_entry_count = 0;
+ while (*(char *) line_ptr != '\0') {
+
+
+ /* filename = (Dwarf_Small *)line_ptr; */
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+
+ /* dir_index = */
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ /* time_last_mod = */
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ /* file_length = */
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ file_entry_count++;
+ }
+ line_ptr++;
+
+ if (line_ptr != check_line_ptr + prologue_length) {
+ *err_code = DW_DLE_LINE_PROLOG_LENGTH_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ /* Initialize the state machine. */
+ address = 0;
+ /* file = 1; */
+ line = 1;
+ /* column = 0; */
+ is_stmt = default_is_stmt;
+ /* basic_block = false; */
+ /* end_sequence = false; */
+
+ /* 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, opcode_base,
+ opcode_length, line_ptr);
+
+
+
+ if (type == LOP_DISCARD) {
+ /* do nothing, necessary ops done */
+ } else if (type == LOP_SPECIAL) {
+ opcode = opcode - opcode_base;
+ address = address + minimum_instruction_length *
+ (opcode / line_range);
+ line = line + line_base + opcode % line_range;
+
+ /* basic_block = false; */
+
+
+ } else if (type == LOP_STANDARD) {
+
+
+ switch (opcode) {
+
+
+ case DW_LNS_copy:{
+ if (opcode_length[DW_LNS_copy] != 0) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+
+ /* basic_block = false; */
+ break;
+ }
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_advance_pc] != 1) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ leb128_num = (Dwarf_Word) utmp2;
+ address =
+ address +
+ minimum_instruction_length * leb128_num;
+ break;
+ }
+
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp;
+
+ if (opcode_length[DW_LNS_advance_line] != 1) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_SWORD(line_ptr, stmp)
+ advance_line = (Dwarf_Sword) stmp;
+ line = line + advance_line;
+ break;
+ }
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_set_file] != 1) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ /* file = (Dwarf_Word)utmp2; */
+ break;
+ }
+
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2;
+
+ if (opcode_length[DW_LNS_set_column] != 1) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2)
+ /* column = (Dwarf_Word)utmp2; */
+ break;
+ }
+
+ case DW_LNS_negate_stmt:{
+ if (opcode_length[DW_LNS_negate_stmt] != 0) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ is_stmt = !is_stmt;
+ break;
+ }
+
+ case DW_LNS_set_basic_block:{
+ if (opcode_length[DW_LNS_set_basic_block] != 0) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ /* basic_block = true; */
+ break;
+ }
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - opcode_base;
+ address = address + minimum_instruction_length *
+ (opcode / line_range);
+
+ break;
+ }
+
+ case DW_LNS_fixed_advance_pc:{
+ if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ 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 = default_is_stmt;
+ /* basic_block = false; */
+ /* end_sequence = false; */
+
+ break;
+ }
+
+ case DW_LNE_set_address:{
+ if (instr_length - 1 == length_size) {
+ 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 = alloca(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;
+ } else {
+ *err_code = DW_DLE_LINE_SET_ADDR_ERROR;
+ return (DW_DLV_ERROR);
+ }
+
+
+ break;
+ }
+
+ case DW_LNE_define_file:{
+
+ break;
+ }
+
+ default:{
+ *err_code = DW_DLE_LINE_EXT_OPCODE_BAD;
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ }
+ }
+
+
+ if (!need_to_sort) {
+ 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) /* final
+ offset */
+ -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) {
+ *err_code = DW_DLE_ALLOC_FAIL;
+ return DW_DLV_ERROR;
+ }
+
+ for (local = area_base, i = 0; local;
+ local = local->ala_next, ++i) {
+
+ ala_array[i] = *local;
+ }
+
+ qsort(ala_array, area_count, sizeof(struct a_line_area), cmpr);
+
+ /* Now we must rearrange the pieces of the line table. */
+
+ start_len = (check_line_ptr + prologue_length) - orig_line_ptr;
+ new_area = malloc(remaining_bytes);
+ if (!new_area) {
+ free(ala_array);
+ *err_code = DW_DLE_ALLOC_FAIL;
+ 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;
+ 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
new file mode 100644
index 0000000000..886174ee8a
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_string.c
@@ -0,0 +1,82 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#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;
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (offset == dbg->de_debug_str_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_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_index,
+ &dbg->de_debug_str,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ *string = (char *) dbg->de_debug_str + 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
new file mode 100644
index 0000000000..dfa2ccaba5
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_stubs.c
@@ -0,0 +1,50 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+
+
+
+ /*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
new file mode 100644
index 0000000000..4e1ab30064
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_types.c
@@ -0,0 +1,123 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#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;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_typenames_index,
+ &dbg->de_debug_typenames,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ return _dwarf_internal_get_pubnames_like_data(dbg, dbg->de_debug_typenames, dbg->de_debug_typenames_size, (Dwarf_Global **) types, /* type
+ punning,
+ Dwarf_Type
+ is never
+ a
+ completed
+ type */
+ ret_type_count,
+ error,
+ DW_DLA_TYPENAME_CONTEXT,
+ DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR);
+
+}
+
+
+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
new file mode 100644
index 0000000000..5fbda38166
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_types.h
@@ -0,0 +1,41 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..df217e3628
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_util.c
@@ -0,0 +1,383 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#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_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:
+ return (dbg->de_pointer_size);
+
+ 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:
+ length = _dwarf_decode_u_leb128(val_ptr, &leb128_length);
+ return (length + leb128_length);
+
+ case DW_FORM_flag:
+ return (1);
+
+ case DW_FORM_ref_udata:
+ _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,
+ 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);
+ }
+}
+
+
+/*
+ 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.
+
+ Returns NULL on error.
+*/
+Dwarf_Abbrev_List
+_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Word code)
+{
+ Dwarf_Debug dbg = cu_context->cc_dbg;
+ Dwarf_Hash_Table hash_table = cu_context->cc_abbrev_hash_table;
+ Dwarf_Word hash_num;
+ Dwarf_Abbrev_List hash_abbrev_list;
+ Dwarf_Abbrev_List abbrev_list;
+ Dwarf_Byte_Ptr abbrev_ptr;
+ Dwarf_Half abbrev_code, abbrev_tag;
+ Dwarf_Half attr_name, attr_form;
+
+ hash_num = code % ABBREV_HASH_TABLE_SIZE;
+ for (hash_abbrev_list = hash_table[hash_num].at_head;
+ hash_abbrev_list != NULL && hash_abbrev_list->ab_code != code;
+ hash_abbrev_list = hash_abbrev_list->ab_next);
+ if (hash_abbrev_list != NULL)
+ return (hash_abbrev_list);
+
+ abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ?
+ cu_context->cc_last_abbrev_ptr :
+ dbg->de_debug_abbrev + cu_context->cc_abbrev_offset;
+
+ /* End of abbrev's for this cu, since abbrev code is 0. */
+ if (*abbrev_ptr == 0) {
+ return (NULL);
+ }
+
+ do {
+ Dwarf_Unsigned utmp;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp)
+ abbrev_code = (Dwarf_Half) utmp;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp)
+ abbrev_tag = (Dwarf_Half) utmp;
+
+ abbrev_list = (Dwarf_Abbrev_List)
+ _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1);
+ if (abbrev_list == NULL)
+ return (NULL);
+
+ hash_num = abbrev_code % ABBREV_HASH_TABLE_SIZE;
+ if (hash_table[hash_num].at_head == NULL) {
+ hash_table[hash_num].at_head =
+ hash_table[hash_num].at_tail = abbrev_list;
+ } else {
+ hash_table[hash_num].at_tail->ab_next = abbrev_list;
+ hash_table[hash_num].at_tail = abbrev_list;
+ }
+
+ abbrev_list->ab_code = abbrev_code;
+ abbrev_list->ab_tag = abbrev_tag;
+
+ abbrev_list->ab_has_child = *(abbrev_ptr++);
+ abbrev_list->ab_abbrev_ptr = abbrev_ptr;
+
+ do {
+ Dwarf_Unsigned utmp3;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp3)
+ attr_name = (Dwarf_Half) utmp3;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp3)
+ attr_form = (Dwarf_Half) utmp3;
+ } 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 ? abbrev_list : 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 + 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;
+
+ /* Testing de_debug_info allows us to avoid testing
+ de_debug_abbrev. One test instead of 2. .debug_info is useless
+ without .debug_abbrev. */
+ if (dbg->de_debug_info) {
+ return DW_DLV_OK;
+ }
+
+ res = _dwarf_load_section(dbg, dbg->de_debug_abbrev_index,
+ &dbg->de_debug_abbrev, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = _dwarf_load_section(dbg, dbg->de_debug_info_index,
+ &dbg->de_debug_info, error);
+ return res;
+
+}
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_util.h b/usr/src/tools/ctf/dwarf/common/dwarf_util.h
new file mode 100644
index 0000000000..146a7d8ee4
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_util.h
@@ -0,0 +1,267 @@
+/*
+
+ Copyright (C) 2000,2003,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., 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
+
+*/
+
+
+
+/*
+ Decodes unsigned leb128 encoded numbers that
+ are assumed to be less than 4 bytes long.
+ Make sure ptr is a pointer to a 1-byte type.
+ Returns UINT_MAX on error.
+
+*/
+#define DECODE_LEB128_UWORD(ptr, value) \
+ { \
+ Dwarf_Word uleblen; \
+ value = _dwarf_decode_u_leb128(ptr,&uleblen); \
+ ptr += uleblen; \
+ }
+
+/*
+ Decodes signed leb128 encoded numbers.
+ Make sure ptr is a pointer to a 1-byte type.
+
+*/
+#define DECODE_LEB128_SWORD(ptr, value) \
+ { \
+ Dwarf_Word sleblen; \
+ value = _dwarf_decode_s_leb128(ptr,&sleblen); \
+ ptr += sleblen; \
+ }
+
+
+/*
+ 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) \
+ if ((*(ptr++) & 0x80) != 0) { \
+ if ((*(ptr++) & 0x80) != 0) { \
+ if ((*(ptr++) & 0x80) != 0) { \
+ if ((*(ptr++) & 0x80) != 0) { \
+ } \
+ } \
+ } \
+ }
+
+
+#define CHECK_DIE(die, error_ret_value) \
+ 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); \
+ }
+
+
+/*
+ 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) \
+ { \
+ BIGGEST_UINT _ltmp = 0; \
+ dbg->de_copy_word( (((char *)(&_ltmp)) + sizeof(_ltmp) - length), \
+ source, length) ; \
+ dest = (desttype)_ltmp; \
+ }
+
+
+/*
+ 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) \
+ if (*(Dwarf_Sbyte *)((char *)&dest + sizeof(dest) - length) < 0) \
+ memcpy((char *)&dest, "\xff\xff\xff\xff\xff\xff\xff\xff", \
+ sizeof(dest) - length)
+#else /* LITTLE ENDIAN */
+
+#define READ_UNALIGNED(dbg,dest,desttype, source, length) \
+ { \
+ BIGGEST_UINT _ltmp = 0; \
+ dbg->de_copy_word( (char *)(&_ltmp) , \
+ source, length) ; \
+ dest = (desttype)_ltmp; \
+ }
+
+
+/*
+ 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) \
+ if (*(Dwarf_Sbyte *)((char *)&dest + (length-1)) < 0) \
+ memcpy((char *)&dest+length, \
+ "\xff\xff\xff\xff\xff\xff\xff\xff", \
+ sizeof(dest) - length)
+
+#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 and w_exten_size (which
+ are really issues only for the dwarfv2.1 64bit extension).
+
+ 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 (yet)).
+
+ 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).
+ Might be a good idea though.
+
+*/
+# define READ_AREA_LENGTH(r_dbg,w_target,r_targtype, \
+ rw_src_data_p,w_length_size,w_exten_size) \
+ 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 */ \
+ 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; \
+ } \
+ }
+
+
+
+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_Small * val_ptr, int v_length_size);
+
+/*
+ This struct is used to build a hash table for the
+ abbreviation codes for a compile-unit.
+*/
+struct Dwarf_Hash_Table_s {
+ Dwarf_Abbrev_List at_head;
+ Dwarf_Abbrev_List at_tail;
+};
+
+Dwarf_Abbrev_List
+_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context,
+ Dwarf_Word 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);
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_vars.c b/usr/src/tools/ctf/dwarf/common/dwarf_vars.c
new file mode 100644
index 0000000000..8e59d520db
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_vars.c
@@ -0,0 +1,123 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#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;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_varnames_index,
+ &dbg->de_debug_varnames,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ return _dwarf_internal_get_pubnames_like_data(dbg, dbg->de_debug_varnames, dbg->de_debug_varnames_size, (Dwarf_Global **) vars, /* type
+ punning,
+ Dwarf_Type
+ is never
+ a
+ completed
+ type */
+ ret_var_count,
+ error,
+ DW_DLA_VAR_CONTEXT,
+ DW_DLE_DEBUG_VARNAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_VARNAMES_VERSION_ERROR);
+}
+
+
+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
new file mode 100644
index 0000000000..b696c2d10b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_vars.h
@@ -0,0 +1,41 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..addd6cfd6f
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_weaks.c
@@ -0,0 +1,122 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#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;
+
+ res =
+ _dwarf_load_section(dbg,
+ dbg->de_debug_weaknames_index,
+ &dbg->de_debug_weaknames,
+ error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ return _dwarf_internal_get_pubnames_like_data(dbg, dbg->de_debug_weaknames, dbg->de_debug_weaknames_size, (Dwarf_Global **) weaks, /* type
+ punning,
+ Dwarf_Type
+ is never
+ a
+ completed
+ type */
+ ret_weak_count,
+ error,
+ DW_DLA_WEAK_CONTEXT,
+ DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR);
+
+}
+
+
+
+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
new file mode 100644
index 0000000000..07d3fdabe9
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_weaks.h
@@ -0,0 +1,41 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..ea030163d6
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/libdwarf.h
@@ -0,0 +1,1602 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ Copyright (C) 2000, 2001, 2002 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
+
+*/
+
+
+#ifndef _LIBDWARF_H
+#define _LIBDWARF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ libdwarf.h
+ $Revision: 1.74 $ $Date: 2002/06/11 17:49:06 $
+
+ 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...
+
+*/
+
+#ifdef __SGI_FAST_LIBELF
+struct elf_sgi;
+typedef struct elf_sgi* dwarf_elf_handle;
+#else
+struct Elf;
+typedef struct Elf* dwarf_elf_handle;
+#endif
+
+#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 */
+#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 */
+#endif
+typedef void* Dwarf_Ptr; /* host machine pointer */
+
+/* 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;
+
+/* Frame description instructions expanded.
+*/
+typedef struct {
+ Dwarf_Small fp_base_op;
+ Dwarf_Small fp_extended_op;
+ Dwarf_Half fp_register;
+ Dwarf_Unsigned fp_offset;
+ Dwarf_Off fp_instr_offset;
+} Dwarf_Frame_Op;
+
+/* DW_REG_TABLE_SIZE must reflect the number of registers
+ *(DW_FRAME_LAST_REG_NUM) as defined in dwarf.h
+ */
+#define DW_REG_TABLE_SIZE 66
+typedef struct {
+ struct {
+ Dwarf_Small dw_offset_relevant;
+ Dwarf_Half dw_regnum;
+ Dwarf_Addr dw_offset;
+ } rules[DW_REG_TABLE_SIZE];
+} Dwarf_Regtable;
+
+/* 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,/* this and drt_second
+ for .word end - begin
+ case */
+ dwarf_drt_second_of_length_pair
+};
+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.
+ 8 for 64bit data */
+ Dwarf_Unsigned drd_offset; /* where the data to reloc is */
+ Dwarf_Unsigned drd_symbol_index;
+};
+
+/* 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*/);
+
+
+/*
+ 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 */
+
+/* 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*/
+
+/* dwarf_init() access flag modifiers
+*/
+#define DW_DLC_SIZE_64 0x40000000 /* 32-bit target */
+#define DW_DLC_SIZE_32 0x20000000 /* 64-bit target */
+
+/* dwarf_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 */
+#define DW_DLC_SYMBOLIC_RELOCATIONS 0x04000000 /* usable with assem output */
+#define DW_DLC_TARGET_BIGENDIAN 0x08000000 /* big endian target */
+#define DW_DLC_TARGET_LITTLEENDIAN 0x00100000 /* little endian target */
+
+/* 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
+#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
+
+ /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */
+#define DW_DLE_LAST 194
+#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 */
+
+/* non-elf initialization */
+int dwarf_init(int /*fd*/,
+ Dwarf_Unsigned /*access*/,
+ Dwarf_Handler /*errhand*/,
+ Dwarf_Ptr /*errarg*/,
+ Dwarf_Debug * /*dbg*/,
+ Dwarf_Error* /*error*/);
+
+/* elf intialization */
+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*/);
+
+/* die traversal operations */
+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 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? */
+int dwarf_dieoffset(Dwarf_Die /*die*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_die_CU_offset(Dwarf_Die /*die*/,
+ Dwarf_Off* /*return_offset*/,
+ 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*/);
+
+/* 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*/);
+
+/* 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*/);
+
+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*/);
+
+/* 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*/);
+
+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_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*/);
+
+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*/);
+
+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*/);
+
+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. */
+int dwarf_get_types(Dwarf_Debug /*dbg*/,
+ Dwarf_Type** /*types*/,
+ Dwarf_Signed * /*number_of_types*/,
+ Dwarf_Error* /*error*/);
+
+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*/);
+
+/* File-scope static variable name operations. */
+int dwarf_get_vars(Dwarf_Debug /*dbg*/,
+ Dwarf_Var** /*vars*/,
+ Dwarf_Signed * /*number_of_vars*/,
+ Dwarf_Error* /*error*/);
+
+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*/);
+
+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) */
+/* Unimplemented. */
+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*/);
+
+
+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*/);
+
+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*/);
+
+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_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*/);
+
+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*/);
+
+int dwarf_expand_frame_instructions(Dwarf_Debug /*dbg*/,
+ 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
+
+int dwarf_get_arange_info(
+ Dwarf_Arange /*arange*/,
+ 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.
+*/
+int _dwarf_print_lines(Dwarf_Die cu_die,Dwarf_Error * /*error*/);
+
+/* _dwarf_ld_sort_lines is for use solely by ld for
+ rearranging 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.
+*/
+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 offsets, for debugging
+ dwarf info
+*/
+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 offsets, for debugging
+ dwarf info
+*/
+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*/);
+
+/* 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*/);
+
+/* 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
+
+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_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_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_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*/);
+
+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*/);
+
+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*/);
+
+/* Operations to create location expressions. */
+Dwarf_P_Expr dwarf_new_expr(Dwarf_P_Debug /*dbg*/, 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 */
+
+
+void dwarf_p_dealloc(void* /*space*/, Dwarf_Unsigned /*type*/);
+
+int dwarf_attr_offset(Dwarf_Die /*die*/,
+ Dwarf_Attribute /*attr of above die*/,
+ Dwarf_Off * /*returns offset thru this ptr */,
+ Dwarf_Error * /*error*/);
+
+
+#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
new file mode 100644
index 0000000000..77d87b41e6
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/libdwarfdefs.h
@@ -0,0 +1,85 @@
+/*
+
+ 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., 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
+
+*/
+
+
+/* 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_SGIDEFS_H)
+#include <sgidefs.h> /* sgidefs.h defines them */
+#define HAVE___UINT32_T 1
+#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 <sys/types.h>
+/* we assume __[u]int32_t and __[u]int64_t defined
+ since __uint32_t defined in the sys/types.h in use */
+#define HAVE___UINT32_T 1
+#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
diff --git a/usr/src/tools/ctf/dwarf/common/mapfile-vers b/usr/src/tools/ctf/dwarf/common/mapfile-vers
new file mode 100644
index 0000000000..54143248d1
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/mapfile-vers
@@ -0,0 +1,199 @@
+#
+# 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_AT_comp_dir;
+ dwarf_add_AT_const_value_signedint;
+ dwarf_add_AT_const_value_string;
+ dwarf_add_AT_const_value_unsignedint;
+ dwarf_add_AT_flag;
+ dwarf_add_AT_location_expr;
+ dwarf_add_AT_name;
+ dwarf_add_AT_producer;
+ 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_arange;
+ dwarf_add_arange_b;
+ 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_child;
+ dwarf_dealloc;
+ dwarf_def_macro;
+ dwarf_die_CU_offset;
+ dwarf_die_link;
+ dwarf_diename;
+ dwarf_dieoffset;
+ dwarf_elf_init;
+ dwarf_end_macro_file;
+ dwarf_errmsg;
+ dwarf_errno;
+ dwarf_expand_frame_instructions;
+ dwarf_expr_current_offset;
+ dwarf_expr_into_block;
+ dwarf_fde_cfa_offset;
+ dwarf_find_macro_value_start;
+ dwarf_finish;
+ dwarf_formaddr;
+ dwarf_formblock;
+ dwarf_formflag;
+ dwarf_formref;
+ dwarf_formsdata;
+ dwarf_formstring;
+ dwarf_formudata;
+ dwarf_func_cu_offset;
+ dwarf_func_die_offset;
+ dwarf_func_name_offsets;
+ dwarf_funcname;
+ dwarf_get_abbrev;
+ dwarf_get_abbrev_children_flag;
+ dwarf_get_abbrev_code;
+ dwarf_get_abbrev_entry;
+ dwarf_get_abbrev_tag;
+ dwarf_get_address_size;
+ dwarf_get_arange;
+ dwarf_get_arange_cu_header_offset;
+ dwarf_get_arange_info;
+ dwarf_get_aranges;
+ 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_elf;
+ dwarf_get_fde_at_pc;
+ dwarf_get_fde_exception_info;
+ dwarf_get_fde_for_die;
+ dwarf_get_fde_info_for_all_regs;
+ dwarf_get_fde_info_for_reg;
+ dwarf_get_fde_instr_bytes;
+ dwarf_get_fde_list;
+ dwarf_get_fde_list_eh;
+ dwarf_get_fde_n;
+ dwarf_get_fde_range;
+ dwarf_get_funcs;
+ dwarf_get_globals;
+ dwarf_get_loclist_entry;
+ dwarf_get_macro_details;
+ dwarf_get_relocation_info;
+ dwarf_get_relocation_info_count;
+ dwarf_get_section_bytes;
+ dwarf_get_str;
+ dwarf_get_types;
+ dwarf_get_vars;
+ dwarf_get_weaks;
+ dwarf_global_cu_offset;
+ dwarf_global_die_offset;
+ dwarf_global_formref;
+ dwarf_global_name_offsets;
+ dwarf_globname;
+ dwarf_hasattr;
+ dwarf_hasform;
+ dwarf_highpc;
+ dwarf_init;
+ 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_n;
+ dwarf_lowpc;
+ dwarf_new_die;
+ dwarf_new_expr;
+ dwarf_new_fde;
+ dwarf_next_cu_header;
+ dwarf_nextglob;
+ dwarf_offdie;
+ dwarf_p_dealloc;
+ dwarf_print_memory_stats;
+ dwarf_producer_finish;
+ dwarf_producer_init;
+ dwarf_producer_init_b;
+ dwarf_reset_section_bytes;
+ dwarf_set_stringcheck;
+ dwarf_siblingof;
+ dwarf_srcfiles;
+ dwarf_srclang;
+ dwarf_srclines;
+ 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_undef_macro;
+ dwarf_var_cu_offset;
+ dwarf_var_die_offset;
+ dwarf_var_name_offsets;
+ dwarf_varname;
+ dwarf_vendor_ext;
+ dwarf_weak_cu_offset;
+ dwarf_weak_die_offset;
+ dwarf_weak_name_offsets;
+ dwarf_weakname;
+ 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
new file mode 100644
index 0000000000..2f85bcd84b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_alloc.c
@@ -0,0 +1,71 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdlib.h>
+
+/*
+ The allocator wants to know which region
+ this is to be in so it can allocate the new space
+ with respect to the right region.
+*/
+ /*ARGSUSED*/
+ Dwarf_Ptr _dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
+{
+ void *sp;
+
+ sp = malloc(size);
+ memset(sp,0, (int) size);
+ return sp;
+}
+
+
+ /*ARGSUSED*/ void
+dwarf_p_dealloc(void *space, Dwarf_Unsigned typ)
+{
+ free(space);
+ return;
+}
+
+
+/* Essentially a stub for now. */
+ /*ARGSUSED*/ void
+_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr)
+{
+ dwarf_p_dealloc(ptr, DW_DLA_STRING);
+}
diff --git a/usr/src/tools/ctf/dwarf/common/pro_alloc.h b/usr/src/tools/ctf/dwarf/common/pro_alloc.h
new file mode 100644
index 0000000000..458d808147
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_alloc.h
@@ -0,0 +1,40 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+Dwarf_Ptr _dwarf_p_get_alloc(Dwarf_P_Debug, Dwarf_Unsigned);
+
+void _dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr);
diff --git a/usr/src/tools/ctf/dwarf/common/pro_arange.c b/usr/src/tools/ctf/dwarf/common/pro_arange.c
new file mode 100644
index 0000000000..292f3d28d0
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_arange.c
@@ -0,0 +1,336 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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
new file mode 100644
index 0000000000..a423f62604
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_arange.h
@@ -0,0 +1,62 @@
+/*
+
+ 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., 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
+
+*/
+
+
+/*
+ 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
new file mode 100644
index 0000000000..f4129884e4
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_die.c
@@ -0,0 +1,390 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#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 new_die, ret_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_tag = tag;
+ 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)
+{
+ int n_nulls; /* to count # of non null neighbors */
+
+ n_nulls = 0;
+ if (parent != NULL) {
+ n_nulls++;
+ new_die->di_parent = parent;
+ if (parent->di_child) { /* got to traverse the child's siblings
+ */
+ Dwarf_P_Die curdie;
+
+ curdie = parent->di_child;
+ while (curdie->di_right)
+ curdie = curdie->di_right;
+ curdie->di_right = new_die; /* attach to sibling list */
+ new_die->di_left = curdie; /* back pointer */
+ } else
+ parent->di_child = new_die;
+ }
+ if (child != NULL) {
+ n_nulls++;
+ new_die->di_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 sibl, lets
+ insert */
+ new_die->di_right = left->di_right;
+ left->di_right = new_die;
+ /* add parent pointer */
+ 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) /* left sibl exists, try inserting */
+ new_die->di_left = right->di_left;
+ 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;
+
+}
+
+/*----------------------------------------------------------------------------
+ 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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
new file mode 100644
index 0000000000..f99752c7e0
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_die.h
@@ -0,0 +1,68 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+/*
+ 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
new file mode 100644
index 0000000000..8c46f1e565
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_encode_nm.c
@@ -0,0 +1,123 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <string.h>
+#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
new file mode 100644
index 0000000000..33a6622a7e
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_encode_nm.h
@@ -0,0 +1,48 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+/* 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
new file mode 100644
index 0000000000..a9e100e496
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_error.c
@@ -0,0 +1,97 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#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
new file mode 100644
index 0000000000..cbafba7718
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_error.h
@@ -0,0 +1,52 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+/* 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
new file mode 100644
index 0000000000..b023d02525
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_expr.c
@@ -0,0 +1,550 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#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];
+ /* Cast of val1 to pointer is ok as if val1 does not point into
+ our (process) address space we are in big trouble anyway
+ (internal error in libdwarf or in libdwarf caller). Compiler
+ may warn about cast to pointer. */
+ WRITE_UNALIGNED(dbg, operand, (const void *)(uintptr_t)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];
+ /* Cast of val1 to pointer is ok as if val1 does not point into
+ our (process) address space we are in big trouble anyway
+ (internal error in libdwarf or in libdwarf caller). Compiler
+ may warn about cast to pointer. */
+ WRITE_UNALIGNED(dbg, operand, (const void *)(uintptr_t) 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;
+
+ 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);
+}
+
+
+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
new file mode 100644
index 0000000000..c187e75269
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_expr.h
@@ -0,0 +1,45 @@
+/*
+
+ 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., 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
+
+*/
+
+
+#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
new file mode 100644
index 0000000000..1448ced6b3
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_finish.c
@@ -0,0 +1,55 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#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);
+ }
+
+ dwarf_p_dealloc((void *) dbg, 0);
+ return 0;
+}
diff --git a/usr/src/tools/ctf/dwarf/common/pro_forms.c b/usr/src/tools/ctf/dwarf/common/pro_forms.c
new file mode 100644
index 0000000000..b3e645e4d4
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_forms.c
@@ -0,0 +1,857 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#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.
+*/
+/* 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 */
+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 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);
+ }
+
+ if (attr != DW_AT_low_pc && attr != DW_AT_high_pc &&
+ attr != DW_AT_MIPS_loop_begin &&
+ attr != DW_AT_MIPS_tail_loop_begin &&
+ attr != DW_AT_MIPS_epilog_begin) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ 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);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = DW_FORM_addr;
+ 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;
+}
+
+
+/*
+ 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:
+ break;
+
+ default:{
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ }
+
+ /*
+ 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_upper_bound:
+ case DW_AT_lower_bound:
+ break;
+
+ default:{
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ }
+
+ /*
+ 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;
+ 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:
+ break;
+
+ default:{
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ }
+
+ /*
+ 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 */
+ 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_sibling:
+ case DW_AT_MIPS_stride:
+ case DW_AT_MIPS_stride_byte:
+ case DW_AT_MIPS_stride_elem:
+ case DW_AT_MIPS_clone_origin:
+ case DW_AT_MIPS_ptr_dopetype:
+ case DW_AT_MIPS_allocatable_dopetype:
+ case DW_AT_MIPS_assumed_shape_dopetype:
+ break;
+
+ default:{
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ 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);
+ }
+
+ 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);
+ }
+
+ 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:
+ case DW_AT_MIPS_has_inlines:
+ case DW_AT_MIPS_assumed_size:
+ break;
+
+ default:{
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ 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);
+ }
+
+ 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:
+ case DW_AT_MIPS_linkage_name:
+ case DW_AT_MIPS_abstract_name:
+ break;
+
+ default:{
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ }
+
+ 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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
new file mode 100644
index 0000000000..e23dce4598
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_frame.c
@@ -0,0 +1,552 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#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 functions 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;
+
+ 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;
+
+
+ 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;
+}
+
+
+/*-------------------------------------------------------------------
+ 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_next = NULL;
+ fde->fde_inst = NULL;
+ fde->fde_n_inst = 0;
+ fde->fde_n_bytes = 0;
+ fde->fde_last_inst = NULL;
+ fde->fde_uwordb_size = dbg->de_offset_size;
+ return fde;
+}
+
+/*------------------------------------------------------------------------
+ Add cfe_offset instruction to fde
+-------------------------------------------------------------------------*/
+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];
+
+ curinst = (Dwarf_P_Frame_Pgm)
+ _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s));
+ if (curinst == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_FPGM_ALLOC,
+ (Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ opc = DW_CFA_offset;
+ regno = reg;
+ if (regno & 0xc0) {
+ DWARF_P_DBG_ERROR(NULL, 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(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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.
+
+*/
+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];
+
+
+ nbytes = 0;
+ ptr = NULL;
+ curinst = (Dwarf_P_Frame_Pgm)
+ _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s));
+ if (curinst == NULL) {
+ _dwarf_p_error(NULL, 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(NULL, 1);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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(NULL, 2);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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(NULL, 4);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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(NULL,
+ sizeof(Dwarf_Unsigned));
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes);
+
+ } else {
+ op = DW_CFA_offset_extended;
+
+ res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
+ buff2, sizeof(buff2));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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_undefined:
+ case DW_CFA_same_value:
+ res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes);
+ break;
+
+ case DW_CFA_register:
+ case DW_CFA_def_cfa:
+ res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+
+ res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
+ buff2, sizeof(buff2));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+
+ ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, 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_register:
+ case DW_CFA_def_cfa_offset:
+ res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes);
+ break;
+
+ default:
+ break;
+ }
+
+ 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 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
new file mode 100644
index 0000000000..b6ef75ae3f
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_frame.h
@@ -0,0 +1,126 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+/*
+ 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;
+};
diff --git a/usr/src/tools/ctf/dwarf/common/pro_funcs.c b/usr/src/tools/ctf/dwarf/common/pro_funcs.c
new file mode 100644
index 0000000000..233e386481
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_funcs.c
@@ -0,0 +1,62 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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
new file mode 100644
index 0000000000..269a5d14c9
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_incl.h
@@ -0,0 +1,73 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#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
+
+
+
+#include "libdwarf.h"
+
+#include "dwarf.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
new file mode 100644
index 0000000000..f4dd526718
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_init.c
@@ -0,0 +1,249 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#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_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_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_DWARF2_99_EXTENSION)
+ /* Revised 64 bit output, using distingushed values. Per 1999
+ dwarf2 revision This produces 64bit extension with ia64 objects.
+
+ Some might want library run time selection of offset size. Not
+ provided here at present. */
+ dbg->de_64bit_extension = (IS_64BIT(dbg) ? 1 : 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);
+ /* 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);
+#elif defined(HAVE_OLD_DWARF2_32BIT_OFFSET)
+ /* This is cygnus 32bit offset, as specified in pure dwarf2 v2.0.0 */
+ 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);
+#else
+ /* MIPS-SGI 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;
+#endif
+ 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(Elf64_Rel) : sizeof(Elf32_Rel);
+#else
+ dbg->de_relocation_record_size = sizeof(Elf32_Rel);
+#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
new file mode 100644
index 0000000000..e6885e40a4
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_line.c
@@ -0,0 +1,300 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#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
new file mode 100644
index 0000000000..27431d8207
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_line.h
@@ -0,0 +1,111 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#define VERSION 2
+#define MIN_INST_LENGTH 4
+#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
new file mode 100644
index 0000000000..aa89ebf75b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_macinfo.c
@@ -0,0 +1,472 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#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
new file mode 100644
index 0000000000..74901b5666
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_macinfo.h
@@ -0,0 +1,40 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..2480a81810
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_opaque.h
@@ -0,0 +1,493 @@
+/*
+
+ Copyright (C) 2000, 2002 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
+
+*/
+
+
+#include <stddef.h>
+
+/*
+ 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;
+
+/* 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 */
+ 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 */
+};
+
+
+/* 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_func() or de_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
+
+
+/* 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_Unsigned de_access;
+ 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_func;
+ Dwarf_Callback_Func_b de_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. */
+
+};
+
+
+#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
new file mode 100644
index 0000000000..d65825db37
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_pubnames.c
@@ -0,0 +1,63 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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
new file mode 100644
index 0000000000..f608759577
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_reloc.c
@@ -0,0 +1,268 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+/*#include <elfaccess.h> */
+#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;
+ struct Dwarf_P_Relocation_Block_s *data;
+ 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;
+ struct Dwarf_P_Relocation_Block_s *data;
+ 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;
+ 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;
+
+ 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
new file mode 100644
index 0000000000..bd8c1fb7bb
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_reloc.h
@@ -0,0 +1,47 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..74e2ba3aaf
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.c
@@ -0,0 +1,298 @@
+/*
+
+ 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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
+ Elf64_Rel *elf64_reloc;
+ void *relrec_to_fill;
+ int res;
+ int rel_type;
+
+ 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 = (Elf64_Rel *) 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)
+{
+ Elf32_Rel *elf32_reloc;
+ void *relrec_to_fill;
+ int res;
+ int rel_type;
+
+ 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 = (Elf32_Rel *) 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;
+ int sec_index;
+ unsigned long i;
+ Dwarf_Error err;
+ 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;
+ struct Dwarf_P_Relocation_Block_s *p_blk;
+ struct Dwarf_P_Relocation_Block_s *p_blk_last;
+ Dwarf_P_Per_Reloc_Sect prb;
+
+ 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_func or de_func_b, getting section number of
+ reloc sec */
+ int rel_section_index;
+ Dwarf_Unsigned name_idx;
+ int int_name;
+ int err;
+
+ if (dbg->de_func_b) {
+ rel_section_index =
+ dbg->de_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_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
new file mode 100644
index 0000000000..bab69d80cb
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_reloc_stream.h
@@ -0,0 +1,63 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+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
new file mode 100644
index 0000000000..589c17bf40
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.c
@@ -0,0 +1,299 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+/*#include <elfaccess.h> */
+#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;
+ int res;
+ 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;
+ int res;
+ struct Dwarf_Relocation_Data_s *slotp1;
+ struct Dwarf_Relocation_Data_s *slotp2;
+
+
+
+ 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;
+ int sec_index;
+ int res;
+ unsigned long i;
+ Dwarf_Error error;
+
+ 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 len */
+ 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_func or de_func_b, getting section number of
+ reloc sec */
+ int rel_section_index;
+ int int_name;
+ Dwarf_Unsigned name_idx;
+
+ /*
+ 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_func_b) {
+ rel_section_index =
+ dbg->de_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_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
new file mode 100644
index 0000000000..5384718b8d
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_reloc_symbolic.h
@@ -0,0 +1,55 @@
+/*
+
+ 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., 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
+
+*/
+
+
+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
new file mode 100644
index 0000000000..ca1dd2a082
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_section.c
@@ -0,0 +1,1958 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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)
+*/
+char *_dwarf_rel_section_names[] = {
+ ".rel.debug_info",
+ ".rel.debug_line",
+ ".rel.debug_abbrev", /* no relocations on this, really */
+ ".rel.debug_frame",
+ ".rel.debug_aranges",
+ ".rel.debug_pubnames",
+ ".rel.debug_str",
+ ".rel.debug_funcnames", /* sgi extension */
+ ".rel.debug_typenames", /* sgi extension */
+ ".rel.debug_varnames", /* sgi extension */
+ ".rel.debug_weaknames", /* sgi extension */
+ ".rel.debug_macinfo",
+ ".rel.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);
+
+
+
+/*
+ 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;
+ int sect;
+ int name_idx;
+ int err;
+ Dwarf_Unsigned du;
+
+ 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_func_b) {
+ new_base_elf_sect =
+ dbg->de_func_b(_dwarf_sectnames[sect],
+ /* rec size */ 1,
+ SECTION_TYPE,
+ flags, SHN_UNDEF, 0, &du, &err);
+
+ } else {
+ new_base_elf_sect = dbg->de_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;
+ int res;
+
+ 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;
+ Dwarf_P_F_Entry curentry;
+ Dwarf_P_Line curline, prevline;
+
+ /* all data named cur* are used to loop thru linked lists */
+
+ int sum_bytes;
+ int prolog_size;
+ unsigned char *data; /* holds disk form data */
+ int elfsectno;
+ unsigned char *start_line_sec; /* pointer to the buffer at
+ section start */
+ /* temps for memcpy */
+ Dwarf_Unsigned du;
+ Dwarf_Ubyte db;
+ Dwarf_Half dh;
+ int res;
+ 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];
+
+ /* statement prologue information */
+ prolog_size = 0;
+ /* 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 += extension_size + /* DISTINGUISHED VALUE */
+ sizeof_uhalf(dbg) + /* version # */
+ uwordb_size + /* prologue 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);
+ prolog_size += uwordb_size; /* for total length field */
+
+ 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);
+
+ /* prologue length */
+ du = prolog_size - (uwordb_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 - uwordb_size - extension_size; /* subtract
+ length field
+ */
+ {
+ 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;
+ int i;
+ int firsttime = 1;
+ int pad; /* pad for padding to align cies and
+ fdes */
+ Dwarf_P_Cie curcie;
+ Dwarf_P_Fde curfde;
+ unsigned char *data;
+ Dwarf_sfixed dsw;
+ Dwarf_Unsigned du;
+ Dwarf_Ubyte db;
+ long *cie_offs; /* holds byte offsets for links to
+ fde's */
+ unsigned long cie_length;
+ int cie_no;
+ 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; /* 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 */
+ cie_no = 1;
+ while (curcie) {
+ char *code_al;
+ int c_bytes;
+ char *data_al;
+ int d_bytes;
+ int res;
+ char buff1[ENCODE_SPACE_NEEDED];
+ char buff2[ENCODE_SPACE_NEEDED];
+ char buff3[ENCODE_SPACE_NEEDED];
+ char *augmentation;
+ char *augmented_al;
+ long augmented_fields_length;
+ int a_bytes;
+
+ 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 + uwordb_size + extension_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 + uwordb_size
+ + extension_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 + uwordb_size
+ + extension_size;
+
+ /* write out fde's */
+ curfde = dbg->de_frame_fdes;
+ while (curfde) {
+ Dwarf_P_Frame_Pgm curinst;
+ long fde_length;
+ int pad;
+ Dwarf_P_Cie cie_ptr;
+ Dwarf_Word cie_index, index;
+ int oet_length, afl_length, res;
+ int v0_augmentation = 0;
+
+#if 0
+ unsigned char *fde_start_point;
+#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 + uwordb_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 + uwordb_size + /* cie
+ pointer
+ */
+ upointer_size + /* initial loc */
+ upointer_size; /* address range */
+ }
+
+ /* 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 + uwordb_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 + uwordb_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 + 2 * 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 + uwordb_size +
+ extension_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;
+ 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;
+
+ res = dbg->de_reloc_name(dbg,
+ DEBUG_FRAME,
+ (data - fde_start_point)
+ + cur_off + uwordb_size, /* r_offset
+ */
+ 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;
+}
+
+
+
+/*---------------------------------------------------------------
+ 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;
+ int abbrevsectno;
+ unsigned char *data;
+ int cu_header_size;
+ Dwarf_P_Abbrev curabbrev, abbrev_head, abbrev_tail;
+ Dwarf_P_Die curdie;
+ Dwarf_P_Die first_child;
+ Dwarf_Word dw;
+ Dwarf_Unsigned du;
+ Dwarf_Half dh;
+ Dwarf_Ubyte db;
+ Dwarf_Half version; /* need 2 byte quantity */
+ Dwarf_Unsigned die_off; /* offset of die in debug_info */
+ int n_abbrevs;
+ int res;
+
+ Dwarf_Small *start_info_sec;
+
+ int uword_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 = extension_size + uword_size + /* length of
+ info section
+ */
+ sizeof(Dwarf_Half) + /* version stamp */
+ uword_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), uword_size);
+ data += uword_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), uword_size);
+ data += uword_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, extension_size + uword_size + sizeof(Dwarf_Half), /* r_offset
+ */
+ dbg->de_sect_name_idx[DEBUG_ABBREV],
+ dwarf_drt_data_reloc, uword_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 */
+ while (curdie != NULL) {
+ int nbytes;
+ Dwarf_P_Attribute curattr;
+ char *space;
+ int res;
+ char buff1[ENCODE_SPACE_NEEDED];
+
+ curdie->di_offset = die_off;
+ 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;
+ 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);
+ }
+
+ }
+ 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;
+ }
+ }
+
+ /* 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;
+
+ /* 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;
+ 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:
+ {
+ du = curattr->ar_ref_die->di_offset;
+ {
+ /* ref to offset of die */
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), uword_size);
+ }
+ 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;
+ }
+ 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;
+ }
+ }
+
+ /* Write out debug_info size */
+ /* Dont include length field or extension bytes */
+ du = die_off - uword_size - extension_size;
+ WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size),
+ (const void *) &du, sizeof(du), uword_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;
+}
+
+/*
+ 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(NULL,
+ sizeof(Dwarf_ufixed) * die->di_n_attr);
+ if (forms == NULL)
+ return NULL;
+ attrs = (Dwarf_ufixed *)
+ _dwarf_p_get_alloc(NULL,
+ 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(NULL, 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
new file mode 100644
index 0000000000..a4044c8a5d
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_section.h
@@ -0,0 +1,112 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+
+/* 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
new file mode 100644
index 0000000000..aa8266199b
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_types.c
@@ -0,0 +1,294 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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
new file mode 100644
index 0000000000..7ce1e33c59
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_types.h
@@ -0,0 +1,44 @@
+/*
+
+ 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., 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
+
+*/
+
+
+/* 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
new file mode 100644
index 0000000000..d01caae5b1
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_util.h
@@ -0,0 +1,107 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+
+#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 <elf.h> 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.
+*/
+#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
+
+#ifndef HAVE_R_IA_64_DIR32LSB
+#define R_IA_64_DIR32LSB 0
+#define R_IA_64_DIR64LSB 0
+#define R_IA_64_SEGREL64LSB 0
+#define R_IA_64_SEGREL32LSB 0
+#endif
+
+#ifdef HAVE_SYS_IA64_ELF_H
+#define Get_REL64_isa(dbg) (ISA_IA64(dbg) ? \
+ R_IA_64_DIR64LSB : R_MIPS_64)
+#define Get_REL32_isa(dbg) (ISA_IA64(dbg) ? \
+ R_IA_64_DIR32LSB : R_MIPS_32)
+
+
+/* ia64 uses 32bit dwarf offsets for sections */
+#define Get_REL_SEGREL_isa(dbg) (ISA_IA64(dbg) ? \
+ R_IA_64_SEGREL32LSB : R_MIPS_SCN_DISP)
+#else
+
+#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) (R_IA_64_DIR64LSB)
+#define Get_REL32_isa(dbg) (R_IA_64_DIR32LSB)
+#define Get_REL_SEGREL_isa(dbg) (R_IA_64_SEGREL64LSB)
+#endif
+
+#endif
diff --git a/usr/src/tools/ctf/dwarf/common/pro_vars.c b/usr/src/tools/ctf/dwarf/common/pro_vars.c
new file mode 100644
index 0000000000..3b9bff9292
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_vars.c
@@ -0,0 +1,62 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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
new file mode 100644
index 0000000000..36d80f0e10
--- /dev/null
+++ b/usr/src/tools/ctf/dwarf/common/pro_weaks.c
@@ -0,0 +1,61 @@
+/*
+
+ 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., 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
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#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);
+}