diff --git a/.gitignore b/.gitignore
index 34804df4..d3e7928c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ config*.h
config*.mak
config.texi
conftest*
+c2str
tags
TAGS
tcc.1
diff --git a/arm-gen.c b/arm-gen.c
index 0d466d4f..e0d98d01 100644
--- a/arm-gen.c
+++ b/arm-gen.c
@@ -866,7 +866,7 @@ static void gen_bounds_epilog(void)
*bounds_ptr = 0;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, lbounds_section->data_offset);
+ func_bound_offset, PTR_SIZE);
/* generate bound local allocation */
if (offset_modified) {
diff --git a/arm-link.c b/arm-link.c
index 5d40f843..47f60c80 100644
--- a/arm-link.c
+++ b/arm-link.c
@@ -4,6 +4,7 @@
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_ARM_ABS32
+#define R_DATA_32U R_ARM_ABS32
#define R_DATA_PTR R_ARM_ABS32
#define R_JMP_SLOT R_ARM_JUMP_SLOT
#define R_GLOB_DAT R_ARM_GLOB_DAT
diff --git a/arm64-gen.c b/arm64-gen.c
index 25b50fab..8232f2a9 100644
--- a/arm64-gen.c
+++ b/arm64-gen.c
@@ -710,7 +710,7 @@ static void gen_bounds_epilog(void)
*bounds_ptr = 0;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, lbounds_section->data_offset);
+ func_bound_offset, PTR_SIZE);
/* generate bound local allocation */
if (offset_modified) {
diff --git a/arm64-link.c b/arm64-link.c
index 99916693..2d1628ff 100644
--- a/arm64-link.c
+++ b/arm64-link.c
@@ -3,6 +3,7 @@
#define EM_TCC_TARGET EM_AARCH64
#define R_DATA_32 R_AARCH64_ABS32
+#define R_DATA_32U R_AARCH64_ABS32
#define R_DATA_PTR R_AARCH64_ABS64
#define R_JMP_SLOT R_AARCH64_JUMP_SLOT
#define R_GLOB_DAT R_AARCH64_GLOB_DAT
diff --git a/c67-link.c b/c67-link.c
index 514689c5..ba017802 100644
--- a/c67-link.c
+++ b/c67-link.c
@@ -4,6 +4,7 @@
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_C60_32
+#define R_DATA_32U R_C60_32
#define R_DATA_PTR R_C60_32
#define R_JMP_SLOT R_C60_JMP_SLOT
#define R_GLOB_DAT R_C60_GLOB_DAT
diff --git a/configure b/configure
index 4063ac72..4af3f433 100755
--- a/configure
+++ b/configure
@@ -51,6 +51,7 @@ ar_set=
darwin=
cpu=
cpuver=
+dwarf=
# OS specific
cpu_sys=`uname -m`
@@ -136,6 +137,8 @@ for opt do
;;
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2-`
;;
+ --dwarf=*) dwarf=`echo $opt | cut -d '=' -f 2-`
+ ;;
--enable-cross) confvars="$confvars cross"
;;
--disable-static) confvars="$confvars static=no"
@@ -328,6 +331,7 @@ Advanced options (experts only):
--config-backtrace=no disable stack backtraces (with -run or -bt)
--config-bcheck=no disable bounds checker (-b)
--config-predefs=no do not compile tccdefs.h, instead just include
+ --dwarf=x Use dwarf debug info instead of stabs (x=2..5)
EOF
exit 1
fi
@@ -493,6 +497,7 @@ print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
print_mak CONFIG_LDDIR "$tcc_lddir"
print_mak CONFIG_TRIPLET "$triplet"
print_mak TCC_CPU_VERSION "$cpuver" num
+print_mak CONFIG_DWARF "$dwarf"
echo "ARCH=$cpu" >> config.mak
echo "TARGETOS=$targetos" >> config.mak
diff --git a/dwarf.h b/dwarf.h
new file mode 100644
index 00000000..c961bc36
--- /dev/null
+++ b/dwarf.h
@@ -0,0 +1,1046 @@
+/* This file defines standard DWARF types, structures, and macros.
+ Copyright (C) 2000-2011, 2014, 2016, 2017, 2018 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see . */
+
+#ifndef _DWARF_H
+#define _DWARF_H 1
+
+/* DWARF Unit Header Types. */
+enum
+ {
+ DW_UT_compile = 0x01,
+ DW_UT_type = 0x02,
+ DW_UT_partial = 0x03,
+ DW_UT_skeleton = 0x04,
+ DW_UT_split_compile = 0x05,
+ DW_UT_split_type = 0x06,
+
+ DW_UT_lo_user = 0x80,
+ DW_UT_hi_user = 0xff
+ };
+
+/* DWARF tags. */
+enum
+ {
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ /* 0x06 reserved. */
+ /* 0x07 reserved. */
+ DW_TAG_imported_declaration = 0x08,
+ /* 0x09 reserved. */
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ /* 0x0c reserved. */
+ DW_TAG_member = 0x0d,
+ /* 0x0e reserved. */
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ /* 0x14 reserved. */
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_parameter = 0x2f,
+ DW_TAG_template_value_parameter = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ /* 0x3e reserved. Was DW_TAG_mutable_type. */
+ DW_TAG_condition = 0x3f,
+ DW_TAG_shared_type = 0x40,
+ DW_TAG_type_unit = 0x41,
+ DW_TAG_rvalue_reference_type = 0x42,
+ DW_TAG_template_alias = 0x43,
+ DW_TAG_coarray_type = 0x44,
+ DW_TAG_generic_subrange = 0x45,
+ DW_TAG_dynamic_type = 0x46,
+ DW_TAG_atomic_type = 0x47,
+ DW_TAG_call_site = 0x48,
+ DW_TAG_call_site_parameter = 0x49,
+ DW_TAG_skeleton_unit = 0x4a,
+ DW_TAG_immutable_type = 0x4b,
+
+ DW_TAG_lo_user = 0x4080,
+
+ DW_TAG_MIPS_loop = 0x4081,
+ DW_TAG_format_label = 0x4101,
+ DW_TAG_function_template = 0x4102,
+ DW_TAG_class_template = 0x4103,
+
+ DW_TAG_GNU_BINCL = 0x4104,
+ DW_TAG_GNU_EINCL = 0x4105,
+
+ DW_TAG_GNU_template_template_param = 0x4106,
+ DW_TAG_GNU_template_parameter_pack = 0x4107,
+ DW_TAG_GNU_formal_parameter_pack = 0x4108,
+ DW_TAG_GNU_call_site = 0x4109,
+ DW_TAG_GNU_call_site_parameter = 0x410a,
+
+ DW_TAG_hi_user = 0xffff
+ };
+
+
+/* Children determination encodings. */
+enum
+ {
+ DW_CHILDREN_no = 0,
+ DW_CHILDREN_yes = 1
+ };
+
+
+/* DWARF attributes encodings. */
+enum
+ {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ /* 0x04 reserved. */
+ /* 0x05 reserved. */
+ /* 0x06 reserved. */
+ /* 0x07 reserved. */
+ /* 0x08 reserved. */
+ DW_AT_ordering = 0x09,
+ /* 0x0a reserved. */
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c, /* Deprecated in DWARF4. */
+ DW_AT_bit_size = 0x0d,
+ /* 0x0e reserved. */
+ /* 0x0f reserved. */
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ /* 0x14 reserved. */
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ /* 0x1f reserved. */
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ /* 0x23 reserved. */
+ /* 0x24 reserved. */
+ DW_AT_producer = 0x25,
+ /* 0x26 reserved. */
+ DW_AT_prototyped = 0x27,
+ /* 0x28 reserved. */
+ /* 0x29 reserved. */
+ DW_AT_return_addr = 0x2a,
+ /* 0x2b reserved. */
+ DW_AT_start_scope = 0x2c,
+ /* 0x2d reserved. */
+ DW_AT_bit_stride = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ /* 0x30 reserved. */
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43, /* Deprecated in DWARF5. */
+ DW_AT_namelist_item = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_byte_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ DW_AT_description = 0x5a,
+ DW_AT_binary_scale = 0x5b,
+ DW_AT_decimal_scale = 0x5c,
+ DW_AT_small = 0x5d,
+ DW_AT_decimal_sign = 0x5e,
+ DW_AT_digit_count = 0x5f,
+ DW_AT_picture_string = 0x60,
+ DW_AT_mutable = 0x61,
+ DW_AT_threads_scaled = 0x62,
+ DW_AT_explicit = 0x63,
+ DW_AT_object_pointer = 0x64,
+ DW_AT_endianity = 0x65,
+ DW_AT_elemental = 0x66,
+ DW_AT_pure = 0x67,
+ DW_AT_recursive = 0x68,
+ DW_AT_signature = 0x69,
+ DW_AT_main_subprogram = 0x6a,
+ DW_AT_data_bit_offset = 0x6b,
+ DW_AT_const_expr = 0x6c,
+ DW_AT_enum_class = 0x6d,
+ DW_AT_linkage_name = 0x6e,
+ DW_AT_string_length_bit_size = 0x6f,
+ DW_AT_string_length_byte_size = 0x70,
+ DW_AT_rank = 0x71,
+ DW_AT_str_offsets_base = 0x72,
+ DW_AT_addr_base = 0x73,
+ DW_AT_rnglists_base = 0x74,
+ /* 0x75 reserved. */
+ DW_AT_dwo_name = 0x76,
+ DW_AT_reference = 0x77,
+ DW_AT_rvalue_reference = 0x78,
+ DW_AT_macros = 0x79,
+ DW_AT_call_all_calls = 0x7a,
+ DW_AT_call_all_source_calls = 0x7b,
+ DW_AT_call_all_tail_calls = 0x7c,
+ DW_AT_call_return_pc = 0x7d,
+ DW_AT_call_value = 0x7e,
+ DW_AT_call_origin = 0x7f,
+ DW_AT_call_parameter = 0x80,
+ DW_AT_call_pc = 0x81,
+ DW_AT_call_tail_call = 0x82,
+ DW_AT_call_target = 0x83,
+ DW_AT_call_target_clobbered = 0x84,
+ DW_AT_call_data_location = 0x85,
+ DW_AT_call_data_value = 0x86,
+ DW_AT_noreturn = 0x87,
+ DW_AT_alignment = 0x88,
+ DW_AT_export_symbols = 0x89,
+ DW_AT_deleted = 0x8a,
+ DW_AT_defaulted = 0x8b,
+ DW_AT_loclists_base = 0x8c,
+
+ DW_AT_lo_user = 0x2000,
+
+ DW_AT_MIPS_fde = 0x2001,
+ DW_AT_MIPS_loop_begin = 0x2002,
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
+ DW_AT_MIPS_epilog_begin = 0x2004,
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
+ DW_AT_MIPS_linkage_name = 0x2007,
+ DW_AT_MIPS_stride = 0x2008,
+ DW_AT_MIPS_abstract_name = 0x2009,
+ DW_AT_MIPS_clone_origin = 0x200a,
+ DW_AT_MIPS_has_inlines = 0x200b,
+ DW_AT_MIPS_stride_byte = 0x200c,
+ DW_AT_MIPS_stride_elem = 0x200d,
+ DW_AT_MIPS_ptr_dopetype = 0x200e,
+ DW_AT_MIPS_allocatable_dopetype = 0x200f,
+ DW_AT_MIPS_assumed_shape_dopetype = 0x2010,
+ DW_AT_MIPS_assumed_size = 0x2011,
+
+ /* GNU extensions. */
+ DW_AT_sf_names = 0x2101,
+ DW_AT_src_info = 0x2102,
+ DW_AT_mac_info = 0x2103,
+ DW_AT_src_coords = 0x2104,
+ DW_AT_body_begin = 0x2105,
+ DW_AT_body_end = 0x2106,
+ DW_AT_GNU_vector = 0x2107,
+ DW_AT_GNU_guarded_by = 0x2108,
+ DW_AT_GNU_pt_guarded_by = 0x2109,
+ DW_AT_GNU_guarded = 0x210a,
+ DW_AT_GNU_pt_guarded = 0x210b,
+ DW_AT_GNU_locks_excluded = 0x210c,
+ DW_AT_GNU_exclusive_locks_required = 0x210d,
+ DW_AT_GNU_shared_locks_required = 0x210e,
+ DW_AT_GNU_odr_signature = 0x210f,
+ DW_AT_GNU_template_name = 0x2110,
+ DW_AT_GNU_call_site_value = 0x2111,
+ DW_AT_GNU_call_site_data_value = 0x2112,
+ DW_AT_GNU_call_site_target = 0x2113,
+ DW_AT_GNU_call_site_target_clobbered = 0x2114,
+ DW_AT_GNU_tail_call = 0x2115,
+ DW_AT_GNU_all_tail_call_sites = 0x2116,
+ DW_AT_GNU_all_call_sites = 0x2117,
+ DW_AT_GNU_all_source_call_sites = 0x2118,
+ DW_AT_GNU_locviews = 0x2137,
+ DW_AT_GNU_entry_view = 0x2138,
+ DW_AT_GNU_macros = 0x2119,
+ DW_AT_GNU_deleted = 0x211a,
+ /* GNU Debug Fission extensions. */
+ DW_AT_GNU_dwo_name = 0x2130,
+ DW_AT_GNU_dwo_id = 0x2131,
+ DW_AT_GNU_ranges_base = 0x2132,
+ DW_AT_GNU_addr_base = 0x2133,
+ DW_AT_GNU_pubnames = 0x2134,
+ DW_AT_GNU_pubtypes = 0x2135,
+
+ /* https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator */
+ DW_AT_GNU_numerator = 0x2303,
+ DW_AT_GNU_denominator = 0x2304,
+ /* https://gcc.gnu.org/wiki/DW_AT_GNU_bias */
+ DW_AT_GNU_bias = 0x2305,
+
+ DW_AT_hi_user = 0x3fff
+ };
+
+/* Old unofficially attribute names. Should not be used.
+ Will not appear in known-dwarf.h */
+
+/* DWARF1 array subscripts and element data types. */
+#define DW_AT_subscr_data 0x0a
+/* DWARF1 enumeration literals. */
+#define DW_AT_element_list 0x0f
+/* DWARF1 reference for variable to member structure, class or union. */
+#define DW_AT_member 0x14
+
+/* DWARF form encodings. */
+enum
+ {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16,
+ DW_FORM_sec_offset = 0x17,
+ DW_FORM_exprloc = 0x18,
+ DW_FORM_flag_present = 0x19,
+ DW_FORM_strx = 0x1a,
+ DW_FORM_addrx = 0x1b,
+ DW_FORM_ref_sup4 = 0x1c,
+ DW_FORM_strp_sup = 0x1d,
+ DW_FORM_data16 = 0x1e,
+ DW_FORM_line_strp = 0x1f,
+ DW_FORM_ref_sig8 = 0x20,
+ DW_FORM_implicit_const = 0x21,
+ DW_FORM_loclistx = 0x22,
+ DW_FORM_rnglistx = 0x23,
+ DW_FORM_ref_sup8 = 0x24,
+ DW_FORM_strx1 = 0x25,
+ DW_FORM_strx2 = 0x26,
+ DW_FORM_strx3 = 0x27,
+ DW_FORM_strx4 = 0x28,
+ DW_FORM_addrx1 = 0x29,
+ DW_FORM_addrx2 = 0x2a,
+ DW_FORM_addrx3 = 0x2b,
+ DW_FORM_addrx4 = 0x2c,
+
+ /* GNU Debug Fission extensions. */
+ DW_FORM_GNU_addr_index = 0x1f01,
+ DW_FORM_GNU_str_index = 0x1f02,
+
+ DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo. */
+ DW_FORM_GNU_strp_alt = 0x1f21 /* offset in alternate .debug_str. */
+ };
+
+
+/* DWARF location operation encodings. */
+enum
+ {
+ DW_OP_addr = 0x03, /* Constant address. */
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08, /* Unsigned 1-byte constant. */
+ DW_OP_const1s = 0x09, /* Signed 1-byte constant. */
+ DW_OP_const2u = 0x0a, /* Unsigned 2-byte constant. */
+ DW_OP_const2s = 0x0b, /* Signed 2-byte constant. */
+ DW_OP_const4u = 0x0c, /* Unsigned 4-byte constant. */
+ DW_OP_const4s = 0x0d, /* Signed 4-byte constant. */
+ DW_OP_const8u = 0x0e, /* Unsigned 8-byte constant. */
+ DW_OP_const8s = 0x0f, /* Signed 8-byte constant. */
+ DW_OP_constu = 0x10, /* Unsigned LEB128 constant. */
+ DW_OP_consts = 0x11, /* Signed LEB128 constant. */
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15, /* 1-byte stack index. */
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23, /* Unsigned LEB128 addend. */
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_bra = 0x28, /* Signed 2-byte constant. */
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_skip = 0x2f, /* Signed 2-byte constant. */
+ DW_OP_lit0 = 0x30, /* Literal 0. */
+ DW_OP_lit1 = 0x31, /* Literal 1. */
+ DW_OP_lit2 = 0x32, /* Literal 2. */
+ DW_OP_lit3 = 0x33, /* Literal 3. */
+ DW_OP_lit4 = 0x34, /* Literal 4. */
+ DW_OP_lit5 = 0x35, /* Literal 5. */
+ DW_OP_lit6 = 0x36, /* Literal 6. */
+ DW_OP_lit7 = 0x37, /* Literal 7. */
+ DW_OP_lit8 = 0x38, /* Literal 8. */
+ DW_OP_lit9 = 0x39, /* Literal 9. */
+ DW_OP_lit10 = 0x3a, /* Literal 10. */
+ DW_OP_lit11 = 0x3b, /* Literal 11. */
+ DW_OP_lit12 = 0x3c, /* Literal 12. */
+ DW_OP_lit13 = 0x3d, /* Literal 13. */
+ DW_OP_lit14 = 0x3e, /* Literal 14. */
+ DW_OP_lit15 = 0x3f, /* Literal 15. */
+ DW_OP_lit16 = 0x40, /* Literal 16. */
+ DW_OP_lit17 = 0x41, /* Literal 17. */
+ DW_OP_lit18 = 0x42, /* Literal 18. */
+ DW_OP_lit19 = 0x43, /* Literal 19. */
+ DW_OP_lit20 = 0x44, /* Literal 20. */
+ DW_OP_lit21 = 0x45, /* Literal 21. */
+ DW_OP_lit22 = 0x46, /* Literal 22. */
+ DW_OP_lit23 = 0x47, /* Literal 23. */
+ DW_OP_lit24 = 0x48, /* Literal 24. */
+ DW_OP_lit25 = 0x49, /* Literal 25. */
+ DW_OP_lit26 = 0x4a, /* Literal 26. */
+ DW_OP_lit27 = 0x4b, /* Literal 27. */
+ DW_OP_lit28 = 0x4c, /* Literal 28. */
+ DW_OP_lit29 = 0x4d, /* Literal 29. */
+ DW_OP_lit30 = 0x4e, /* Literal 30. */
+ DW_OP_lit31 = 0x4f, /* Literal 31. */
+ DW_OP_reg0 = 0x50, /* Register 0. */
+ DW_OP_reg1 = 0x51, /* Register 1. */
+ DW_OP_reg2 = 0x52, /* Register 2. */
+ DW_OP_reg3 = 0x53, /* Register 3. */
+ DW_OP_reg4 = 0x54, /* Register 4. */
+ DW_OP_reg5 = 0x55, /* Register 5. */
+ DW_OP_reg6 = 0x56, /* Register 6. */
+ DW_OP_reg7 = 0x57, /* Register 7. */
+ DW_OP_reg8 = 0x58, /* Register 8. */
+ DW_OP_reg9 = 0x59, /* Register 9. */
+ DW_OP_reg10 = 0x5a, /* Register 10. */
+ DW_OP_reg11 = 0x5b, /* Register 11. */
+ DW_OP_reg12 = 0x5c, /* Register 12. */
+ DW_OP_reg13 = 0x5d, /* Register 13. */
+ DW_OP_reg14 = 0x5e, /* Register 14. */
+ DW_OP_reg15 = 0x5f, /* Register 15. */
+ DW_OP_reg16 = 0x60, /* Register 16. */
+ DW_OP_reg17 = 0x61, /* Register 17. */
+ DW_OP_reg18 = 0x62, /* Register 18. */
+ DW_OP_reg19 = 0x63, /* Register 19. */
+ DW_OP_reg20 = 0x64, /* Register 20. */
+ DW_OP_reg21 = 0x65, /* Register 21. */
+ DW_OP_reg22 = 0x66, /* Register 22. */
+ DW_OP_reg23 = 0x67, /* Register 24. */
+ DW_OP_reg24 = 0x68, /* Register 24. */
+ DW_OP_reg25 = 0x69, /* Register 25. */
+ DW_OP_reg26 = 0x6a, /* Register 26. */
+ DW_OP_reg27 = 0x6b, /* Register 27. */
+ DW_OP_reg28 = 0x6c, /* Register 28. */
+ DW_OP_reg29 = 0x6d, /* Register 29. */
+ DW_OP_reg30 = 0x6e, /* Register 30. */
+ DW_OP_reg31 = 0x6f, /* Register 31. */
+ DW_OP_breg0 = 0x70, /* Base register 0. */
+ DW_OP_breg1 = 0x71, /* Base register 1. */
+ DW_OP_breg2 = 0x72, /* Base register 2. */
+ DW_OP_breg3 = 0x73, /* Base register 3. */
+ DW_OP_breg4 = 0x74, /* Base register 4. */
+ DW_OP_breg5 = 0x75, /* Base register 5. */
+ DW_OP_breg6 = 0x76, /* Base register 6. */
+ DW_OP_breg7 = 0x77, /* Base register 7. */
+ DW_OP_breg8 = 0x78, /* Base register 8. */
+ DW_OP_breg9 = 0x79, /* Base register 9. */
+ DW_OP_breg10 = 0x7a, /* Base register 10. */
+ DW_OP_breg11 = 0x7b, /* Base register 11. */
+ DW_OP_breg12 = 0x7c, /* Base register 12. */
+ DW_OP_breg13 = 0x7d, /* Base register 13. */
+ DW_OP_breg14 = 0x7e, /* Base register 14. */
+ DW_OP_breg15 = 0x7f, /* Base register 15. */
+ DW_OP_breg16 = 0x80, /* Base register 16. */
+ DW_OP_breg17 = 0x81, /* Base register 17. */
+ DW_OP_breg18 = 0x82, /* Base register 18. */
+ DW_OP_breg19 = 0x83, /* Base register 19. */
+ DW_OP_breg20 = 0x84, /* Base register 20. */
+ DW_OP_breg21 = 0x85, /* Base register 21. */
+ DW_OP_breg22 = 0x86, /* Base register 22. */
+ DW_OP_breg23 = 0x87, /* Base register 23. */
+ DW_OP_breg24 = 0x88, /* Base register 24. */
+ DW_OP_breg25 = 0x89, /* Base register 25. */
+ DW_OP_breg26 = 0x8a, /* Base register 26. */
+ DW_OP_breg27 = 0x8b, /* Base register 27. */
+ DW_OP_breg28 = 0x8c, /* Base register 28. */
+ DW_OP_breg29 = 0x8d, /* Base register 29. */
+ DW_OP_breg30 = 0x8e, /* Base register 30. */
+ DW_OP_breg31 = 0x8f, /* Base register 31. */
+ DW_OP_regx = 0x90, /* Unsigned LEB128 register. */
+ DW_OP_fbreg = 0x91, /* Signed LEB128 offset. */
+ DW_OP_bregx = 0x92, /* ULEB128 register followed by SLEB128 off. */
+ DW_OP_piece = 0x93, /* ULEB128 size of piece addressed. */
+ DW_OP_deref_size = 0x94, /* 1-byte size of data retrieved. */
+ DW_OP_xderef_size = 0x95, /* 1-byte size of data retrieved. */
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ DW_OP_form_tls_address = 0x9b,/* TLS offset to address in current thread */
+ DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI. */
+ DW_OP_bit_piece = 0x9d, /* ULEB128 size and ULEB128 offset in bits. */
+ DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode. */
+ DW_OP_stack_value = 0x9f, /* No operands, special like DW_OP_piece. */
+
+ DW_OP_implicit_pointer = 0xa0,
+ DW_OP_addrx = 0xa1,
+ DW_OP_constx = 0xa2,
+ DW_OP_entry_value = 0xa3,
+ DW_OP_const_type = 0xa4,
+ DW_OP_regval_type = 0xa5,
+ DW_OP_deref_type = 0xa6,
+ DW_OP_xderef_type = 0xa7,
+ DW_OP_convert = 0xa8,
+ DW_OP_reinterpret = 0xa9,
+
+ /* GNU extensions. */
+ DW_OP_GNU_push_tls_address = 0xe0,
+ DW_OP_GNU_uninit = 0xf0,
+ DW_OP_GNU_encoded_addr = 0xf1,
+ DW_OP_GNU_implicit_pointer = 0xf2,
+ DW_OP_GNU_entry_value = 0xf3,
+ DW_OP_GNU_const_type = 0xf4,
+ DW_OP_GNU_regval_type = 0xf5,
+ DW_OP_GNU_deref_type = 0xf6,
+ DW_OP_GNU_convert = 0xf7,
+ DW_OP_GNU_reinterpret = 0xf9,
+ DW_OP_GNU_parameter_ref = 0xfa,
+
+ /* GNU Debug Fission extensions. */
+ DW_OP_GNU_addr_index = 0xfb,
+ DW_OP_GNU_const_index = 0xfc,
+
+ DW_OP_GNU_variable_value = 0xfd,
+
+ DW_OP_lo_user = 0xe0, /* Implementation-defined range start. */
+ DW_OP_hi_user = 0xff /* Implementation-defined range end. */
+ };
+
+
+/* DWARF base type encodings. */
+enum
+ {
+ DW_ATE_void = 0x0,
+ DW_ATE_address = 0x1,
+ DW_ATE_boolean = 0x2,
+ DW_ATE_complex_float = 0x3,
+ DW_ATE_float = 0x4,
+ DW_ATE_signed = 0x5,
+ DW_ATE_signed_char = 0x6,
+ DW_ATE_unsigned = 0x7,
+ DW_ATE_unsigned_char = 0x8,
+ DW_ATE_imaginary_float = 0x9,
+ DW_ATE_packed_decimal = 0xa,
+ DW_ATE_numeric_string = 0xb,
+ DW_ATE_edited = 0xc,
+ DW_ATE_signed_fixed = 0xd,
+ DW_ATE_unsigned_fixed = 0xe,
+ DW_ATE_decimal_float = 0xf,
+ DW_ATE_UTF = 0x10,
+ DW_ATE_UCS = 0x11,
+ DW_ATE_ASCII = 0x12,
+
+ DW_ATE_lo_user = 0x80,
+ DW_ATE_hi_user = 0xff
+ };
+
+
+/* DWARF decimal sign encodings. */
+enum
+ {
+ DW_DS_unsigned = 1,
+ DW_DS_leading_overpunch = 2,
+ DW_DS_trailing_overpunch = 3,
+ DW_DS_leading_separate = 4,
+ DW_DS_trailing_separate = 5,
+ };
+
+
+/* DWARF endianity encodings. */
+enum
+ {
+ DW_END_default = 0,
+ DW_END_big = 1,
+ DW_END_little = 2,
+
+ DW_END_lo_user = 0x40,
+ DW_END_hi_user = 0xff
+ };
+
+
+/* DWARF accessibility encodings. */
+enum
+ {
+ DW_ACCESS_public = 1,
+ DW_ACCESS_protected = 2,
+ DW_ACCESS_private = 3
+ };
+
+
+/* DWARF visibility encodings. */
+enum
+ {
+ DW_VIS_local = 1,
+ DW_VIS_exported = 2,
+ DW_VIS_qualified = 3
+ };
+
+
+/* DWARF virtuality encodings. */
+enum
+ {
+ DW_VIRTUALITY_none = 0,
+ DW_VIRTUALITY_virtual = 1,
+ DW_VIRTUALITY_pure_virtual = 2
+ };
+
+
+/* DWARF language encodings. */
+enum
+ {
+ DW_LANG_C89 = 0x0001, /* ISO C:1989 */
+ DW_LANG_C = 0x0002, /* C */
+ DW_LANG_Ada83 = 0x0003, /* ISO Ada:1983 */
+ DW_LANG_C_plus_plus = 0x0004, /* ISO C++:1998 */
+ DW_LANG_Cobol74 = 0x0005, /* ISO Cobol:1974 */
+ DW_LANG_Cobol85 = 0x0006, /* ISO Cobol:1985 */
+ DW_LANG_Fortran77 = 0x0007, /* ISO FORTRAN 77 */
+ DW_LANG_Fortran90 = 0x0008, /* ISO Fortran 90 */
+ DW_LANG_Pascal83 = 0x0009, /* ISO Pascal:1983 */
+ DW_LANG_Modula2 = 0x000a, /* ISO Modula-2:1996 */
+ DW_LANG_Java = 0x000b, /* Java */
+ DW_LANG_C99 = 0x000c, /* ISO C:1999 */
+ DW_LANG_Ada95 = 0x000d, /* ISO Ada:1995 */
+ DW_LANG_Fortran95 = 0x000e, /* ISO Fortran 95 */
+ DW_LANG_PLI = 0x000f, /* ISO PL/1:1976 */
+ DW_LANG_ObjC = 0x0010, /* Objective-C */
+ DW_LANG_ObjC_plus_plus = 0x0011, /* Objective-C++ */
+ DW_LANG_UPC = 0x0012, /* Unified Parallel C */
+ DW_LANG_D = 0x0013, /* D */
+ DW_LANG_Python = 0x0014, /* Python */
+ DW_LANG_OpenCL = 0x0015, /* OpenCL */
+ DW_LANG_Go = 0x0016, /* Go */
+ DW_LANG_Modula3 = 0x0017, /* Modula-3 */
+ DW_LANG_Haskell = 0x0018, /* Haskell */
+ DW_LANG_C_plus_plus_03 = 0x0019, /* ISO C++:2003 */
+ DW_LANG_C_plus_plus_11 = 0x001a, /* ISO C++:2011 */
+ DW_LANG_OCaml = 0x001b, /* OCaml */
+ DW_LANG_Rust = 0x001c, /* Rust */
+ DW_LANG_C11 = 0x001d, /* ISO C:2011 */
+ DW_LANG_Swift = 0x001e, /* Swift */
+ DW_LANG_Julia = 0x001f, /* Julia */
+ DW_LANG_Dylan = 0x0020, /* Dylan */
+ DW_LANG_C_plus_plus_14 = 0x0021, /* ISO C++:2014 */
+ DW_LANG_Fortran03 = 0x0022, /* ISO/IEC 1539-1:2004 */
+ DW_LANG_Fortran08 = 0x0023, /* ISO/IEC 1539-1:2010 */
+ DW_LANG_RenderScript = 0x0024, /* RenderScript Kernal Language */
+ DW_LANG_BLISS = 0x0025, /* BLISS */
+
+ DW_LANG_lo_user = 0x8000,
+ DW_LANG_Mips_Assembler = 0x8001, /* Assembler */
+ DW_LANG_hi_user = 0xffff
+ };
+
+/* Old (typo) '1' != 'I'. */
+#define DW_LANG_PL1 DW_LANG_PLI
+
+/* DWARF identifier case encodings. */
+enum
+ {
+ DW_ID_case_sensitive = 0,
+ DW_ID_up_case = 1,
+ DW_ID_down_case = 2,
+ DW_ID_case_insensitive = 3
+ };
+
+
+/* DWARF calling conventions encodings.
+ Used as values of DW_AT_calling_convention for subroutines
+ (normal, program or nocall) or structures, unions and class types
+ (normal, reference or value). */
+enum
+ {
+ DW_CC_normal = 0x1,
+ DW_CC_program = 0x2,
+ DW_CC_nocall = 0x3,
+ DW_CC_pass_by_reference = 0x4,
+ DW_CC_pass_by_value = 0x5,
+ DW_CC_lo_user = 0x40,
+ DW_CC_hi_user = 0xff
+ };
+
+
+/* DWARF inline encodings. */
+enum
+ {
+ DW_INL_not_inlined = 0,
+ DW_INL_inlined = 1,
+ DW_INL_declared_not_inlined = 2,
+ DW_INL_declared_inlined = 3
+ };
+
+
+/* DWARF ordering encodings. */
+enum
+ {
+ DW_ORD_row_major = 0,
+ DW_ORD_col_major = 1
+ };
+
+
+/* DWARF discriminant descriptor encodings. */
+enum
+ {
+ DW_DSC_label = 0,
+ DW_DSC_range = 1
+ };
+
+/* DWARF defaulted member function encodings. */
+enum
+ {
+ DW_DEFAULTED_no = 0,
+ DW_DEFAULTED_in_class = 1,
+ DW_DEFAULTED_out_of_class = 2
+ };
+
+/* DWARF line content descriptions. */
+enum
+ {
+ DW_LNCT_path = 0x1,
+ DW_LNCT_directory_index = 0x2,
+ DW_LNCT_timestamp = 0x3,
+ DW_LNCT_size = 0x4,
+ DW_LNCT_MD5 = 0x5,
+ DW_LNCT_lo_user = 0x2000,
+ DW_LNCT_hi_user = 0x3fff
+ };
+
+/* DWARF standard opcode encodings. */
+enum
+ {
+ DW_LNS_copy = 1,
+ DW_LNS_advance_pc = 2,
+ DW_LNS_advance_line = 3,
+ DW_LNS_set_file = 4,
+ DW_LNS_set_column = 5,
+ DW_LNS_negate_stmt = 6,
+ DW_LNS_set_basic_block = 7,
+ DW_LNS_const_add_pc = 8,
+ DW_LNS_fixed_advance_pc = 9,
+ DW_LNS_set_prologue_end = 10,
+ DW_LNS_set_epilogue_begin = 11,
+ DW_LNS_set_isa = 12
+ };
+
+
+/* DWARF extended opcode encodings. */
+enum
+ {
+ DW_LNE_end_sequence = 1,
+ DW_LNE_set_address = 2,
+ DW_LNE_define_file = 3,
+ DW_LNE_set_discriminator = 4,
+
+ DW_LNE_lo_user = 128,
+
+ DW_LNE_NVIDIA_inlined_call = 144,
+ DW_LNE_NVIDIA_set_function_name = 145,
+
+ DW_LNE_hi_user = 255
+ };
+
+
+/* DWARF macinfo type encodings. */
+enum
+ {
+ DW_MACINFO_define = 1,
+ DW_MACINFO_undef = 2,
+ DW_MACINFO_start_file = 3,
+ DW_MACINFO_end_file = 4,
+ DW_MACINFO_vendor_ext = 255
+ };
+
+
+/* DWARF debug_macro type encodings. */
+enum
+ {
+ DW_MACRO_define = 0x01,
+ DW_MACRO_undef = 0x02,
+ DW_MACRO_start_file = 0x03,
+ DW_MACRO_end_file = 0x04,
+ DW_MACRO_define_strp = 0x05,
+ DW_MACRO_undef_strp = 0x06,
+ DW_MACRO_import = 0x07,
+ DW_MACRO_define_sup = 0x08,
+ DW_MACRO_undef_sup = 0x09,
+ DW_MACRO_import_sup = 0x0a,
+ DW_MACRO_define_strx = 0x0b,
+ DW_MACRO_undef_strx = 0x0c,
+ DW_MACRO_lo_user = 0xe0,
+ DW_MACRO_hi_user = 0xff
+ };
+
+/* Old GNU extension names for DWARF5 debug_macro type encodings.
+ There are no equivalents for the supplementary object file (sup)
+ and indirect string references (strx). */
+#define DW_MACRO_GNU_define DW_MACRO_define
+#define DW_MACRO_GNU_undef DW_MACRO_undef
+#define DW_MACRO_GNU_start_file DW_MACRO_start_file
+#define DW_MACRO_GNU_end_file DW_MACRO_end_file
+#define DW_MACRO_GNU_define_indirect DW_MACRO_define_strp
+#define DW_MACRO_GNU_undef_indirect DW_MACRO_undef_strp
+#define DW_MACRO_GNU_transparent_include DW_MACRO_import
+#define DW_MACRO_GNU_lo_user DW_MACRO_lo_user
+#define DW_MACRO_GNU_hi_user DW_MACRO_hi_user
+
+
+/* Range list entry encoding. */
+enum
+ {
+ DW_RLE_end_of_list = 0x0,
+ DW_RLE_base_addressx = 0x1,
+ DW_RLE_startx_endx = 0x2,
+ DW_RLE_startx_length = 0x3,
+ DW_RLE_offset_pair = 0x4,
+ DW_RLE_base_address = 0x5,
+ DW_RLE_start_end = 0x6,
+ DW_RLE_start_length = 0x7
+ };
+
+
+/* Location list entry encoding. */
+enum
+ {
+ DW_LLE_end_of_list = 0x0,
+ DW_LLE_base_addressx = 0x1,
+ DW_LLE_startx_endx = 0x2,
+ DW_LLE_startx_length = 0x3,
+ DW_LLE_offset_pair = 0x4,
+ DW_LLE_default_location = 0x5,
+ DW_LLE_base_address = 0x6,
+ DW_LLE_start_end = 0x7,
+ DW_LLE_start_length = 0x8
+ };
+
+
+/* GNU DebugFission list entry encodings (.debug_loc.dwo). */
+enum
+ {
+ DW_LLE_GNU_end_of_list_entry = 0x0,
+ DW_LLE_GNU_base_address_selection_entry = 0x1,
+ DW_LLE_GNU_start_end_entry = 0x2,
+ DW_LLE_GNU_start_length_entry = 0x3
+ };
+
+/* DWARF5 package file section identifiers. */
+enum
+ {
+ DW_SECT_INFO = 1,
+ /* Reserved = 2, */
+ DW_SECT_ABBREV = 3,
+ DW_SECT_LINE = 4,
+ DW_SECT_LOCLISTS = 5,
+ DW_SECT_STR_OFFSETS = 6,
+ DW_SECT_MACRO = 7,
+ DW_SECT_RNGLISTS = 8,
+ };
+
+
+/* DWARF call frame instruction encodings. */
+enum
+ {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_extended = 0,
+
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ DW_CFA_val_offset = 0x14,
+ DW_CFA_val_offset_sf = 0x15,
+ DW_CFA_val_expression = 0x16,
+
+ DW_CFA_low_user = 0x1c,
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
+ DW_CFA_GNU_window_save = 0x2d,
+ DW_CFA_AARCH64_negate_ra_state = 0x2d,
+ DW_CFA_GNU_args_size = 0x2e,
+ DW_CFA_GNU_negative_offset_extended = 0x2f,
+ DW_CFA_high_user = 0x3f
+ };
+
+/* ID indicating CIE as opposed to FDE in .debug_frame. */
+enum
+ {
+ DW_CIE_ID_32 = 0xffffffffU, /* In 32-bit format CIE header. */
+ DW_CIE_ID_64 = 0xffffffffffffffffULL /* In 64-bit format CIE header. */
+ };
+
+
+/* Information for GNU unwind information. */
+enum
+ {
+ DW_EH_PE_absptr = 0x00,
+ DW_EH_PE_omit = 0xff,
+
+ /* FDE data encoding. */
+ DW_EH_PE_uleb128 = 0x01,
+ DW_EH_PE_udata2 = 0x02,
+ DW_EH_PE_udata4 = 0x03,
+ DW_EH_PE_udata8 = 0x04,
+ DW_EH_PE_sleb128 = 0x09,
+ DW_EH_PE_sdata2 = 0x0a,
+ DW_EH_PE_sdata4 = 0x0b,
+ DW_EH_PE_sdata8 = 0x0c,
+ DW_EH_PE_signed = 0x08,
+
+ /* FDE flags. */
+ DW_EH_PE_pcrel = 0x10,
+ DW_EH_PE_textrel = 0x20,
+ DW_EH_PE_datarel = 0x30,
+ DW_EH_PE_funcrel = 0x40,
+ DW_EH_PE_aligned = 0x50,
+
+ DW_EH_PE_indirect = 0x80
+ };
+
+
+/* DWARF XXX. */
+#define DW_ADDR_none 0
+
+/* Section 7.2.2 of the DWARF3 specification defines a range of escape
+ codes that can appear in the length field of certain DWARF structures.
+
+ These defines enumerate the minimum and maximum values of this range.
+ Currently only the maximum value is used (to indicate that 64-bit
+ values are going to be used in the dwarf data that accompanies the
+ structure). The other values are reserved.
+
+ Note: There is a typo in DWARF3 spec (published Dec 20, 2005). In
+ sections 7.4, 7.5.1, 7.19, 7.20 the minimum escape code is referred to
+ as 0xffffff00 whereas in fact it should be 0xfffffff0. */
+#define DWARF3_LENGTH_MIN_ESCAPE_CODE 0xfffffff0u
+#define DWARF3_LENGTH_MAX_ESCAPE_CODE 0xffffffffu
+#define DWARF3_LENGTH_64_BIT DWARF3_LENGTH_MAX_ESCAPE_CODE
+
+#endif /* dwarf.h */
diff --git a/i386-gen.c b/i386-gen.c
index 8c245ada..62bc2ad5 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -1071,7 +1071,7 @@ static void gen_bounds_epilog(void)
*bounds_ptr = 0;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, lbounds_section->data_offset);
+ func_bound_offset, PTR_SIZE);
/* generate bound local allocation */
if (offset_modified) {
diff --git a/i386-link.c b/i386-link.c
index a7969f07..72a0884b 100644
--- a/i386-link.c
+++ b/i386-link.c
@@ -4,6 +4,7 @@
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_386_32
+#define R_DATA_32U R_386_32
#define R_DATA_PTR R_386_32
#define R_JMP_SLOT R_386_JMP_SLOT
#define R_GLOB_DAT R_386_GLOB_DAT
diff --git a/lib/Makefile b/lib/Makefile
index 43942fc6..74722b61 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -27,7 +27,7 @@ arm-libtcc1-usegcc ?= no
ifeq "$($(T)-libtcc1-usegcc)" "yes"
XCC = $(CC)
XAR = $(AR)
- XFLAGS = $(CFLAGS) -fPIC -gstabs -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
+ XFLAGS = $(CFLAGS) -fPIC -gdwarf -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
endif
ifneq ($(CONFIG_backtrace),no)
diff --git a/lib/bt-exe.c b/lib/bt-exe.c
index f0e494d4..3f9cc929 100644
--- a/lib/bt-exe.c
+++ b/lib/bt-exe.c
@@ -18,6 +18,10 @@ void __bt_init(rt_context *p, int num_callers)
__attribute__((weak)) void __bound_init(void*, int);
struct rt_context *rc = &g_rtctxt;
//fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr);
+ /* call __bound_init here due to redirection of sigaction */
+ /* needed to add global symbols */
+ if (__bound_init && p->bounds_start)
+ __bound_init(p->bounds_start, -1);
if (num_callers) {
memcpy(rc, p, offsetof(rt_context, next));
rc->num_callers = num_callers - 1;
diff --git a/libtcc.c b/libtcc.c
index 1feb7410..e7335922 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -1722,6 +1722,12 @@ static void args_parser_listfile(TCCState *s,
*pargc = s->argc = argc, *pargv = s->argv = argv;
}
+#ifdef CONFIG_DWARF
+#define DWARF_VERSION atoi(CONFIG_DWARF)
+#else
+#define DWARF_VERSION 0
+#endif
+
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
{
TCCState *s1 = s;
@@ -1819,6 +1825,7 @@ reparse:
s->rt_num_callers = atoi(optarg);
s->do_backtrace = 1;
s->do_debug = 1;
+ s->dwarf = DWARF_VERSION;
break;
#endif
#ifdef CONFIG_TCC_BCHECK
@@ -1826,16 +1833,22 @@ reparse:
s->do_bounds_check = 1;
s->do_backtrace = 1;
s->do_debug = 1;
+ s->dwarf = DWARF_VERSION;
break;
#endif
case TCC_OPTION_g:
/* Use "-g" as alias for "-g1". Use "-g0" to disable debug */
/* Other common used values: "-g0", "-g1", "-g2" and "-g3" */
/* no failure with unsupported options */
- if (isnum(*optarg))
+ s->do_debug = 1;
+ s->dwarf = DWARF_VERSION;
+ if (*optarg == 'd') {
+ s->dwarf = 5;
+ if (!strncmp(optarg,"dwarf-",6))
+ s->dwarf = atoi(optarg + 6);
+ }
+ else if (isnum(*optarg))
s->do_debug = atoi(optarg);
- else
- s->do_debug = 1;
break;
case TCC_OPTION_c:
x = TCC_OUTPUT_OBJ;
diff --git a/riscv64-gen.c b/riscv64-gen.c
index 9a521d5a..b728d59e 100644
--- a/riscv64-gen.c
+++ b/riscv64-gen.c
@@ -471,7 +471,7 @@ static void gen_bounds_epilog(void)
*bounds_ptr = 0;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, lbounds_section->data_offset);
+ func_bound_offset, PTR_SIZE);
label.type.t = VT_VOID | VT_STATIC;
/* generate bound local allocation */
diff --git a/riscv64-link.c b/riscv64-link.c
index 2aeefefb..cf00c67d 100644
--- a/riscv64-link.c
+++ b/riscv64-link.c
@@ -3,6 +3,7 @@
#define EM_TCC_TARGET EM_RISCV
#define R_DATA_32 R_RISCV_32
+#define R_DATA_32U R_RISCV_32
#define R_DATA_PTR R_RISCV_64
#define R_JMP_SLOT R_RISCV_JUMP_SLOT
#define R_GLOB_DAT R_RISCV_64
diff --git a/tcc-doc.texi b/tcc-doc.texi
index fa223250..83f05166 100644
--- a/tcc-doc.texi
+++ b/tcc-doc.texi
@@ -349,12 +349,15 @@ Turn on/off linking of all objects in archives.
Debugger options:
@table @option
-@item -g
-Generate run time debug information so that you get clear run time
+@item -g[x]
+Generate run time stab debug information so that you get clear run time
error messages: @code{ test.c:68: in function 'test5()': dereferencing
invalid pointer} instead of the laconic @code{Segmentation
fault}.
+@item -gdwarf[-x]
+Generate run time dwarf debug information instead of stab debug information.
+
@item -b
Generate additional support code to check memory allocations and array/pointer
bounds (@pxref{Bounds}). @option{-g} is implied.
diff --git a/tcc.c b/tcc.c
index ce1945a1..693eb216 100644
--- a/tcc.c
+++ b/tcc.c
@@ -58,7 +58,8 @@ static const char help[] =
" -soname set name for shared library to be used at runtime\n"
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
"Debugger options:\n"
- " -g generate runtime debug info\n"
+ " -g[x] generate stab runtime debug info\n"
+ " -gdwarf[-x] generate dwarf runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
" -b compile with built-in memory and bounds checker (implies -g)\n"
#endif
diff --git a/tcc.h b/tcc.h
index d66baf78..03e83343 100644
--- a/tcc.h
+++ b/tcc.h
@@ -368,6 +368,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
#include "libtcc.h"
#include "elf.h"
#include "stab.h"
+#include "dwarf.h"
/* -------------------------------------------- */
@@ -792,6 +793,7 @@ struct TCCState {
/* compile with debug symbol (and use them if error during execution) */
unsigned char do_debug;
+ unsigned char dwarf;
unsigned char do_backtrace;
#ifdef CONFIG_TCC_BCHECK
/* compile with built-in memory and bounds checker */
@@ -922,6 +924,12 @@ struct TCCState {
Section *symtab_section;
/* debug sections */
Section *stab_section;
+ Section *dwarf_info_section;
+ Section *dwarf_abbrev_section;
+ Section *dwarf_line_section;
+ Section *dwarf_aranges_section;
+ Section *dwarf_str_section;
+ Section *dwarf_line_str_section;
/* Is there a new undefined sym since last new_undef_sym() */
int new_undef_sym;
@@ -1822,6 +1830,12 @@ ST_FUNC void post_sem(TCCSem *p);
#define symtab_section TCC_STATE_VAR(symtab_section)
#define stab_section TCC_STATE_VAR(stab_section)
#define stabstr_section stab_section->link
+#define dwarf_info_section TCC_STATE_VAR(dwarf_info_section)
+#define dwarf_abbrev_section TCC_STATE_VAR(dwarf_abbrev_section)
+#define dwarf_line_section TCC_STATE_VAR(dwarf_line_section)
+#define dwarf_aranges_section TCC_STATE_VAR(dwarf_aranges_section)
+#define dwarf_str_section TCC_STATE_VAR(dwarf_str_section)
+#define dwarf_line_str_section TCC_STATE_VAR(dwarf_line_str_section)
#define gnu_ext TCC_STATE_VAR(gnu_ext)
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
#define tcc_error TCC_SET_STATE(_tcc_error)
diff --git a/tccelf.c b/tccelf.c
index 9e860b59..d4823eb9 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -47,6 +47,8 @@ struct sym_version {
/* section is dynsymtab_section */
#define SHF_DYNSYM 0x40000000
+#define DWARF_DEBUG(s) (!strncmp((s), ".debug_", sizeof(".debug_")-1))
+
/* ------------------------------------------------------------------------- */
ST_FUNC void tccelf_new(TCCState *s)
@@ -102,12 +104,39 @@ ST_FUNC void tccelf_stab_new(TCCState *s)
if (s->do_backtrace && s->output_type != TCC_OUTPUT_MEMORY)
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
#endif
- stab_section = new_section(s, ".stab", SHT_PROGBITS, shf);
- stab_section->sh_entsize = sizeof(Stab_Sym);
- stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value;
- stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, shf);
- /* put first entry */
- put_stabs(s, "", 0, 0, 0, 0);
+ if (s->dwarf) {
+ dwarf_info_section =
+ new_section(s, ".debug_info", SHT_PROGBITS, shf);
+ dwarf_abbrev_section =
+ new_section(s, ".debug_abbrev", SHT_PROGBITS, shf);
+ dwarf_line_section =
+ new_section(s, ".debug_line", SHT_PROGBITS, shf);
+ dwarf_aranges_section =
+ new_section(s, ".debug_aranges", SHT_PROGBITS, shf);
+ shf |= SHF_MERGE | SHF_STRINGS;
+ dwarf_str_section =
+ new_section(s, ".debug_str", SHT_PROGBITS, shf);
+ dwarf_str_section->sh_entsize = 1;
+ dwarf_info_section->sh_addralign =
+ dwarf_abbrev_section->sh_addralign =
+ dwarf_line_section->sh_addralign =
+ dwarf_aranges_section->sh_addralign =
+ dwarf_str_section->sh_addralign = 1;
+ if (s1->dwarf >= 5) {
+ dwarf_line_str_section =
+ new_section(s, ".debug_line_str", SHT_PROGBITS, shf);
+ dwarf_line_str_section->sh_entsize = 1;
+ dwarf_line_str_section->sh_addralign = 1;
+ }
+ }
+ else {
+ stab_section = new_section(s, ".stab", SHT_PROGBITS, shf);
+ stab_section->sh_entsize = sizeof(Stab_Sym);
+ stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value;
+ stab_section->link = new_section(s, ".stabstr", SHT_STRTAB, shf);
+ /* put first entry */
+ put_stabs(s, "", 0, 0, 0, 0);
+ }
}
static void free_section(Section *s)
@@ -944,7 +973,10 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
sym->st_value = 0;
else
tcc_error_noabort("undefined symbol '%s'", name);
- } else if (sh_num < SHN_LORESERVE) {
+ } else if (sh_num < SHN_LORESERVE &&
+ /* Debug dwarf relocations must be relative to start section.
+ This only happens when backtrace is used. */
+ (sym->st_name || !DWARF_DEBUG(s1->sections[sym->st_shndx]->name))) {
/* add section base */
sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
}
@@ -1330,7 +1362,7 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t
if (sec && offs == -1)
offs = sec->data_offset;
return set_elf_sym(symtab_section, offs, 0,
- ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
+ ELFW(ST_INFO)(name && !strstr(name, "__dwarf") ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
}
static void add_init_array_defines(TCCState *s1, const char *section_name)
@@ -1395,10 +1427,10 @@ static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset
}
#ifdef CONFIG_TCC_BACKTRACE
-static void put_ptr(TCCState *s1, Section *s, int offs)
+static void put_ptr(TCCState *s1, Section *s, int offs, const char *name)
{
int c;
- c = set_global_sym(s1, NULL, s, offs);
+ c = set_global_sym(s1, name, s, offs);
s = data_section;
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
section_ptr_add(s, PTR_SIZE);
@@ -1415,16 +1447,29 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
o = s->data_offset;
/* create (part of) a struct rt_context (see tccrun.c) */
- put_ptr(s1, stab_section, 0);
- put_ptr(s1, stab_section, -1);
- put_ptr(s1, stab_section->link, 0);
+ if (s1->dwarf) {
+ put_ptr(s1, dwarf_line_section, 0, "__dwarf_line");
+ put_ptr(s1, dwarf_line_section, -1, "__dwarf_line_end");
+ if (s1->dwarf >= 5)
+ put_ptr(s1, dwarf_line_str_section, 0, "__dwarf_line_str");
+ else
+ put_ptr(s1, dwarf_str_section, 0, "__dwarf_str");
+ put_ptr(s1, text_section, 0, "__dwarf_text");
+ }
+ else {
+ put_ptr(s1, stab_section, 0, NULL);
+ put_ptr(s1, stab_section, -1, NULL);
+ put_ptr(s1, stab_section->link, 0, NULL);
+ section_ptr_add(s, PTR_SIZE);
+ }
+ /* skip esym_start/esym_end/elf_str (not loaded) */
section_ptr_add(s, 3 * PTR_SIZE);
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
- put_ptr(s1, NULL, 0);
+ put_ptr(s1, NULL, 0, NULL);
n = 2 * PTR_SIZE;
#ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check) {
- put_ptr(s1, bounds_section, 0);
+ put_ptr(s1, bounds_section, 0, NULL);
n -= PTR_SIZE;
}
#endif
@@ -1849,6 +1894,8 @@ static int set_sec_sizes(TCCState *s1)
/* when generating a DLL, we include relocations but
we may patch them */
if (file_type == TCC_OUTPUT_DLL
+ /* Do not include dwarf relocatable sections. */
+ && !DWARF_DEBUG(s1->sections[s->sh_info]->name)
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
int count = prepare_dynamic_rel(s1, s);
if (count) {
@@ -2963,8 +3010,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
strcmp(strsec + sh->sh_name, ".stabstr")
)
continue;
- if (seencompressed
- && !strncmp(strsec + sh->sh_name, ".debug_", sizeof(".debug_")-1))
+ if (seencompressed && DWARF_DEBUG(strsec + sh->sh_name))
continue;
sh = &shdr[i];
diff --git a/tccgen.c b/tccgen.c
index d1e0823a..3754fc98 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -142,52 +142,56 @@ static void init_prec(void);
static const struct {
int type;
+ int size;
+ int encoding;
const char *name;
} default_debug[] = {
- { VT_INT, "int:t1=r1;-2147483648;2147483647;" },
- { VT_BYTE, "char:t2=r2;0;127;" },
+ { VT_INT, 4, DW_ATE_signed, "int:t1=r1;-2147483648;2147483647;" },
+ { VT_BYTE, 1, DW_ATE_signed_char, "char:t2=r2;0;127;" },
#if LONG_SIZE == 4
- { VT_LONG | VT_INT, "long int:t3=r3;-2147483648;2147483647;" },
+ { VT_LONG | VT_INT, 4, DW_ATE_signed, "long int:t3=r3;-2147483648;2147483647;" },
#else
- { VT_LLONG | VT_LONG, "long int:t3=r3;-9223372036854775808;9223372036854775807;" },
+ { VT_LLONG | VT_LONG, 8, DW_ATE_signed, "long int:t3=r3;-9223372036854775808;9223372036854775807;" },
#endif
- { VT_INT | VT_UNSIGNED, "unsigned int:t4=r4;0;037777777777;" },
+ { VT_INT | VT_UNSIGNED, 4, DW_ATE_unsigned, "unsigned int:t4=r4;0;037777777777;" },
#if LONG_SIZE == 4
- { VT_LONG | VT_INT | VT_UNSIGNED, "long unsigned int:t5=r5;0;037777777777;" },
+ { VT_LONG | VT_INT | VT_UNSIGNED, 4, DW_ATE_unsigned, "long unsigned int:t5=r5;0;037777777777;" },
#else
/* use octal instead of -1 so size_t works (-gstabs+ in gcc) */
- { VT_LLONG | VT_LONG | VT_UNSIGNED, "long unsigned int:t5=r5;0;01777777777777777777777;" },
+ { VT_LLONG | VT_LONG | VT_UNSIGNED, 8, DW_ATE_unsigned, "long unsigned int:t5=r5;0;01777777777777777777777;" },
#endif
- { VT_QLONG, "__int128:t6=r6;0;-1;" },
- { VT_QLONG | VT_UNSIGNED, "__int128 unsigned:t7=r7;0;-1;" },
- { VT_LLONG, "long long int:t8=r8;-9223372036854775808;9223372036854775807;" },
- { VT_LLONG | VT_UNSIGNED, "long long unsigned int:t9=r9;0;01777777777777777777777;" },
- { VT_SHORT, "short int:t10=r10;-32768;32767;" },
- { VT_SHORT | VT_UNSIGNED, "short unsigned int:t11=r11;0;65535;" },
- { VT_BYTE | VT_DEFSIGN, "signed char:t12=r12;-128;127;" },
- { VT_BYTE | VT_DEFSIGN | VT_UNSIGNED, "unsigned char:t13=r13;0;255;" },
- { VT_FLOAT, "float:t14=r1;4;0;" },
- { VT_DOUBLE, "double:t15=r1;8;0;" },
+ { VT_QLONG, 16, DW_ATE_signed, "__int128:t6=r6;0;-1;" },
+ { VT_QLONG | VT_UNSIGNED, 16, DW_ATE_unsigned, "__int128 unsigned:t7=r7;0;-1;" },
+ { VT_LLONG, 8, DW_ATE_signed, "long long int:t8=r8;-9223372036854775808;9223372036854775807;" },
+ { VT_LLONG | VT_UNSIGNED, 8, DW_ATE_unsigned, "long long unsigned int:t9=r9;0;01777777777777777777777;" },
+ { VT_SHORT, 2, DW_ATE_signed, "short int:t10=r10;-32768;32767;" },
+ { VT_SHORT | VT_UNSIGNED, 2, DW_ATE_unsigned, "short unsigned int:t11=r11;0;65535;" },
+ { VT_BYTE | VT_DEFSIGN, 1, DW_ATE_signed_char, "signed char:t12=r12;-128;127;" },
+ { VT_BYTE | VT_DEFSIGN | VT_UNSIGNED, 1, DW_ATE_unsigned_char, "unsigned char:t13=r13;0;255;" },
+ { VT_FLOAT, 4, DW_ATE_float, "float:t14=r1;4;0;" },
+ { VT_DOUBLE, 8, DW_ATE_float, "double:t15=r1;8;0;" },
#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- { VT_DOUBLE | VT_LONG, "long double:t16=r1;8;0;" },
+ { VT_DOUBLE | VT_LONG, 8, DW_ATE_float, "long double:t16=r1;8;0;" },
#else
- { VT_LDOUBLE, "long double:t16=r1;16;0;" },
+ { VT_LDOUBLE, 16, DW_ATE_float, "long double:t16=r1;16;0;" },
#endif
- { -1, "_Float32:t17=r1;4;0;" },
- { -1, "_Float64:t18=r1;8;0;" },
- { -1, "_Float128:t19=r1;16;0;" },
- { -1, "_Float32x:t20=r1;8;0;" },
- { -1, "_Float64x:t21=r1;16;0;" },
- { -1, "_Decimal32:t22=r1;4;0;" },
- { -1, "_Decimal64:t23=r1;8;0;" },
- { -1, "_Decimal128:t24=r1;16;0;" },
+ { -1, -1, -1, "_Float32:t17=r1;4;0;" },
+ { -1, -1, -1, "_Float64:t18=r1;8;0;" },
+ { -1, -1, -1, "_Float128:t19=r1;16;0;" },
+ { -1, -1, -1, "_Float32x:t20=r1;8;0;" },
+ { -1, -1, -1, "_Float64x:t21=r1;16;0;" },
+ { -1, -1, -1, "_Decimal32:t22=r1;4;0;" },
+ { -1, -1, -1, "_Decimal64:t23=r1;8;0;" },
+ { -1, -1, -1, "_Decimal128:t24=r1;16;0;" },
/* if default char is unsigned */
- { VT_BYTE | VT_UNSIGNED, "unsigned char:t25=r25;0;255;" },
+ { VT_BYTE | VT_UNSIGNED, 1, DW_ATE_unsigned_char, "unsigned char:t25=r25;0;255;" },
/* boolean type */
- { VT_BOOL, "bool:t26=r26;0;255;" },
- { VT_VOID, "void:t27=27" },
+ { VT_BOOL, 1, DW_ATE_unsigned_char, "bool:t26=r26;0;255;" },
+ { VT_VOID, 1, DW_ATE_void, "void:t27=27" },
};
+#define N_DEFAULT_DEBUG (sizeof (default_debug) / sizeof (default_debug[0]))
+
static int debug_next_type;
static struct debug_hash {
@@ -207,10 +211,231 @@ static struct debug_info {
char *str;
Section *sec;
int sym_index;
+ int info;
+ int file;
+ int line;
} *sym;
struct debug_info *child, *next, *last, *parent;
} *debug_info, *debug_info_root;
+/* dwarf debug */
+
+#define DWARF_LINE_BASE -5
+#define DWARF_LINE_RANGE 14
+#define DWARF_OPCODE_BASE 13
+
+#if defined TCC_TARGET_ARM64
+#define DWARF_MIN_INSTR_LEN 4
+#elif defined TCC_TARGET_ARM
+#define DWARF_MIN_INSTR_LEN 2
+#else
+#define DWARF_MIN_INSTR_LEN 1
+#endif
+
+#define DWARF_ABBREV_COMPILE_UNIT 1
+#define DWARF_ABBREV_BASE_TYPE 2
+#define DWARF_ABBREV_VARIABLE_EXTERNAL 3
+#define DWARF_ABBREV_VARIABLE_STATIC 4
+#define DWARF_ABBREV_VARIABLE_LOCAL 5
+#define DWARF_ABBREV_FORMAL_PARAMETER 6
+#define DWARF_ABBREV_POINTER 7
+#define DWARF_ABBREV_ARRAY_TYPE 8
+#define DWARF_ABBREV_SUBRANGE_TYPE 9
+#define DWARF_ABBREV_TYPEDEF 10
+#define DWARF_ABBREV_ENUMERATOR 11
+#define DWARF_ABBREV_ENUMERATION_TYPE 12
+#define DWARF_ABBREV_MEMBER 13
+#define DWARF_ABBREV_MEMBER_BF 14
+#define DWARF_ABBREV_STRUCTURE_TYPE 15
+#define DWARF_ABBREV_UNION_TYPE 16
+#define DWARF_ABBREV_SUBPROGRAM_EXTERNAL 17
+#define DWARF_ABBREV_SUBPROGRAM_STATIC 18
+#define DWARF_ABBREV_LEXICAL_BLOCK 19
+
+static const unsigned char dwarf_abbrev_init[] = {
+ DWARF_ABBREV_COMPILE_UNIT, DW_TAG_compile_unit, 1,
+ DW_AT_producer, DW_FORM_strp,
+ DW_AT_language, DW_FORM_data1,
+ DW_AT_name, DW_FORM_line_strp,
+ DW_AT_comp_dir, DW_FORM_line_strp,
+ DW_AT_low_pc, DW_FORM_addr,
+#if PTR_SIZE == 4
+ DW_AT_high_pc, DW_FORM_data4,
+#else
+ DW_AT_high_pc, DW_FORM_data8,
+#endif
+ DW_AT_stmt_list, DW_FORM_data4,
+ 0, 0,
+ DWARF_ABBREV_BASE_TYPE, DW_TAG_base_type, 0,
+ DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_encoding, DW_FORM_data1,
+ DW_AT_name, DW_FORM_strp,
+ 0, 0,
+ DWARF_ABBREV_VARIABLE_EXTERNAL, DW_TAG_variable, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_external, DW_FORM_flag,
+ DW_AT_location, DW_FORM_block1,
+ 0, 0,
+ DWARF_ABBREV_VARIABLE_STATIC, DW_TAG_variable, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_location, DW_FORM_block1,
+ 0, 0,
+ DWARF_ABBREV_VARIABLE_LOCAL, DW_TAG_variable, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_location, DW_FORM_block1,
+ 0, 0,
+ DWARF_ABBREV_FORMAL_PARAMETER, DW_TAG_formal_parameter, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_location, DW_FORM_block1,
+ 0, 0,
+ DWARF_ABBREV_POINTER, DW_TAG_pointer_type, 0,
+ DW_AT_byte_size, DW_FORM_data1,
+ DW_AT_byte_size, DW_FORM_implicit_const, 8,
+ DW_AT_type, DW_FORM_ref4,
+ 0, 0,
+ DWARF_ABBREV_ARRAY_TYPE, DW_TAG_array_type, 1,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_sibling, DW_FORM_ref4,
+ 0, 0,
+ DWARF_ABBREV_SUBRANGE_TYPE, DW_TAG_subrange_type, 0,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_upper_bound, DW_FORM_udata,
+ 0, 0,
+ DWARF_ABBREV_TYPEDEF, DW_TAG_typedef, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ 0, 0,
+ DWARF_ABBREV_ENUMERATOR, DW_TAG_enumerator, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_const_value, DW_FORM_data4,
+ 0, 0,
+ DWARF_ABBREV_ENUMERATION_TYPE, DW_TAG_enumeration_type, 1,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_encoding, DW_FORM_data1,
+ DW_AT_byte_size, DW_FORM_data1,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_sibling, DW_FORM_ref4,
+ 0, 0,
+ DWARF_ABBREV_MEMBER, DW_TAG_member, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_data_member_location, DW_FORM_udata,
+ 0, 0,
+ DWARF_ABBREV_MEMBER_BF, DW_TAG_member, 0,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_bit_size, DW_FORM_udata,
+ DW_AT_data_bit_offset, DW_FORM_udata,
+ 0, 0,
+ DWARF_ABBREV_STRUCTURE_TYPE, DW_TAG_structure_type, 1,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_sibling, DW_FORM_ref4,
+ 0, 0,
+ DWARF_ABBREV_UNION_TYPE, DW_TAG_union_type, 1,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_byte_size, DW_FORM_udata,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_sibling, DW_FORM_ref4,
+ 0, 0,
+ DWARF_ABBREV_SUBPROGRAM_EXTERNAL, DW_TAG_subprogram, 1,
+ DW_AT_external, DW_FORM_flag,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_low_pc, DW_FORM_addr,
+#if PTR_SIZE == 4
+ DW_AT_high_pc, DW_FORM_data4,
+#else
+ DW_AT_high_pc, DW_FORM_data8,
+#endif
+ DW_AT_sibling, DW_FORM_ref4,
+ DW_AT_frame_base, DW_FORM_block1,
+ 0, 0,
+ DWARF_ABBREV_SUBPROGRAM_STATIC, DW_TAG_subprogram, 1,
+ DW_AT_name, DW_FORM_strp,
+ DW_AT_decl_file, DW_FORM_udata,
+ DW_AT_decl_line, DW_FORM_udata,
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_low_pc, DW_FORM_addr,
+#if PTR_SIZE == 4
+ DW_AT_high_pc, DW_FORM_data4,
+#else
+ DW_AT_high_pc, DW_FORM_data8,
+#endif
+ DW_AT_sibling, DW_FORM_ref4,
+ DW_AT_frame_base, DW_FORM_block1,
+ 0, 0,
+ DWARF_ABBREV_LEXICAL_BLOCK, DW_TAG_lexical_block, 1,
+ DW_AT_low_pc, DW_FORM_addr,
+#if PTR_SIZE == 4
+ DW_AT_high_pc, DW_FORM_data4,
+#else
+ DW_AT_high_pc, DW_FORM_data8,
+#endif
+ 0, 0,
+ 0
+};
+
+static const unsigned char dwarf_line_opcodes[] = {
+ 0 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,1
+};
+
+static struct {
+ int info;
+ int abbrev;
+ int line;
+ int str;
+ int line_str;
+} dwarf_sym;
+
+static struct {
+ int start;
+ int dir_size;
+ char **dir_table;
+ int filename_size;
+ struct dwarf_filename_struct {
+ int dir_entry;
+ char *name;
+ } *filename_table;
+ int line_size;
+ int line_max_size;
+ unsigned char *line_data;
+ int cur_file;
+ int last_file;
+ int last_pc;
+ int last_line;
+} dwarf_line;
+
+static struct {
+ int start;
+ Sym *func;
+ int line;
+ int base_type_used[N_DEFAULT_DEBUG];
+} dwarf_info;
+
+/* test coverage */
+
static struct {
unsigned long offset;
unsigned long last_file_name;
@@ -404,36 +629,323 @@ void pv (const char *lbl, int a, int b)
#endif
/* ------------------------------------------------------------------------- */
+
+#define dwarf_data1(s,data) \
+ { unsigned char *p = section_ptr_add((s), 1); *p = (data); }
+#define dwarf_data2(s,data) \
+ write16le(section_ptr_add((s), 2), (data))
+#define dwarf_data4(s,data) \
+ write32le(section_ptr_add((s), 4), (data))
+#define dwarf_data8(s,data) \
+ write64le(section_ptr_add((s), 8), (data))
+
+static int dwarf_get_section_sym(Section *s)
+{
+ return put_elf_sym(symtab_section, 0, 0,
+ ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
+ s->sh_num, NULL);
+}
+
+static void dwarf_reloc(Section *s, int sym, int rel)
+{
+ put_elf_reloca(symtab_section, s, s->data_offset, rel, sym, 0);
+}
+
+static void dwarf_string(Section *s, Section *dw, int sym, const char *str)
+{
+ int offset, len;
+ char *ptr;
+
+ len = strlen(str) + 1;
+ offset = dw->data_offset;
+ ptr = section_ptr_add(dw, len);
+ memmove(ptr, str, len);
+ put_elf_reloca(symtab_section, s, s->data_offset, R_DATA_32U, sym,
+ PTR_SIZE == 4 ? 0 : offset);
+ dwarf_data4(s, PTR_SIZE == 4 ? offset : 0);
+}
+
+static void dwarf_strp(Section *s, const char *str)
+{
+ dwarf_string(s, dwarf_str_section, dwarf_sym.str, str);
+}
+
+static void dwarf_line_strp(Section *s, const char *str)
+{
+ dwarf_string(s, dwarf_line_str_section, dwarf_sym.line_str, str);
+}
+
+static void dwarf_line_op(unsigned char op)
+{
+ if (dwarf_line.line_size >= dwarf_line.line_max_size) {
+ dwarf_line.line_max_size += 1024;
+ dwarf_line.line_data =
+ (unsigned char *)tcc_realloc(dwarf_line.line_data,
+ dwarf_line.line_max_size);
+ }
+ dwarf_line.line_data[dwarf_line.line_size++] = op;
+}
+
+static void dwarf_file(TCCState *s1)
+{
+ int i;
+ char *filename;
+
+ if (!s1->do_debug || !s1->dwarf)
+ return;
+ filename = strrchr(file->filename, '/');
+ if (filename == NULL) {
+ for (i = 1; i < dwarf_line.filename_size; i++)
+ if (dwarf_line.filename_table[i].dir_entry == 0 &&
+ strcmp(dwarf_line.filename_table[i].name,
+ file->filename) == 0) {
+ dwarf_line.cur_file = i;
+ return;
+ }
+ }
+ else {
+ int j;
+ char *undo = filename;
+
+ *filename++ = '\0';
+ for (i = 0; i < dwarf_line.dir_size; i++)
+ if (strcmp(dwarf_line.dir_table[i], file->filename) == 0)
+ for (j = 1; j < dwarf_line.filename_size; j++)
+ if (dwarf_line.filename_table[i].dir_entry == i &&
+ strcmp(dwarf_line.filename_table[j].name,
+ filename) == 0) {
+ *undo = '/';
+ dwarf_line.cur_file = j;
+ return;
+ }
+ *undo = '/';
+ }
+ return;
+}
+
+#if 0
+static int dwarf_uleb128_size (unsigned long long value)
+{
+ int size = 0;
+
+ do {
+ value >>= 7;
+ size++;
+ } while (value != 0);
+ return size;
+}
+#endif
+
+static int dwarf_sleb128_size (long long value)
+{
+ int more;
+ int size = 0;
+
+ do {
+ unsigned char byte = value & 0x7f;
+
+ value = (value >> 7) | ~(-1 >> 7);
+ more =!((((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+ size++;
+ } while (more);
+ return size;
+}
+
+static void dwarf_uleb128 (Section *s, unsigned long long value)
+{
+ do {
+ unsigned char byte = value & 0x7f;
+
+ value >>= 7;
+ if (value)
+ byte |= 0x80;
+ dwarf_data1(s, byte);
+ } while (value != 0);
+}
+
+static void dwarf_sleb128 (Section *s, long long value)
+{
+ int more;
+
+ do {
+ unsigned char byte = value & 0x7f;
+
+ value = (value >> 7) | ~(-1 >> 7);
+ more =!((((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+ if (more)
+ byte |= 0x80;
+ dwarf_data1(s, byte);
+ } while (more);
+}
+
+static void dwarf_uleb128_op (unsigned long long value)
+{
+ do {
+ unsigned char byte = value & 0x7f;
+
+ value >>= 7;
+ if (value)
+ byte |= 0x80;
+ dwarf_line_op(byte);
+ } while (value != 0);
+}
+
+static void dwarf_sleb128_op (long long value)
+{
+ int more;
+
+ do {
+ unsigned char byte = value & 0x7f;
+
+ value = (value >> 7) | ~(-1 >> 7);
+ more =!((((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+ if (more)
+ byte |= 0x80;
+ dwarf_line_op(byte);
+ } while (more);
+}
+
/* start of translation unit info */
ST_FUNC void tcc_debug_start(TCCState *s1)
{
if (s1->do_debug) {
int i;
+ char *filename = file->prev ? file->prev->filename : file->filename;
char buf[512];
- /* file info: full path + filename */
- section_sym = put_elf_sym(symtab_section, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
- text_section->sh_num, NULL);
getcwd(buf, sizeof(buf));
#ifdef _WIN32
normalize_slashes(buf);
#endif
pstrcat(buf, sizeof(buf), "/");
- put_stabs_r(s1, buf, N_SO, 0, 0,
- text_section->data_offset, text_section, section_sym);
- put_stabs_r(s1, file->prev ? file->prev->filename : file->filename,
- N_SO, 0, 0,
- text_section->data_offset, text_section, section_sym);
- for (i = 0; i < sizeof (default_debug) / sizeof (default_debug[0]); i++)
- put_stabs(s1, default_debug[i].name, N_LSYM, 0, 0, 0);
+ if (s1->dwarf) {
+ int start_abbrev;
+ unsigned char *ptr;
+
+ /* dwarf_abbrev */
+ start_abbrev = dwarf_abbrev_section->data_offset;
+ ptr = section_ptr_add(dwarf_abbrev_section, sizeof(dwarf_abbrev_init));
+ memcpy(ptr, dwarf_abbrev_init, sizeof(dwarf_abbrev_init));
+
+ if (s1->dwarf < 5) {
+ while (*ptr) {
+ ptr += 3;
+ while (*ptr) {
+ if (ptr[1] == DW_FORM_line_strp)
+ ptr[1] = DW_FORM_strp;
+ ptr += 2;
+ }
+ }
+ }
+
+ dwarf_sym.info = dwarf_get_section_sym(dwarf_info_section);
+ dwarf_sym.abbrev = dwarf_get_section_sym(dwarf_abbrev_section);
+ dwarf_sym.line = dwarf_get_section_sym(dwarf_line_section);
+ dwarf_sym.str = dwarf_get_section_sym(dwarf_str_section);
+ if (tcc_state->dwarf >= 5)
+ dwarf_sym.line_str = dwarf_get_section_sym(dwarf_line_str_section);
+ else {
+ dwarf_line_str_section = dwarf_str_section;
+ dwarf_sym.line_str = dwarf_sym.str;
+ }
+ section_sym = dwarf_get_section_sym(text_section);
+
+ /* dwarf_info */
+ dwarf_info.start = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0); // size
+ dwarf_data2(dwarf_info_section, s1->dwarf); // version
+ if (s1->dwarf >= 5) {
+ dwarf_data1(dwarf_info_section, DW_UT_compile); // unit type
+ dwarf_data1(dwarf_info_section, PTR_SIZE);
+ dwarf_reloc(dwarf_info_section, dwarf_sym.abbrev, R_DATA_32U);
+ dwarf_data4(dwarf_info_section, start_abbrev);
+ }
+ else {
+ dwarf_reloc(dwarf_info_section, dwarf_sym.abbrev, R_DATA_32U);
+ dwarf_data4(dwarf_info_section, start_abbrev);
+ dwarf_data1(dwarf_info_section, PTR_SIZE);
+ }
+
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_COMPILE_UNIT);
+ dwarf_strp(dwarf_info_section, "tcc " TCC_VERSION);
+ dwarf_data1(dwarf_info_section, DW_LANG_C11);
+ dwarf_line_strp(dwarf_info_section, filename);
+ dwarf_line_strp(dwarf_info_section, buf);
+ dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
+#if PTR_SIZE == 4
+ dwarf_data4(dwarf_info_section, ind); // low pc
+ dwarf_data4(dwarf_info_section, 0); // high pc
+#else
+ dwarf_data8(dwarf_info_section, ind); // low pc
+ dwarf_data8(dwarf_info_section, 0); // high pc
+#endif
+ dwarf_reloc(dwarf_info_section, dwarf_sym.line, R_DATA_32U);
+ dwarf_data4(dwarf_info_section, dwarf_line_section->data_offset); // stmt_list
+
+ /* dwarf_line */
+ dwarf_line.start = dwarf_line_section->data_offset;
+ dwarf_data4(dwarf_line_section, 0); // length
+ dwarf_data2(dwarf_line_section, s1->dwarf); // version
+ if (s1->dwarf >= 5) {
+ dwarf_data1(dwarf_line_section, PTR_SIZE); // address size
+ dwarf_data1(dwarf_line_section, 0); // segment selector
+ }
+ dwarf_data4(dwarf_line_section, 0); // prologue Length
+ dwarf_data1(dwarf_line_section, DWARF_MIN_INSTR_LEN);
+ if (s1->dwarf >= 4)
+ dwarf_data1(dwarf_line_section, 1); // maximum ops per instruction
+ dwarf_data1(dwarf_line_section, 1); // Initial value of 'is_stmt'
+ dwarf_data1(dwarf_line_section, DWARF_LINE_BASE);
+ dwarf_data1(dwarf_line_section, DWARF_LINE_RANGE);
+ dwarf_data1(dwarf_line_section, DWARF_OPCODE_BASE);
+ ptr = section_ptr_add(dwarf_line_section, sizeof(dwarf_line_opcodes));
+ memcpy(ptr, dwarf_line_opcodes, sizeof(dwarf_line_opcodes));
+ dwarf_line.dir_size = 1;
+ dwarf_line.dir_table = (char **) tcc_malloc(sizeof (char *));
+ dwarf_line.dir_table[0] = tcc_strdup(buf);
+ /* line state machine starts with file 1 instead of 0 */
+ dwarf_line.filename_size = 2;
+ dwarf_line.filename_table =
+ (struct dwarf_filename_struct *)
+ tcc_malloc(2*sizeof (struct dwarf_filename_struct));
+ dwarf_line.filename_table[0].dir_entry = 0;
+ dwarf_line.filename_table[0].name = tcc_strdup(filename);
+ dwarf_line.filename_table[1].dir_entry = 0;
+ dwarf_line.filename_table[1].name = tcc_strdup(filename);
+ dwarf_line.line_size = dwarf_line.line_max_size = 0;
+ dwarf_line.line_data = NULL;
+ dwarf_line.cur_file = 1;
+ dwarf_line.last_file = 0;
+ dwarf_line.last_pc = 0;
+ dwarf_line.last_line = 1;
+ dwarf_line_op(0); // extended
+ dwarf_uleb128_op(1 + PTR_SIZE); // extended size
+ dwarf_line_op(DW_LNE_set_address);
+ for (i = 0; i < PTR_SIZE; i++)
+ dwarf_line_op(0);
+ memset(&dwarf_info.base_type_used, 0, sizeof(dwarf_info.base_type_used));
+ }
+ else {
+ /* file info: full path + filename */
+ section_sym = put_elf_sym(symtab_section, 0, 0,
+ ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
+ text_section->sh_num, NULL);
+ put_stabs_r(s1, buf, N_SO, 0, 0,
+ text_section->data_offset, text_section, section_sym);
+ put_stabs_r(s1, filename, N_SO, 0, 0,
+ text_section->data_offset, text_section, section_sym);
+ for (i = 0; i < N_DEFAULT_DEBUG; i++)
+ put_stabs(s1, default_debug[i].name, N_LSYM, 0, 0, 0);
+ }
new_file = last_line_num = 0;
func_ind = -1;
- debug_next_type = sizeof(default_debug) / sizeof(default_debug[0]);
+ debug_next_type = N_DEFAULT_DEBUG;
debug_hash = NULL;
n_debug_hash = 0;
-
/* we're currently 'including' the */
tcc_debug_bincl(s1);
}
@@ -450,8 +962,111 @@ ST_FUNC void tcc_debug_end(TCCState *s1)
{
if (!s1->do_debug)
return;
- put_stabs_r(s1, NULL, N_SO, 0, 0,
- text_section->data_offset, text_section, section_sym);
+ if (s1->dwarf) {
+ int i;
+ int start_aranges;
+ unsigned char *ptr;
+ int text_size = text_section->data_offset;
+
+ /* dwarf_info */
+ dwarf_data1(dwarf_info_section, 0);
+ ptr = dwarf_info_section->data + dwarf_info.start;
+ write32le(ptr, dwarf_info_section->data_offset - dwarf_info.start - 4);
+ write32le(ptr + 25 + (s1->dwarf >= 5) + PTR_SIZE, text_size);
+
+ /* dwarf_aranges */
+ start_aranges = dwarf_aranges_section->data_offset;
+ dwarf_data4(dwarf_aranges_section, 0); // size
+ dwarf_data2(dwarf_aranges_section, 2); // version
+ dwarf_reloc(dwarf_aranges_section, dwarf_sym.info, R_DATA_32U);
+ dwarf_data4(dwarf_aranges_section, 0); // dwarf_info
+#if PTR_SIZE == 4
+ dwarf_data1(dwarf_aranges_section, 4); // address size
+#else
+ dwarf_data1(dwarf_aranges_section, 8); // address size
+#endif
+ dwarf_data1(dwarf_aranges_section, 0); // segment selector size
+ dwarf_data4(dwarf_aranges_section, 0); // padding
+ dwarf_reloc(dwarf_aranges_section, section_sym, R_DATA_PTR);
+#if PTR_SIZE == 4
+ dwarf_data4(dwarf_aranges_section, 0); // Begin
+ dwarf_data4(dwarf_aranges_section, text_size); // End
+ dwarf_data4(dwarf_aranges_section, 0); // End list
+ dwarf_data4(dwarf_aranges_section, 0); // End list
+#else
+ dwarf_data8(dwarf_aranges_section, 0); // Begin
+ dwarf_data8(dwarf_aranges_section, text_size); // End
+ dwarf_data8(dwarf_aranges_section, 0); // End list
+ dwarf_data8(dwarf_aranges_section, 0); // End list
+#endif
+ ptr = dwarf_aranges_section->data + start_aranges;
+ write32le(ptr, dwarf_aranges_section->data_offset - start_aranges - 4);
+
+ /* dwarf_line */
+ if (s1->dwarf >= 5) {
+ dwarf_data1(dwarf_line_section, 1); /* col */
+ dwarf_uleb128(dwarf_line_section, DW_LNCT_path);
+ dwarf_uleb128(dwarf_line_section, DW_FORM_line_strp);
+ dwarf_uleb128(dwarf_line_section, dwarf_line.dir_size);
+ for (i = 0; i < dwarf_line.dir_size; i++)
+ dwarf_line_strp(dwarf_line_section, dwarf_line.dir_table[i]);
+ dwarf_data1(dwarf_line_section, 2); /* col */
+ dwarf_uleb128(dwarf_line_section, DW_LNCT_path);
+ dwarf_uleb128(dwarf_line_section, DW_FORM_line_strp);
+ dwarf_uleb128(dwarf_line_section, DW_LNCT_directory_index);
+ dwarf_uleb128(dwarf_line_section, DW_FORM_udata);
+ dwarf_uleb128(dwarf_line_section, dwarf_line.filename_size);
+ for (i = 0; i < dwarf_line.filename_size; i++) {
+ dwarf_line_strp(dwarf_line_section,
+ dwarf_line.filename_table[i].name);
+ dwarf_uleb128(dwarf_line_section,
+ dwarf_line.filename_table[i].dir_entry);
+ }
+ }
+ else {
+ int len;
+
+ for (i = 0; i < dwarf_line.dir_size; i++) {
+ len = strlen(dwarf_line.dir_table[i]) + 1;
+ ptr = section_ptr_add(dwarf_line_section, len);
+ memmove(ptr, dwarf_line.dir_table[i], len);
+ }
+ dwarf_data1(dwarf_line_section, 0); /* end dir */
+ for (i = 0; i < dwarf_line.filename_size; i++) {
+ len = strlen(dwarf_line.filename_table[i].name) + 1;
+ ptr = section_ptr_add(dwarf_line_section, len);
+ memmove(ptr, dwarf_line.filename_table[i].name, len);
+ dwarf_uleb128(dwarf_line_section,
+ dwarf_line.filename_table[i].dir_entry);
+ dwarf_uleb128(dwarf_line_section, 0); /* time */
+ dwarf_uleb128(dwarf_line_section, 0); /* size */
+ }
+ dwarf_data1(dwarf_line_section, 0); /* end file */
+ }
+ for (i = 0; i < dwarf_line.dir_size; i++)
+ tcc_free(dwarf_line.dir_table[i]);
+ tcc_free(dwarf_line.dir_table);
+ for (i = 0; i < dwarf_line.filename_size; i++)
+ tcc_free(dwarf_line.filename_table[i].name);
+ tcc_free(dwarf_line.filename_table);
+
+ dwarf_line_op(0); // extended
+ dwarf_uleb128_op(1); // extended size
+ dwarf_line_op(DW_LNE_end_sequence);
+ i = (s1->dwarf >= 5) * 2;
+ write32le(&dwarf_line_section->data[dwarf_line.start + 6 + i],
+ dwarf_line_section->data_offset - dwarf_line.start - (10 + i));
+ section_ptr_add(dwarf_line_section, 3);
+ dwarf_reloc(dwarf_line_section, section_sym, R_DATA_PTR);
+ ptr = section_ptr_add(dwarf_line_section, dwarf_line.line_size - 3);
+ memmove(ptr - 3, dwarf_line.line_data, dwarf_line.line_size);
+ tcc_free(dwarf_line.line_data);
+ write32le(dwarf_line_section->data + dwarf_line.start,
+ dwarf_line_section->data_offset - dwarf_line.start - 4);
+ }
+ else
+ put_stabs_r(s1, NULL, N_SO, 0, 0,
+ text_section->data_offset, text_section, section_sym);
tcc_free(debug_hash);
}
@@ -462,8 +1077,10 @@ static BufferedFile* put_new_file(TCCState *s1)
if (f->filename[0] == ':')
f = f->prev;
if (f && new_file) {
- put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym);
+ if (!s1->dwarf)
+ put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym);
new_file = last_line_num = 0;
+ dwarf_file(s1);
}
return f;
}
@@ -475,6 +1092,7 @@ ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename)
return;
pstrcpy(file->filename, sizeof(file->filename), filename);
new_file = 1;
+ dwarf_file(s1);
}
/* begin of #include */
@@ -482,8 +1100,53 @@ ST_FUNC void tcc_debug_bincl(TCCState *s1)
{
if (!s1->do_debug)
return;
- put_stabs(s1, file->filename, N_BINCL, 0, 0, 0);
+ if (s1->dwarf) {
+ int i, j;
+ char *filename = strrchr(file->filename, '/');
+ char *dir;
+
+ if (filename == NULL) {
+ filename = file->filename;
+ i = 0;
+ }
+ else {
+ char *undo = filename;
+
+ *filename++ = '\0';
+ dir = file->filename;
+ for (i = 0; i < dwarf_line.dir_size; i++)
+ if (strcmp (dwarf_line.dir_table[i], dir) == 0)
+ break;
+ if (i == dwarf_line.dir_size) {
+ dwarf_line.dir_size++;
+ dwarf_line.dir_table =
+ (char **) tcc_realloc(dwarf_line.dir_table,
+ dwarf_line.dir_size *
+ sizeof (char *));
+ dwarf_line.dir_table[i] = tcc_strdup(dir);
+ }
+ *undo = '/';
+ }
+ if (strcmp(filename, "")) {
+ for (j = 0; j < dwarf_line.filename_size; j++)
+ if (strcmp (dwarf_line.filename_table[j].name, filename) == 0)
+ break;
+ if (j == dwarf_line.filename_size) {
+ dwarf_line.filename_table =
+ (struct dwarf_filename_struct *)
+ tcc_realloc(dwarf_line.filename_table,
+ (dwarf_line.filename_size + 1) *
+ sizeof (struct dwarf_filename_struct));
+ dwarf_line.filename_table[dwarf_line.filename_size].dir_entry = i;
+ dwarf_line.filename_table[dwarf_line.filename_size++].name =
+ tcc_strdup(filename);
+ }
+ }
+ }
+ else
+ put_stabs(s1, file->filename, N_BINCL, 0, 0, 0);
new_file = 1;
+ dwarf_file(s1);
}
/* end of #include */
@@ -491,30 +1154,73 @@ ST_FUNC void tcc_debug_eincl(TCCState *s1)
{
if (!s1->do_debug)
return;
- put_stabn(s1, N_EINCL, 0, 0, 0);
+ if (!s1->dwarf)
+ put_stabn(s1, N_EINCL, 0, 0, 0);
new_file = 1;
+ dwarf_file(s1);
}
/* generate line number info */
static void tcc_debug_line(TCCState *s1)
{
BufferedFile *f;
+
if (!s1->do_debug
|| cur_text_section != text_section
|| !(f = put_new_file(s1))
|| last_line_num == f->line_num)
return;
- if (func_ind != -1) {
- put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind);
- } else {
- /* from tcc_assemble */
- put_stabs_r(s1, NULL, N_SLINE, 0, f->line_num, ind, text_section, section_sym);
+ if (s1->dwarf) {
+ int len_pc = (ind - dwarf_line.last_pc) / DWARF_MIN_INSTR_LEN;
+ int len_line = f->line_num - dwarf_line.last_line;
+ int n = len_pc * DWARF_LINE_RANGE + len_line + DWARF_OPCODE_BASE - DWARF_LINE_BASE;
+
+ if (dwarf_line.cur_file != dwarf_line.last_file) {
+ dwarf_line.last_file = dwarf_line.cur_file;
+ dwarf_line_op(DW_LNS_set_file);
+ dwarf_uleb128_op(dwarf_line.cur_file);
+ }
+ if (len_pc &&
+ len_line >= DWARF_LINE_BASE && len_line <= (DWARF_OPCODE_BASE + DWARF_LINE_BASE) &&
+ n >= DWARF_OPCODE_BASE && n <= 255)
+ dwarf_line_op(n);
+ else {
+ if (len_pc) {
+ n = len_pc * DWARF_LINE_RANGE + 0 + DWARF_OPCODE_BASE - DWARF_LINE_BASE;
+ if (n >= DWARF_OPCODE_BASE && n <= 255)
+ dwarf_line_op(n);
+ else {
+ dwarf_line_op(DW_LNS_advance_pc);
+ dwarf_uleb128_op(len_pc);
+ }
+ }
+ if (len_line) {
+ n = 0 * DWARF_LINE_RANGE + len_line + DWARF_OPCODE_BASE - DWARF_LINE_BASE;
+ if (len_line >= DWARF_LINE_BASE && len_line <= (DWARF_OPCODE_BASE + DWARF_LINE_BASE) &&
+ n >= DWARF_OPCODE_BASE && n <= 255)
+ dwarf_line_op(n);
+ else {
+ dwarf_line_op(DW_LNS_advance_line);
+ dwarf_sleb128_op(len_line);
+ }
+ }
+ }
+ dwarf_line.last_pc = ind;
+ dwarf_line.last_line = f->line_num;
+ }
+ else {
+ if (func_ind != -1) {
+ put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind);
+ } else {
+ /* from tcc_assemble */
+ put_stabs_r(s1, NULL, N_SLINE, 0, f->line_num, ind, text_section, section_sym);
+ }
+ last_line_num = f->line_num;
}
- last_line_num = f->line_num;
}
static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned long value,
- Section *sec, int sym_index)
+ Section *sec, int sym_index, int info)
{
struct debug_sym *s;
@@ -529,6 +1235,9 @@ static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned l
s->str = tcc_strdup(str);
s->sec = sec;
s->sym_index = sym_index;
+ s->info = info;
+ s->file = dwarf_line.cur_file;
+ s->line = file->line_num;
}
else if (sec)
put_stabs_r (s1, str, type, 0, 0, value, sec, sym_index);
@@ -567,6 +1276,40 @@ static void tcc_debug_stabn(TCCState *s1, int type, int value)
}
}
+static int tcc_debug_find(Sym *t)
+{
+ int i;
+
+ for (i = 0; i < n_debug_hash; i++)
+ if (t == debug_hash[i].type)
+ return debug_hash[i].debug_type;
+ return -1;
+}
+
+static int tcc_debug_add(Sym *t, int dwarf)
+{
+ int offset = dwarf ? dwarf_info_section->data_offset : ++debug_next_type;
+
+ debug_hash = (struct debug_hash *)
+ tcc_realloc (debug_hash,
+ (n_debug_hash + 1) * sizeof(*debug_hash));
+ debug_hash[n_debug_hash].debug_type = offset;
+ debug_hash[n_debug_hash++].type = t;
+ return offset;
+}
+
+static void tcc_debug_remove(Sym *t)
+{
+ int i;
+
+ for (i = 0; i < n_debug_hash; i++)
+ if (t == debug_hash[i].type) {
+ n_debug_hash--;
+ for (; i < n_debug_hash; i++)
+ debug_hash[i] = debug_hash[i+1];
+ }
+}
+
static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
{
int type;
@@ -585,22 +1328,12 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
break;
}
if ((type & VT_BTYPE) == VT_STRUCT) {
- int i;
+ Sym *e = t;
t = t->type.ref;
- for (i = 0; i < n_debug_hash; i++) {
- if (t == debug_hash[i].type) {
- debug_type = debug_hash[i].debug_type;
- break;
- }
- }
+ debug_type = tcc_debug_find(t);
if (debug_type == -1) {
- debug_type = ++debug_next_type;
- debug_hash = (struct debug_hash *)
- tcc_realloc (debug_hash,
- (n_debug_hash + 1) * sizeof(*debug_hash));
- debug_hash[n_debug_hash].debug_type = debug_type;
- debug_hash[n_debug_hash++].type = t;
+ debug_type = tcc_debug_add(t, 0);
cstr_new (&str);
cstr_printf (&str, "%s:T%d=%c%d",
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
@@ -627,39 +1360,44 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
cstr_printf (&str, ",%d,%d;", pos, size);
}
cstr_printf (&str, ";");
- tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0);
+ tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
cstr_free (&str);
+ if (debug_info)
+ tcc_debug_remove(e);
}
}
else if (IS_ENUM(type)) {
Sym *e = t = t->type.ref;
- debug_type = ++debug_next_type;
- cstr_new (&str);
- cstr_printf (&str, "%s:T%d=e",
- (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL),
- debug_type);
- while (t->next) {
- t = t->next;
- cstr_printf (&str, "%s:",
- (t->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_FIELD, NULL));
- cstr_printf (&str, e->type.t & VT_UNSIGNED ? "%u," : "%d,",
- (int)t->enum_val);
- }
- cstr_printf (&str, ";");
- tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0);
- cstr_free (&str);
+ debug_type = tcc_debug_find(t);
+ if (debug_type == -1) {
+ debug_type = tcc_debug_add(t, 0);
+ cstr_new (&str);
+ cstr_printf (&str, "%s:T%d=e",
+ (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL),
+ debug_type);
+ while (t->next) {
+ t = t->next;
+ cstr_printf (&str, "%s:",
+ (t->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(t->v & ~SYM_FIELD, NULL));
+ cstr_printf (&str, e->type.t & VT_UNSIGNED ? "%u," : "%d,",
+ (int)t->enum_val);
+ }
+ cstr_printf (&str, ";");
+ tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
+ cstr_free (&str);
+ if (debug_info)
+ tcc_debug_remove(e);
+ }
}
else if ((type & VT_BTYPE) != VT_FUNC) {
type &= ~VT_STRUCT_MASK;
- for (debug_type = 1;
- debug_type <= sizeof(default_debug) / sizeof(default_debug[0]);
- debug_type++)
+ for (debug_type = 1; debug_type <= N_DEFAULT_DEBUG; debug_type++)
if (default_debug[debug_type - 1].type == type)
break;
- if (debug_type > sizeof(default_debug) / sizeof(default_debug[0]))
+ if (debug_type > N_DEFAULT_DEBUG)
return;
}
if (n > 0)
@@ -686,8 +1424,263 @@ static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
cstr_printf (result, "%d", debug_type);
}
+static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
+{
+ int type;
+ int debug_type = -1;
+ Sym *e, *t = s;
+ int i;
+
+ for (;;) {
+ type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE);
+ if ((type & VT_BTYPE) != VT_BYTE)
+ type &= ~VT_DEFSIGN;
+ if (type == VT_PTR || type == (VT_PTR | VT_ARRAY))
+ t = t->type.ref;
+ else
+ break;
+ }
+ if ((type & VT_BTYPE) == VT_STRUCT) {
+ t = t->type.ref;
+ debug_type = tcc_debug_find(t);
+ if (debug_type == -1) {
+ int pos_sib, i, *pos_type;
+
+ debug_type = tcc_debug_add(t, 1);
+ e = t;
+ i = 0;
+ while (e->next) {
+ e = e->next;
+ i++;
+ }
+ pos_type = (int *) tcc_malloc(i * sizeof(int));
+ dwarf_data1(dwarf_info_section,
+ IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_TYPE
+ : DWARF_ABBREV_STRUCTURE_TYPE);
+ dwarf_strp(dwarf_info_section,
+ (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
+ dwarf_uleb128(dwarf_info_section, t->c);
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, file->line_num);
+ pos_sib = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0);
+ e = t;
+ i = 0;
+ while (e->next) {
+ e = e->next;
+ if (e->type.t & VT_BITFIELD) {
+ int pos = e->c * 8 + BIT_POS(e->type.t);
+ int size = BIT_SIZE(e->type.t);
+
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_MEMBER_BF);
+ dwarf_strp(dwarf_info_section,
+ (e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, file->line_num);
+ pos_type[i++] = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0);
+ dwarf_uleb128(dwarf_info_section, size);
+ dwarf_uleb128(dwarf_info_section, pos);
+ }
+ else {
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_MEMBER);
+ dwarf_strp(dwarf_info_section,
+ (e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, file->line_num);
+ pos_type[i++] = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0);
+ dwarf_uleb128(dwarf_info_section, e->c);
+ }
+ }
+ dwarf_data1(dwarf_info_section, 0);
+ write32le(dwarf_info_section->data + pos_sib,
+ dwarf_info_section->data_offset - dwarf_info.start);
+ e = t;
+ i = 0;
+ while (e->next) {
+ e = e->next;
+ type = tcc_get_dwarf_info(s1, e);
+ write32le(dwarf_info_section->data + pos_type[i++],
+ type - dwarf_info.start);
+ }
+ tcc_free(pos_type);
+ if (debug_info)
+ tcc_debug_remove(t);
+ }
+ }
+ else if (IS_ENUM(type)) {
+ t = t->type.ref;
+ debug_type = tcc_debug_find(t);
+ if (debug_type == -1) {
+ int pos_sib, pos_type;
+ CType ct = { VT_INT | (type & VT_UNSIGNED) , NULL };
+ Sym sym = { .type = ct };
+
+ pos_type = tcc_get_dwarf_info(s1, &sym);
+ debug_type = tcc_debug_add(t, 1);
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_ENUMERATION_TYPE);
+ dwarf_strp(dwarf_info_section,
+ (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
+ dwarf_data1(dwarf_info_section,
+ type & VT_UNSIGNED ? DW_ATE_unsigned : DW_ATE_signed );
+ dwarf_data1(dwarf_info_section, 4);
+ dwarf_data4(dwarf_info_section, pos_type - dwarf_info.start);
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, file->line_num);
+ pos_sib = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0);
+ e = t;
+ while (e->next) {
+ e = e->next;
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_ENUMERATOR);
+ dwarf_strp(dwarf_info_section,
+ (e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
+ ? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
+ dwarf_data4(dwarf_info_section, e->enum_val);
+ }
+ dwarf_data1(dwarf_info_section, 0);
+ write32le(dwarf_info_section->data + pos_sib,
+ dwarf_info_section->data_offset - dwarf_info.start);
+ if (debug_info)
+ tcc_debug_remove(t);
+ }
+ }
+ else if ((type & VT_BTYPE) != VT_FUNC) {
+ type &= ~VT_STRUCT_MASK;
+ for (i = 1; i <= N_DEFAULT_DEBUG; i++)
+ if (default_debug[i - 1].type == type)
+ break;
+ if (i > N_DEFAULT_DEBUG)
+ return 0;
+ debug_type = dwarf_info.base_type_used[i - 1];
+ if (debug_type == 0) {
+ char name[100];
+
+ debug_type = dwarf_info_section->data_offset;
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_BASE_TYPE);
+ dwarf_uleb128(dwarf_info_section, default_debug[i - 1].size);
+ dwarf_data1(dwarf_info_section, default_debug[i - 1].encoding);
+ strncpy(name, default_debug[i - 1].name, sizeof(name) -1);
+ *strchr(name, ':') = 0;
+ dwarf_strp(dwarf_info_section, name);
+ dwarf_info.base_type_used[i - 1] = debug_type;
+ }
+ }
+ t = s;
+ for (;;) {
+ type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE);
+ if ((type & VT_BTYPE) != VT_BYTE)
+ type &= ~VT_DEFSIGN;
+ if (type == VT_PTR) {
+ i = dwarf_info_section->data_offset;
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_POINTER);
+ dwarf_data1(dwarf_info_section, PTR_SIZE);
+ dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start);
+ debug_type = i;
+ }
+ else if (type == (VT_PTR | VT_ARRAY)) {
+ int sib_pos, sub_type;
+ CType ct = { VT_INT | VT_UNSIGNED , NULL };
+ Sym sym = { .type = ct };
+
+ sub_type = tcc_get_dwarf_info(s1, &sym);
+ i = dwarf_info_section->data_offset;
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_ARRAY_TYPE);
+ dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start);
+ sib_pos = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0);
+ for (;;) {
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_SUBRANGE_TYPE);
+ dwarf_data4(dwarf_info_section, sub_type - dwarf_info.start);
+ dwarf_uleb128(dwarf_info_section, t->type.ref->c - 1);
+ s = t->type.ref;
+ type = s->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE);
+ if (type != (VT_PTR | VT_ARRAY))
+ break;
+ t = s;
+ }
+ dwarf_data1(dwarf_info_section, 0);
+ write32le(dwarf_info_section->data + sib_pos,
+ dwarf_info_section->data_offset - dwarf_info.start);
+ debug_type = i;
+ }
+ else if (type == VT_FUNC) {
+ return tcc_get_dwarf_info (s1, t->type.ref);
+ }
+ else
+ break;
+ t = t->type.ref;
+ }
+ return debug_type;
+}
+
static void tcc_debug_finish (TCCState *s1, struct debug_info *cur)
{
+ if (s1->dwarf) {
+ while (cur) {
+ int i;
+ struct debug_info *next = cur->next;
+
+ for (i = cur->n_sym - 1; i >= 0; i--) {
+ struct debug_sym *s = &cur->sym[i];
+
+ dwarf_data1(dwarf_info_section,
+ s->type == N_PSYM
+ ? DWARF_ABBREV_FORMAL_PARAMETER
+ : s->type == N_GSYM
+ ? DWARF_ABBREV_VARIABLE_EXTERNAL
+ : s->type == N_STSYM
+ ? DWARF_ABBREV_VARIABLE_STATIC
+ : DWARF_ABBREV_VARIABLE_LOCAL);
+ dwarf_strp(dwarf_info_section, s->str);
+ if (s->type == N_GSYM || s->type == N_STSYM) {
+ dwarf_uleb128(dwarf_info_section, s->file);
+ dwarf_uleb128(dwarf_info_section, s->line);
+ }
+ dwarf_data4(dwarf_info_section, s->info - dwarf_info.start);
+ if (s->type == N_GSYM || s->type == N_STSYM) {
+ /* global/static */
+ if (s->type == N_GSYM)
+ dwarf_data1(dwarf_info_section, 1);
+ dwarf_data1(dwarf_info_section, PTR_SIZE + 1);
+ dwarf_data1(dwarf_info_section, DW_OP_addr);
+ if (s->type == N_STSYM)
+ dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
+#if PTR_SIZE == 4
+ dwarf_data4(dwarf_info_section, s->value);
+#else
+ dwarf_data8(dwarf_info_section, s->value);
+#endif
+ }
+ else {
+ /* param/local */
+ dwarf_data1(dwarf_info_section, dwarf_sleb128_size(s->value) + 1);
+ dwarf_data1(dwarf_info_section, DW_OP_fbreg);
+ dwarf_sleb128(dwarf_info_section, s->value);
+ }
+ tcc_free (s->str);
+ }
+ tcc_free (cur->sym);
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_LEXICAL_BLOCK);
+ dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
+#if PTR_SIZE == 4
+ dwarf_data4(dwarf_info_section, func_ind + cur->start);
+ dwarf_data4(dwarf_info_section, cur->end - cur->start);
+#else
+ dwarf_data8(dwarf_info_section, func_ind + cur->start);
+ dwarf_data8(dwarf_info_section, cur->end - cur->start);
+#endif
+ tcc_debug_finish (s1, cur->child);
+ dwarf_data1(dwarf_info_section, 0);
+ tcc_free (cur);
+ cur = next;
+ }
+ }
while (cur) {
int i;
struct debug_info *next = cur->next;
@@ -720,10 +1713,19 @@ static void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e)
for (; s != e; s = s->prev) {
if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
continue;
- cstr_reset (&debug_str);
- cstr_printf (&debug_str, "%s:%s", get_tok_str(s->v, NULL), param ? "p" : "");
- tcc_get_debug_info(s1, s, &debug_str);
- tcc_debug_stabs(s1, debug_str.data, param ? N_PSYM : N_LSYM, s->c, NULL, 0);
+ if (s1->dwarf) {
+ tcc_debug_stabs(s1, get_tok_str(s->v, NULL),
+ param ? N_PSYM : N_LSYM, s->c, NULL, 0,
+ tcc_get_dwarf_info(s1, s));
+ }
+ else {
+ cstr_reset (&debug_str);
+ cstr_printf (&debug_str, "%s:%s", get_tok_str(s->v, NULL),
+ param ? "p" : "");
+ tcc_get_debug_info(s1, s, &debug_str);
+ tcc_debug_stabs(s1, debug_str.data, param ? N_PSYM : N_LSYM,
+ s->c, NULL, 0, 0);
+ }
}
cstr_free (&debug_str);
}
@@ -739,23 +1741,83 @@ static void tcc_debug_funcstart(TCCState *s1, Sym *sym)
debug_info = NULL;
tcc_debug_stabn(s1, N_LBRAC, ind - func_ind);
if (!(f = put_new_file(s1)))
- return;
- cstr_new (&debug_str);
- cstr_printf(&debug_str, "%s:%c", funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
- tcc_get_debug_info(s1, sym->type.ref, &debug_str);
- put_stabs_r(s1, debug_str.data, N_FUN, 0, f->line_num, 0, cur_text_section, sym->c);
- cstr_free (&debug_str);
-
+ return;
tcc_debug_line(s1);
+ if (s1->dwarf) {
+ dwarf_info.func = sym;
+ dwarf_info.line = file->line_num;
+ if (s1->do_backtrace) {
+ int i;
+
+ dwarf_line_op(0); // extended
+ dwarf_uleb128_op(strlen(funcname) + 2);
+ dwarf_line_op(DW_LNE_hi_user - 1);
+ for (i = 0; i < strlen(funcname) + 1; i++)
+ dwarf_line_op(funcname[i]);
+ }
+ }
+ else {
+ cstr_new (&debug_str);
+ cstr_printf(&debug_str, "%s:%c", funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
+ tcc_get_debug_info(s1, sym->type.ref, &debug_str);
+ put_stabs_r(s1, debug_str.data, N_FUN, 0, f->line_num, 0, cur_text_section, sym->c);
+ cstr_free (&debug_str);
+ }
}
/* put function size */
static void tcc_debug_funcend(TCCState *s1, int size)
{
+ int func_sib = 0;
+
if (!s1->do_debug)
return;
+ tcc_debug_line(s1);
tcc_debug_stabn(s1, N_RBRAC, size);
+ if (s1->dwarf) {
+ Sym *sym = dwarf_info.func;
+ int debug_info = tcc_get_dwarf_info(s1, sym->type.ref);
+
+ dwarf_data1(dwarf_info_section,
+ sym->type.t & VT_STATIC ? DWARF_ABBREV_SUBPROGRAM_STATIC
+ : DWARF_ABBREV_SUBPROGRAM_EXTERNAL);
+ if ((sym->type.t & VT_STATIC) == 0)
+ dwarf_data1(dwarf_info_section, 1);
+ dwarf_strp(dwarf_info_section, funcname);
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, dwarf_info.line);
+ dwarf_data4(dwarf_info_section, debug_info - dwarf_info.start);
+ dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
+#if PTR_SIZE == 4
+ dwarf_data4(dwarf_info_section, func_ind); // low_pc
+ dwarf_data4(dwarf_info_section, size); // high_pc
+#else
+ dwarf_data8(dwarf_info_section, func_ind); // low_pc
+ dwarf_data8(dwarf_info_section, size); // high_pc
+#endif
+ func_sib = dwarf_info_section->data_offset;
+ dwarf_data4(dwarf_info_section, 0); // sibling
+ dwarf_data1(dwarf_info_section, 1);
+#if defined(TCC_TARGET_I386)
+ dwarf_data1(dwarf_info_section, DW_OP_reg5); // ebp
+#elif defined(TCC_TARGET_X86_64)
+ dwarf_data1(dwarf_info_section, DW_OP_reg6); // rbp
+#elif defined TCC_TARGET_ARM
+ dwarf_data1(dwarf_info_section, DW_OP_reg13); // sp
+#elif defined TCC_TARGET_ARM64
+ dwarf_data1(dwarf_info_section, DW_OP_reg29); // reg 29
+#elif defined TCC_TARGET_RISCV64
+ dwarf_data1(dwarf_info_section, DW_OP_reg8); // r8(s0)
+#else
+ dwarf_data1(dwarf_info_section, DW_OP_call_frame_cfa);
+#endif
+ }
tcc_debug_finish (s1, debug_info_root);
+ if (s1->dwarf) {
+ dwarf_data1(dwarf_info_section, 0);
+ write32le(dwarf_info_section->data + func_sib,
+ dwarf_info_section->data_offset - dwarf_info.start);
+ }
}
@@ -769,19 +1831,44 @@ static void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bin
if (sym_type == STT_FUNC || sym->v >= SYM_FIRST_ANOM)
return;
s = s1->sections[sh_num];
+ if (s1->dwarf) {
+ int debug_type;
+
+ debug_type = tcc_get_dwarf_info(s1, sym);
+ dwarf_data1(dwarf_info_section,
+ sym_bind == STB_GLOBAL
+ ? DWARF_ABBREV_VARIABLE_EXTERNAL
+ : DWARF_ABBREV_VARIABLE_STATIC);
+ dwarf_strp(dwarf_info_section, get_tok_str(sym->v, NULL));
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, file->line_num);
+ dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start);
+ if (sym_bind == STB_GLOBAL)
+ dwarf_data1(dwarf_info_section, 1);
+ dwarf_data1(dwarf_info_section, PTR_SIZE + 1);
+ dwarf_data1(dwarf_info_section, DW_OP_addr);
+ greloca(dwarf_info_section, sym, dwarf_info_section->data_offset,
+ R_DATA_PTR, 0);
+#if PTR_SIZE == 4
+ dwarf_data4(dwarf_info_section, 0);
+#else
+ dwarf_data8(dwarf_info_section, 0);
+#endif
+ return;
+ }
cstr_new (&str);
cstr_printf (&str, "%s:%c",
- get_tok_str(sym->v, NULL),
- sym_bind == STB_GLOBAL ? 'G' : local_scope ? 'V' : 'S'
- );
+ get_tok_str(sym->v, NULL),
+ sym_bind == STB_GLOBAL ? 'G' : local_scope ? 'V' : 'S'
+ );
tcc_get_debug_info(s1, sym, &str);
if (sym_bind == STB_GLOBAL)
- tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0);
+ tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0, 0);
else
tcc_debug_stabs(s1, str.data,
(sym->type.t & VT_STATIC) && data_section == s
- ? N_STSYM : N_LCSYM, 0, s, sym->c);
+ ? N_STSYM : N_LCSYM, 0, s, sym->c, 0);
cstr_free (&str);
}
@@ -791,12 +1878,25 @@ static void tcc_debug_typedef(TCCState *s1, Sym *sym)
if (!s1->do_debug)
return;
+ if (s1->dwarf) {
+ int debug_type;
+
+ debug_type = tcc_get_dwarf_info(s1, sym);
+ if (debug_type != -1) {
+ dwarf_data1(dwarf_info_section, DWARF_ABBREV_TYPEDEF);
+ dwarf_strp(dwarf_info_section, get_tok_str(sym->v & ~SYM_FIELD, NULL));
+ dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
+ dwarf_uleb128(dwarf_info_section, file->line_num);
+ dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start);
+ }
+ return;
+ }
cstr_new (&str);
cstr_printf (&str, "%s:t",
(sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
? "" : get_tok_str(sym->v & ~SYM_FIELD, NULL));
tcc_get_debug_info(s1, sym, &str);
- tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0);
+ tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
cstr_free (&str);
}
@@ -973,7 +2073,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
const_wanted = 0;
nocode_wanted = 0x80000000;
local_scope = 0;
- debug_modes = s1->do_debug | s1->test_coverage << 1;
+ debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1;
tcc_debug_start(s1);
tcc_tcov_start ();
diff --git a/tccrun.c b/tccrun.c
index 9c9f4e07..d79da200 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -27,8 +27,16 @@
typedef struct rt_context
{
/* --> tccelf.c:tcc_add_btstub wants those below in that order: */
- Stab_Sym *stab_sym, *stab_sym_end;
- char *stab_str;
+ union {
+ struct {
+ Stab_Sym *stab_sym, *stab_sym_end;
+ char *stab_str;
+ };
+ struct {
+ unsigned char *dwarf_line, *dwarf_line_end, *dwarf_line_str;
+ addr_t dwarf_text;
+ };
+ };
ElfW(Sym) *esym_start, *esym_end;
char *elf_str;
addr_t prog_base;
@@ -169,9 +177,18 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
memset(rc, 0, sizeof *rc);
if (s1->do_debug) {
void *p;
- rc->stab_sym = (Stab_Sym *)stab_section->data;
- rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
- rc->stab_str = (char *)stab_section->link->data;
+ if (s1->dwarf) {
+ rc->dwarf_line = dwarf_line_section->data;
+ rc->dwarf_line_end = dwarf_line_section->data + dwarf_line_section->data_offset;
+ rc->dwarf_line_str = dwarf_line_str_section->data;
+ rc->dwarf_text = text_section->sh_addr;
+ }
+ else {
+ rc->stab_sym = (Stab_Sym *)stab_section->data;
+ rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
+ rc->stab_str = (char *)stab_section->link->data;
+ rc->dwarf_text = 0;
+ }
rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
rc->elf_str = (char *)symtab_section->link->data;
@@ -571,6 +588,337 @@ found:
return func_addr;
}
+#define MAX_128 ((8 * sizeof (long long) + 6) / 7)
+
+#define DW_GETC(s,e) ((s) < (e) ? *(s)++ : 0)
+
+#define DIR_TABLE_SIZE (64)
+#define FILE_TABLE_SIZE (256)
+
+static unsigned long long
+dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
+{
+ unsigned char *cp = *ln;
+ unsigned long long retval = 0;
+ int i;
+
+ for (i = 0; i < MAX_128; i++) {
+ unsigned long long byte = DW_GETC(cp, end);
+
+ retval |= (byte & 0x7f) << (i * 7);
+ if ((byte & 0x80) == 0)
+ break;
+ }
+ *ln = cp;
+ return retval;
+}
+
+static long long
+dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
+{
+ unsigned char *cp = *ln;
+ long long retval = 0;
+ int i;
+
+ for (i = 0; i < MAX_128; i++) {
+ unsigned long long byte = DW_GETC(cp, end);
+
+ retval |= (byte & 0x7f) << (i * 7);
+ if ((byte & 0x80) == 0) {
+ if ((byte & 0x40) && (i + 1) * 7 < 64)
+ retval |= -1LL << ((i + 1) * 7);
+ break;
+ }
+ }
+ *ln = cp;
+ return retval;
+}
+
+static unsigned int dwarf_read_32(unsigned char **ln, unsigned char *end)
+{
+ unsigned char *cp = *ln;
+ unsigned int retval = 0;
+
+ if ((cp + 4) < end) {
+ retval = read32le(cp);
+ cp += 4;
+ }
+ *ln = cp;
+ return retval;
+}
+
+#if PTR_SIZE == 8
+static unsigned long long dwarf_read_64(unsigned char **ln, unsigned char *end)
+{
+ unsigned char *cp = *ln;
+ unsigned long long retval = 0;
+
+ if ((cp + 8) < end) {
+ retval = read64le(cp);
+ cp += 8;
+ }
+ *ln = cp;
+ return retval;
+}
+#endif
+
+static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
+ const char *msg, const char *skip)
+{
+ unsigned char *ln;
+ unsigned char *cp;
+ unsigned char *end;
+ unsigned int size;
+ unsigned char version;
+ unsigned int min_insn_length;
+ unsigned int max_ops_per_insn;
+ int line_base;
+ unsigned int line_range;
+ unsigned int opcode_base;
+ unsigned int opindex;
+ unsigned int col;
+ unsigned int i;
+ unsigned int len;
+ unsigned int dir_size;
+#if 0
+ char *dirs[DIR_TABLE_SIZE];
+#endif
+ unsigned int filename_size;
+ struct dwarf_filename_struct {
+ unsigned int dir_entry;
+ char *name;
+ } filename_table[FILE_TABLE_SIZE];
+ addr_t last_pc;
+ addr_t pc;
+ addr_t func_addr;
+ int line;
+ char *filename;
+ char *function;
+ ElfW(Sym) *esym;
+
+next:
+ ln = rc->dwarf_line;
+ while (ln < rc->dwarf_line_end) {
+ dir_size = 0;
+ filename_size = 0;
+ last_pc = 0;
+ pc = 0;
+ func_addr = -1;
+ line = 1;
+ filename = NULL;
+ function = NULL;
+ size = dwarf_read_32(&ln, rc->dwarf_line_end);
+ end = ln + size;
+ version = DW_GETC(ln, end);
+ version += DW_GETC(ln, end) << 8;
+ if (version >= 5)
+ ln += 6; // address size, segment selector, prologue Length
+ else
+ ln += 4; // prologue Length
+ min_insn_length = DW_GETC(ln, end);
+ if (version >= 4)
+ max_ops_per_insn = DW_GETC(ln, end);
+ else
+ max_ops_per_insn = 1;
+ ln++; // Initial value of 'is_stmt'
+ line_base = DW_GETC(ln, end);
+ line_base |= line_base >= 0x80 ? ~0xff : 0;
+ line_range = DW_GETC(ln, end);
+ opcode_base = DW_GETC(ln, end);
+ opindex = 0;
+ ln += 12;
+ if (version >= 5) {
+ col = DW_GETC(ln, end);
+ for (i = 0; i < col * 2; i++)
+ dwarf_read_uleb128(&ln, end);
+ dir_size = dwarf_read_uleb128(&ln, end);
+ for (i = 0; i < dir_size; i++)
+#if 0
+ if (i < DIR_TABLE_SIZE)
+ dirs[i] = (char *)rc->dwarf_line_str + dwarf_read_32(&ln, end);
+ else
+#endif
+ dwarf_read_32(&ln, end);
+ col = DW_GETC(ln, end);
+ for (i = 0; i < col * 2; i++)
+ dwarf_read_uleb128(&ln, end);
+ filename_size = dwarf_read_uleb128(&ln, end);
+ for (i = 0; i < filename_size; i++)
+ if (i < FILE_TABLE_SIZE) {
+ filename_table[i].name = (char *)rc->dwarf_line_str + dwarf_read_32(&ln, end);
+ filename_table[i].dir_entry = dwarf_read_uleb128(&ln, end);
+ }
+ else {
+ dwarf_read_32(&ln, end);
+ dwarf_read_uleb128(&ln, end);
+ }
+ }
+ else {
+ while ((i = DW_GETC(ln, end))) {
+#if 0
+ if (++dir_size < DIR_TABLE_SIZE)
+ dirs[dir_size - 1] = (char *)ln - 1;
+#endif
+ while (DW_GETC(ln, end)) {}
+ }
+ while ((i = DW_GETC(ln, end))) {
+ if (++filename_size < FILE_TABLE_SIZE) {
+ filename_table[filename_size - 1].name = (char *)ln - 1;
+ while (DW_GETC(ln, end)) {}
+ filename_table[filename_size - 1].dir_entry =
+ dwarf_read_uleb128(&ln, end);
+ }
+ else {
+ while (DW_GETC(ln, end)) {}
+ dwarf_read_uleb128(&ln, end);
+ }
+ dwarf_read_uleb128(&ln, end); // time
+ dwarf_read_uleb128(&ln, end); // size
+ }
+ }
+ while (ln < end) {
+ last_pc = pc;
+ switch (DW_GETC(ln, end)) {
+ case 0:
+ len = dwarf_read_uleb128(&ln, end);
+ cp = ln;
+ ln += len;
+ if (len == 0)
+ goto next_line;
+ switch (DW_GETC(cp, end)) {
+ case DW_LNE_end_sequence:
+ goto next_line;
+ case DW_LNE_set_address:
+#if PTR_SIZE == 4
+ dwarf_read_32(&cp, end);
+#else
+ dwarf_read_64(&cp, end);
+#endif
+ pc = rc->dwarf_text;
+ opindex = 0;
+ break;
+ case DW_LNE_define_file: /* deprecated */
+ break;
+ case DW_LNE_set_discriminator:
+ dwarf_read_uleb128(&cp, end);
+ break;
+ case DW_LNE_hi_user - 1:
+ function = (char *)cp;
+ func_addr = pc;
+ break;
+ default:
+ break;
+ }
+ break;
+ case DW_LNS_copy:
+ break;
+ case DW_LNS_advance_pc:
+ if (max_ops_per_insn == 1)
+ pc += dwarf_read_uleb128(&ln, end) * min_insn_length;
+ else {
+ unsigned long long off = dwarf_read_uleb128(&ln, end);
+
+ pc += (opindex + off) / max_ops_per_insn *
+ min_insn_length;
+ opindex = (opindex + off) % max_ops_per_insn;
+ }
+ i = 0;
+ goto check_pc;
+ case DW_LNS_advance_line:
+ line += dwarf_read_sleb128(&ln, end);
+ break;
+ case DW_LNS_set_file:
+ i = dwarf_read_uleb128(&ln, end);
+ if (i < FILE_TABLE_SIZE && i < filename_size)
+ filename = filename_table[i].name;
+ break;
+ case DW_LNS_set_column:
+ dwarf_read_uleb128(&ln, end);
+ break;
+ case DW_LNS_negate_stmt:
+ break;
+ case DW_LNS_set_basic_block:
+ break;
+ case DW_LNS_const_add_pc:
+ if (max_ops_per_insn == 1)
+ pc += ((255 - opcode_base) / line_range) * min_insn_length;
+ else {
+ unsigned int off = (255 - opcode_base) / line_range;
+
+ pc += ((opindex + off) / max_ops_per_insn) *
+ min_insn_length;
+ opindex = (opindex + off) % max_ops_per_insn;
+ }
+ i = 0;
+ goto check_pc;
+ case DW_LNS_fixed_advance_pc:
+ i = DW_GETC(ln, end);
+ i += DW_GETC(ln, end) << 8;
+ pc += i;
+ opindex = 0;
+ i = 0;
+ goto check_pc;
+ case DW_LNS_set_prologue_end:
+ break;
+ case DW_LNS_set_epilogue_begin:
+ break;
+ case DW_LNS_set_isa:
+ dwarf_read_uleb128(&ln, end);
+ break;
+ default:
+ i = ln[-1];
+ if (max_ops_per_insn == 1)
+ pc += ((i - opcode_base) / line_range) * min_insn_length;
+ else {
+ pc += (opindex + (i - opcode_base) / line_range) /
+ max_ops_per_insn * min_insn_length;
+ opindex = (opindex + (i - opcode_base) / line_range) %
+ max_ops_per_insn;
+ }
+ i = (int)((i - opcode_base) % line_range) + line_base;
+check_pc:
+ if (pc >= wanted_pc && wanted_pc >= last_pc)
+ goto found;
+ line += i;
+ break;
+ }
+ }
+next_line:
+ ln = end;
+ }
+
+ filename = NULL;
+ function = NULL;
+ func_addr = -1;
+
+ /* we try symtab symbols (no line number info) */
+ for (esym = rc->esym_start + 1; esym < rc->esym_end; ++esym) {
+ int type = ELFW(ST_TYPE)(esym->st_info);
+ if (type == STT_FUNC || type == STT_GNU_IFUNC) {
+ if (wanted_pc >= esym->st_value &&
+ wanted_pc < esym->st_value + esym->st_size) {
+ function = rc->elf_str + esym->st_name;
+ func_addr = esym->st_value;
+ goto found;
+ }
+ }
+ }
+
+ if ((rc = rc->next))
+ goto next;
+
+found:
+ if (filename) {
+ if (skip[0] && strstr(filename, skip))
+ return (addr_t)-1;
+ rt_printf("%s:%d: ", filename, line);
+ }
+ else
+ rt_printf("0x%08llx : ", (long long)wanted_pc);
+ rt_printf("%s %s", msg, function ? function : "???");
+ return (addr_t)func_addr;
+}
+
static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);
static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
@@ -603,7 +951,10 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
ret = rt_get_caller_pc(&pc, rc, i);
a = "%s";
if (ret != -1) {
- pc = rt_printline(rc, pc, level ? "by" : "at", skip);
+ if ((addr_t)rc->dwarf_text)
+ pc = rt_printline_dwarf(rc, pc, level ? "by" : "at", skip);
+ else
+ pc = rt_printline(rc, pc, level ? "by" : "at", skip);
if (pc == (addr_t)-1)
continue;
a = ": %s";
diff --git a/tests/tests2/126_bound_global.c b/tests/tests2/126_bound_global.c
new file mode 100644
index 00000000..d3a5c3b4
--- /dev/null
+++ b/tests/tests2/126_bound_global.c
@@ -0,0 +1,13 @@
+/* test bound checking code without -run */
+
+int arr[10];
+
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ for (i = 0; i <= sizeof(arr)/sizeof(arr[0]); i++)
+ arr[i] = 0;
+ return 0;
+}
diff --git a/tests/tests2/126_bound_global.expect b/tests/tests2/126_bound_global.expect
new file mode 100644
index 00000000..fcdea900
--- /dev/null
+++ b/tests/tests2/126_bound_global.expect
@@ -0,0 +1,2 @@
+126_bound_global.c:11: at main: BCHECK: ........ is outside of the region
+126_bound_global.c:11: at main: RUNTIME ERROR: invalid memory access
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index a75ea6b6..776c7276 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -58,6 +58,9 @@ ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
SKIP += 114_bound_signal.test # libc problem signal/fork
SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
endif
+ifneq (,$(filter Darwin,$(TARGETOS)))
+ SKIP += 126_bound_global.test # bt-exe.c problem on apple
+endif
# Some tests might need arguments
ARGS =
@@ -100,7 +103,7 @@ GEN-ALWAYS =
108_constructor.test: NORUN = true
112_backtrace.test: FLAGS += -dt -b
-112_backtrace.test 113_btdll.test: FILTER += \
+112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
-e 's;[0-9A-Fa-fx]\{5,\};........;g' \
-e 's;0x[0-9A-Fa-f]\{1,\};0x?;g'
@@ -122,6 +125,8 @@ ifneq ($(CONFIG_bcheck),no)
endif
125_atomic_misc.test: FLAGS += -dt
124_atomic_counter.test: FLAGS += -pthread
+126_bound_global.test: FLAGS += -b
+126_bound_global.test: NORUN = true
# Filter source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
diff --git a/x86_64-gen.c b/x86_64-gen.c
index 6641901f..29871d57 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -701,7 +701,7 @@ static void gen_bounds_epilog(void)
*bounds_ptr = 0;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, lbounds_section->data_offset);
+ func_bound_offset, PTR_SIZE);
/* generate bound local allocation */
if (offset_modified) {
diff --git a/x86_64-link.c b/x86_64-link.c
index 6bffb059..abd6ddb9 100644
--- a/x86_64-link.c
+++ b/x86_64-link.c
@@ -4,6 +4,7 @@
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_X86_64_32S
+#define R_DATA_32U R_X86_64_32
#define R_DATA_PTR R_X86_64_64
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
#define R_GLOB_DAT R_X86_64_GLOB_DAT