/* * TCC - Tiny C Compiler * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "tcc.h" /* stab debug support */ static const struct { int type; int size; int encoding; const char *name;} default_debug[] = { { 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, 4, DW_ATE_signed, "long int:t3=r3;-2147483648;2147483647;" },#else { VT_LLONG | VT_LONG, 8, DW_ATE_signed, "long int:t3=r3;-9223372036854775808;9223372036854775807;" },#endif { VT_INT | VT_UNSIGNED, 4, DW_ATE_unsigned, "unsigned int:t4=r4;0;037777777777;" },#if LONG_SIZE == 4 { 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, 8, DW_ATE_unsigned, "long unsigned int:t5=r5;0;01777777777777777777777;" },#endif { 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, 8, DW_ATE_float, "long double:t16=r1;8;0;" },#else { VT_LDOUBLE, 16, DW_ATE_float, "long double:t16=r1;16;0;" },#endif { -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, 1, DW_ATE_unsigned_char, "unsigned char:t25=r25;0;255;" }, /* boolean type */ { VT_BOOL, 1, DW_ATE_boolean, "bool:t26=r26;0;255;" },#if LONG_SIZE == 4 { VT_VOID, 1, DW_ATE_unsigned_char, "void:t27=27" },#else /* bitfields use these */ { VT_LONG | VT_INT, 8, DW_ATE_signed, "long int:t27=r27;-9223372036854775808;9223372036854775807;" }, { VT_LONG | VT_INT | VT_UNSIGNED, 8, DW_ATE_unsigned, "long unsigned int:t28=r28;0;01777777777777777777777;" }, { VT_VOID, 1, DW_ATE_unsigned_char, "void:t29=29" },#endif}; #define N_DEFAULT_DEBUG (sizeof (default_debug) / sizeof (default_debug[0])) /* 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_SIGNED 11#define DWARF_ABBREV_ENUMERATOR_UNSIGNED 12#define DWARF_ABBREV_ENUMERATION_TYPE 13#define DWARF_ABBREV_MEMBER 14#define DWARF_ABBREV_MEMBER_BF 15#define DWARF_ABBREV_STRUCTURE_TYPE 16#define DWARF_ABBREV_STRUCTURE_EMPTY_TYPE 17#define DWARF_ABBREV_UNION_TYPE 18#define DWARF_ABBREV_UNION_EMPTY_TYPE 19#define DWARF_ABBREV_SUBPROGRAM_EXTERNAL 20#define DWARF_ABBREV_SUBPROGRAM_STATIC 21#define DWARF_ABBREV_LEXICAL_BLOCK 22#define DWARF_ABBREV_LEXICAL_EMPTY_BLOCK 23#define DWARF_ABBREV_SUBROUTINE_TYPE 24#define DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE 25#define DWARF_ABBREV_FORMAL_PARAMETER2 26 /* all entries should have been generated with dwarf_uleb128 except has_children. All values are currently below 128 so this currently works. */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_sec_offset, 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_exprloc, 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_exprloc, 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_exprloc, 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_exprloc, 0, 0, DWARF_ABBREV_POINTER, DW_TAG_pointer_type, 0, DW_AT_byte_size, DW_FORM_data1, 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_SIGNED, DW_TAG_enumerator, 0, DW_AT_name, DW_FORM_strp, DW_AT_const_value, DW_FORM_sdata, 0, 0, DWARF_ABBREV_ENUMERATOR_UNSIGNED, DW_TAG_enumerator, 0, DW_AT_name, DW_FORM_strp, DW_AT_const_value, DW_FORM_udata, 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_STRUCTURE_EMPTY_TYPE, DW_TAG_structure_type, 0, 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, 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_UNION_EMPTY_TYPE, DW_TAG_union_type, 0, 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, 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_exprloc, 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_exprloc, 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, DWARF_ABBREV_LEXICAL_EMPTY_BLOCK, DW_TAG_lexical_block, 0, 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, DWARF_ABBREV_SUBROUTINE_TYPE, DW_TAG_subroutine_type, 1, DW_AT_type, DW_FORM_ref4, DW_AT_sibling, DW_FORM_ref4, 0, 0, DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE, DW_TAG_subroutine_type, 0, DW_AT_type, DW_FORM_ref4, 0, 0, DWARF_ABBREV_FORMAL_PARAMETER2, DW_TAG_formal_parameter, 0, DW_AT_type, DW_FORM_ref4, 0, 0, 0}; static const unsigned char dwarf_line_opcodes[] = { 0 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,1}; /* ------------------------------------------------------------------------- *//* debug state */ #define N_STR_HASH (251) struct dwarf_str_hash { int len; unsigned long data_offset; struct dwarf_str_hash *next;}; struct _tccdbg { int last_line_num, new_file; int section_sym; int debug_next_type; struct _debug_hash { int debug_type; Sym *type; } *debug_hash_global, *debug_hash_local; /* store forward structure/unions types */ struct _debug_forw_hash { Sym *type; int n_debug_type; int *debug_type; } *debug_forw_hash_global, *debug_forw_hash_local; int n_debug_hash_global; int n_debug_hash_local; int n_debug_forw_hash_global; int n_debug_forw_hash_local; struct _debug_info { int start; int end; int last_debug_hash; int last_debug_forw_hash; int n_sym; struct debug_sym { int type; unsigned long value; 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; struct { int info; int abbrev; int line; int str; int line_str; } dwarf_sym; 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; struct { int start; Sym *func; int line; int base_type_used[N_DEFAULT_DEBUG]; } dwarf_info; struct dwarf_str_hash *dwarf_str[N_STR_HASH]; struct dwarf_str_hash *dwarf_line_str[N_STR_HASH]; /* test coverage */ struct { unsigned long offset; unsigned long last_file_name; unsigned long last_func_name; int ind; int line; } tcov_data;}; #define last_line_num s1->dState->last_line_num#define new_file s1->dState->new_file#define section_sym s1->dState->section_sym#define debug_next_type s1->dState->debug_next_type#define debug_hash_global s1->dState->debug_hash_global#define debug_hash_local s1->dState->debug_hash_local#define debug_forw_hash_global s1->dState->debug_forw_hash_global#define debug_forw_hash_local s1->dState->debug_forw_hash_local#define n_debug_hash_global s1->dState->n_debug_hash_global#define n_debug_hash_local s1->dState->n_debug_hash_local#define n_debug_forw_hash_global s1->dState->n_debug_forw_hash_global#define n_debug_forw_hash_local s1->dState->n_debug_forw_hash_local#define debug_info s1->dState->debug_info#define debug_info_root s1->dState->debug_info_root#define dwarf_sym s1->dState->dwarf_sym#define dwarf_line s1->dState->dwarf_line#define dwarf_info s1->dState->dwarf_info#define dwarf_str s1->dState->dwarf_str#define dwarf_line_str s1->dState->dwarf_line_str#define tcov_data s1->dState->tcov_data #define FDE_ENCODING (DW_EH_PE_udata4 | DW_EH_PE_signed | DW_EH_PE_pcrel) /* ------------------------------------------------------------------------- */static int put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value); ST_FUNC void tcc_debug_new(TCCState *s1){ int shf = 0; if (!s1->dState) s1->dState = tcc_mallocz(sizeof *s1->dState); #ifdef CONFIG_TCC_BACKTRACE /* include stab info with standalone backtrace support */ if (s1->do_debug && s1->output_type == TCC_OUTPUT_MEMORY) s1->do_backtrace = 1; if (s1->do_backtrace) shf = SHF_ALLOC; /* have debug data available at runtime */#endif if (s1->dwarf) { int i; /* The sections below are just to make reloctions with R_DATA_32DW work correctly. See tccelf.c */ static const char *const debug[] = { ".debug_macro", ".debug_loc", ".debug_ranges", ".debug_loclists", ".debug_rnglists", ".debug_str_offsets", ".debug_addr" }; s1->dwlo = s1->nb_sections; dwarf_info_section = new_section(s1, ".debug_info", SHT_PROGBITS, shf); dwarf_abbrev_section = new_section(s1, ".debug_abbrev", SHT_PROGBITS, shf); dwarf_line_section = new_section(s1, ".debug_line", SHT_PROGBITS, shf); dwarf_aranges_section = new_section(s1, ".debug_aranges", SHT_PROGBITS, shf); for (i = 0; i < sizeof(debug)/sizeof(debug[0]); i++) new_section(s1, debug[i], SHT_PROGBITS, 0)->sh_addralign = 1; shf |= SHF_MERGE | SHF_STRINGS; dwarf_str_section = new_section(s1, ".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(s1, ".debug_line_str", SHT_PROGBITS, shf); dwarf_line_str_section->sh_entsize = 1; dwarf_line_str_section->sh_addralign = 1; } s1->dwhi = s1->nb_sections; } else { stab_section = new_section(s1, ".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(s1, ".stabstr", SHT_STRTAB, shf); /* put first entry */ put_stabs(s1, "", 0, 0, 0, 0);Lines 1–500 of 2676. Load more
/* * TCC - Tiny C Compiler * * Copyright (c) 2001-2004 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "tcc.h" /* stab debug support */ static const struct { int type; int size; int encoding; const char *name; } default_debug[] = { { 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, 4, DW_ATE_signed, "long int:t3=r3;-2147483648;2147483647;" }, #else { VT_LLONG | VT_LONG, 8, DW_ATE_signed, "long int:t3=r3;-9223372036854775808;9223372036854775807;" }, #endif { VT_INT | VT_UNSIGNED, 4, DW_ATE_unsigned, "unsigned int:t4=r4;0;037777777777;" }, #if LONG_SIZE == 4 { 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, 8, DW_ATE_unsigned, "long unsigned int:t5=r5;0;01777777777777777777777;" }, #endif { 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, 8, DW_ATE_float, "long double:t16=r1;8;0;" }, #else { VT_LDOUBLE, 16, DW_ATE_float, "long double:t16=r1;16;0;" }, #endif { -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, 1, DW_ATE_unsigned_char, "unsigned char:t25=r25;0;255;" }, /* boolean type */ { VT_BOOL, 1, DW_ATE_boolean, "bool:t26=r26;0;255;" }, #if LONG_SIZE == 4 { VT_VOID, 1, DW_ATE_unsigned_char, "void:t27=27" }, #else /* bitfields use these */ { VT_LONG | VT_INT, 8, DW_ATE_signed, "long int:t27=r27;-9223372036854775808;9223372036854775807;" }, { VT_LONG | VT_INT | VT_UNSIGNED, 8, DW_ATE_unsigned, "long unsigned int:t28=r28;0;01777777777777777777777;" }, { VT_VOID, 1, DW_ATE_unsigned_char, "void:t29=29" }, #endif }; #define N_DEFAULT_DEBUG (sizeof (default_debug) / sizeof (default_debug[0])) /* 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_SIGNED 11 #define DWARF_ABBREV_ENUMERATOR_UNSIGNED 12 #define DWARF_ABBREV_ENUMERATION_TYPE 13 #define DWARF_ABBREV_MEMBER 14 #define DWARF_ABBREV_MEMBER_BF 15 #define DWARF_ABBREV_STRUCTURE_TYPE 16 #define DWARF_ABBREV_STRUCTURE_EMPTY_TYPE 17 #define DWARF_ABBREV_UNION_TYPE 18 #define DWARF_ABBREV_UNION_EMPTY_TYPE 19 #define DWARF_ABBREV_SUBPROGRAM_EXTERNAL 20 #define DWARF_ABBREV_SUBPROGRAM_STATIC 21 #define DWARF_ABBREV_LEXICAL_BLOCK 22 #define DWARF_ABBREV_LEXICAL_EMPTY_BLOCK 23 #define DWARF_ABBREV_SUBROUTINE_TYPE 24 #define DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE 25 #define DWARF_ABBREV_FORMAL_PARAMETER2 26 /* all entries should have been generated with dwarf_uleb128 except has_children. All values are currently below 128 so this currently works. */ 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_sec_offset, 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_exprloc, 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_exprloc, 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_exprloc, 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_exprloc, 0, 0, DWARF_ABBREV_POINTER, DW_TAG_pointer_type, 0, DW_AT_byte_size, DW_FORM_data1, 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_SIGNED, DW_TAG_enumerator, 0, DW_AT_name, DW_FORM_strp, DW_AT_const_value, DW_FORM_sdata, 0, 0, DWARF_ABBREV_ENUMERATOR_UNSIGNED, DW_TAG_enumerator, 0, DW_AT_name, DW_FORM_strp, DW_AT_const_value, DW_FORM_udata, 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_STRUCTURE_EMPTY_TYPE, DW_TAG_structure_type, 0, 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, 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_UNION_EMPTY_TYPE, DW_TAG_union_type, 0, 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, 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_exprloc, 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_exprloc, 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, DWARF_ABBREV_LEXICAL_EMPTY_BLOCK, DW_TAG_lexical_block, 0, 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, DWARF_ABBREV_SUBROUTINE_TYPE, DW_TAG_subroutine_type, 1, DW_AT_type, DW_FORM_ref4, DW_AT_sibling, DW_FORM_ref4, 0, 0, DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE, DW_TAG_subroutine_type, 0, DW_AT_type, DW_FORM_ref4, 0, 0, DWARF_ABBREV_FORMAL_PARAMETER2, DW_TAG_formal_parameter, 0, DW_AT_type, DW_FORM_ref4, 0, 0, 0 }; static const unsigned char dwarf_line_opcodes[] = { 0 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,1 }; /* ------------------------------------------------------------------------- */ /* debug state */ #define N_STR_HASH (251) struct dwarf_str_hash { int len; unsigned long data_offset; struct dwarf_str_hash *next; }; struct _tccdbg { int last_line_num, new_file; int section_sym; int debug_next_type; struct _debug_hash { int debug_type; Sym *type; } *debug_hash_global, *debug_hash_local; /* store forward structure/unions types */ struct _debug_forw_hash { Sym *type; int n_debug_type; int *debug_type; } *debug_forw_hash_global, *debug_forw_hash_local; int n_debug_hash_global; int n_debug_hash_local; int n_debug_forw_hash_global; int n_debug_forw_hash_local; struct _debug_info { int start; int end; int last_debug_hash; int last_debug_forw_hash; int n_sym; struct debug_sym { int type; unsigned long value; 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; struct { int info; int abbrev; int line; int str; int line_str; } dwarf_sym; 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; struct { int start; Sym *func; int line; int base_type_used[N_DEFAULT_DEBUG]; } dwarf_info; struct dwarf_str_hash *dwarf_str[N_STR_HASH]; struct dwarf_str_hash *dwarf_line_str[N_STR_HASH]; /* test coverage */ struct { unsigned long offset; unsigned long last_file_name; unsigned long last_func_name; int ind; int line; } tcov_data; }; #define last_line_num s1->dState->last_line_num #define new_file s1->dState->new_file #define section_sym s1->dState->section_sym #define debug_next_type s1->dState->debug_next_type #define debug_hash_global s1->dState->debug_hash_global #define debug_hash_local s1->dState->debug_hash_local #define debug_forw_hash_global s1->dState->debug_forw_hash_global #define debug_forw_hash_local s1->dState->debug_forw_hash_local #define n_debug_hash_global s1->dState->n_debug_hash_global #define n_debug_hash_local s1->dState->n_debug_hash_local #define n_debug_forw_hash_global s1->dState->n_debug_forw_hash_global #define n_debug_forw_hash_local s1->dState->n_debug_forw_hash_local #define debug_info s1->dState->debug_info #define debug_info_root s1->dState->debug_info_root #define dwarf_sym s1->dState->dwarf_sym #define dwarf_line s1->dState->dwarf_line #define dwarf_info s1->dState->dwarf_info #define dwarf_str s1->dState->dwarf_str #define dwarf_line_str s1->dState->dwarf_line_str #define tcov_data s1->dState->tcov_data #define FDE_ENCODING (DW_EH_PE_udata4 | DW_EH_PE_signed | DW_EH_PE_pcrel) /* ------------------------------------------------------------------------- */ static int put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value); ST_FUNC void tcc_debug_new(TCCState *s1) { int shf = 0; if (!s1->dState) s1->dState = tcc_mallocz(sizeof *s1->dState); #ifdef CONFIG_TCC_BACKTRACE /* include stab info with standalone backtrace support */ if (s1->do_debug && s1->output_type == TCC_OUTPUT_MEMORY) s1->do_backtrace = 1; if (s1->do_backtrace) shf = SHF_ALLOC; /* have debug data available at runtime */ #endif if (s1->dwarf) { int i; /* The sections below are just to make reloctions with R_DATA_32DW work correctly. See tccelf.c */ static const char *const debug[] = { ".debug_macro", ".debug_loc", ".debug_ranges", ".debug_loclists", ".debug_rnglists", ".debug_str_offsets", ".debug_addr" }; s1->dwlo = s1->nb_sections; dwarf_info_section = new_section(s1, ".debug_info", SHT_PROGBITS, shf); dwarf_abbrev_section = new_section(s1, ".debug_abbrev", SHT_PROGBITS, shf); dwarf_line_section = new_section(s1, ".debug_line", SHT_PROGBITS, shf); dwarf_aranges_section = new_section(s1, ".debug_aranges", SHT_PROGBITS, shf); for (i = 0; i < sizeof(debug)/sizeof(debug[0]); i++) new_section(s1, debug[i], SHT_PROGBITS, 0)->sh_addralign = 1; shf |= SHF_MERGE | SHF_STRINGS; dwarf_str_section = new_section(s1, ".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(s1, ".debug_line_str", SHT_PROGBITS, shf); dwarf_line_str_section->sh_entsize = 1; dwarf_line_str_section->sh_addralign = 1; } s1->dwhi = s1->nb_sections; } else { stab_section = new_section(s1, ".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(s1, ".stabstr", SHT_STRTAB, shf); /* put first entry */ put_stabs(s1, "", 0, 0, 0, 0);