From f08ef63153b345dc1ae2505738f6406288a7a3db Mon Sep 17 00:00:00 2001 From: d0p1 Date: Fri, 7 Feb 2025 17:17:17 +0100 Subject: [PATCH] Refactor and remove code (tccdbg, tccmacho, ...) --- .gitignore | 6 +- Changelog | 2 +- Makefile.am | 11 +- compile_flags.txt | 3 + configure.ac | 5 +- dwarf.h | 1046 ------------ lib/Makefile | 105 -- libtcc.h | 116 -- libtcc/Makefile.am | 6 + coff.h => libtcc/coff.h | 5 +- elf.h => libtcc/elf.h | 0 i386-asm.c => libtcc/i386/asm.c | 12 +- i386-asm.h => libtcc/i386/asm.h | 0 i386-gen.c => libtcc/i386/gen.c | 84 - i386-link.c => libtcc/i386/link.c | 30 +- i386-tok.h => libtcc/i386/tok.h | 4 +- libtcc.c => libtcc/libtcc.c | 180 +-- libtcc/libtcc.h | 179 +++ libtcc/object/archive.h | 35 + libtcc/object/coff.h | 69 + libtcc/option.c | 2 + libtcc/option.h | 6 + tcc.h => libtcc/tcc.h | 208 +-- tccasm.c => libtcc/tccasm.c | 4 +- tcccoff.c => libtcc/tcccoff.c | 30 +- libtcc/tcccoff.c_old.c | 951 +++++++++++ tccelf.c => libtcc/tccelf.c | 544 +------ tccgen.c => libtcc/tccgen.c | 546 +------ tccpe.c => libtcc/tccpe.c | 21 +- tccpp.c => libtcc/tccpp.c | 30 +- tcctok.h => libtcc/tcctok.h | 162 +- libtcc/utils/string.h | 47 + {lib => libtcc1}/alloca-bt.S | 0 {lib => libtcc1}/alloca.S | 0 {lib => libtcc1}/armeabi.c | 0 {lib => libtcc1}/armflush.c | 0 {lib => libtcc1}/atomic.S | 0 {lib => libtcc1}/bcheck.c | 0 {lib => libtcc1}/bt-dll.c | 0 {lib => libtcc1}/bt-exe.c | 0 {lib => libtcc1}/bt-log.c | 0 {lib => libtcc1}/builtin.c | 0 {lib => libtcc1}/dsohandle.c | 0 {lib => libtcc1}/lib-arm64.c | 0 {lib => libtcc1}/libtcc1.c | 0 {lib => libtcc1}/runmain.c | 0 {lib => libtcc1}/stdatomic.c | 0 tcclib.h => libtcc1/tcclib.h | 0 {lib => libtcc1}/tcov.c | 0 {lib => libtcc1}/va_list.c | 0 stab.def | 234 --- stab.h | 17 - tcc.c | 339 ---- tcc/Makefile.am | 5 + tcc/tcc.c | 314 ++++ tcc/tcc_new.c | 134 ++ tcctools.c => tcc/tcctools.c | 2 +- tcc/tcctools.h | 10 + tccdbg.c | 2482 ----------------------------- tccmacho.c | 2480 ---------------------------- 60 files changed, 1887 insertions(+), 8579 deletions(-) create mode 100644 compile_flags.txt delete mode 100644 dwarf.h delete mode 100644 lib/Makefile delete mode 100644 libtcc.h create mode 100644 libtcc/Makefile.am rename coff.h => libtcc/coff.h (99%) rename elf.h => libtcc/elf.h (100%) rename i386-asm.c => libtcc/i386/asm.c (99%) rename i386-asm.h => libtcc/i386/asm.h (100%) rename i386-gen.c => libtcc/i386/gen.c (92%) rename i386-link.c => libtcc/i386/link.c (88%) rename i386-tok.h => libtcc/i386/tok.h (99%) rename libtcc.c => libtcc/libtcc.c (90%) create mode 100644 libtcc/libtcc.h create mode 100644 libtcc/object/archive.h create mode 100644 libtcc/object/coff.h create mode 100644 libtcc/option.c create mode 100644 libtcc/option.h rename tcc.h => libtcc/tcc.h (89%) rename tccasm.c => libtcc/tccasm.c (99%) rename tcccoff.c => libtcc/tcccoff.c (81%) create mode 100644 libtcc/tcccoff.c_old.c rename tccelf.c => libtcc/tccelf.c (86%) rename tccgen.c => libtcc/tccgen.c (94%) rename tccpe.c => libtcc/tccpe.c (99%) rename tccpp.c => libtcc/tccpp.c (99%) rename tcctok.h => libtcc/tcctok.h (61%) create mode 100644 libtcc/utils/string.h rename {lib => libtcc1}/alloca-bt.S (100%) rename {lib => libtcc1}/alloca.S (100%) rename {lib => libtcc1}/armeabi.c (100%) rename {lib => libtcc1}/armflush.c (100%) rename {lib => libtcc1}/atomic.S (100%) rename {lib => libtcc1}/bcheck.c (100%) rename {lib => libtcc1}/bt-dll.c (100%) rename {lib => libtcc1}/bt-exe.c (100%) rename {lib => libtcc1}/bt-log.c (100%) rename {lib => libtcc1}/builtin.c (100%) rename {lib => libtcc1}/dsohandle.c (100%) rename {lib => libtcc1}/lib-arm64.c (100%) rename {lib => libtcc1}/libtcc1.c (100%) rename {lib => libtcc1}/runmain.c (100%) rename {lib => libtcc1}/stdatomic.c (100%) rename tcclib.h => libtcc1/tcclib.h (100%) rename {lib => libtcc1}/tcov.c (100%) rename {lib => libtcc1}/va_list.c (100%) delete mode 100644 stab.def delete mode 100644 stab.h delete mode 100644 tcc.c create mode 100644 tcc/Makefile.am create mode 100644 tcc/tcc.c create mode 100644 tcc/tcc_new.c rename tcctools.c => tcc/tcctools.c (99%) create mode 100644 tcc/tcctools.h delete mode 100644 tccdbg.c delete mode 100644 tccmacho.c diff --git a/.gitignore b/.gitignore index 902348ce..2bcddd92 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ .gdb_history a.out tcc_g -tcc +tcc/tcc tcc_c tcc_p *-tcc @@ -76,4 +76,6 @@ stamp-h1 *_old *.cache .deps -build-aux \ No newline at end of file +build-aux +configure +.dirstamp \ No newline at end of file diff --git a/Changelog b/Changelog index 7ccf11da..fae6936a 100644 --- a/Changelog +++ b/Changelog @@ -72,7 +72,7 @@ User interface: - -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III) - -m32/-m64 to re-exec cross compiler (Henry Kroll III) - -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov) -- new LIBTCCAPI tcc_set_options() (grischka) +- new tcc_set_options() (grischka) Platforms: - Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka) diff --git a/Makefile.am b/Makefile.am index bc67671e..d53d090e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,12 +1,3 @@ AM_CFLAGS = - -noinst_LIBRARIES = libtcc.a -libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c tccdbg.c tccasm.c tccelf.c i386-gen.c i386-link.c i386-asm.c -libtcc_a_CPPFLAGS = -I$(top_srcdir) - -bin_PROGRAMS = tcc - -tcc_SOURCES = tcc.c -tcc_LDADD = libtcc.a -tcc_CPPFLAGS = -I$(top_srcdir) +SUBDIRS = libtcc tcc diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 00000000..3f2296c6 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,3 @@ +-I. +-DHAVE_CONFIG_H +-Ilibtcc \ No newline at end of file diff --git a/configure.ac b/configure.ac index 05657655..96555617 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,10 @@ AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign subdir-objects -Werror -Wall]) AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([ + Makefile + libtcc/Makefile + tcc/Makefile]) AC_LANG([C]) AC_PROG_CC diff --git a/dwarf.h b/dwarf.h deleted file mode 100644 index c961bc36..00000000 --- a/dwarf.h +++ /dev/null @@ -1,1046 +0,0 @@ -/* 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/lib/Makefile b/lib/Makefile deleted file mode 100644 index 6524d829..00000000 --- a/lib/Makefile +++ /dev/null @@ -1,105 +0,0 @@ -# -# Tiny C Compiler Makefile for libtcc1.a -# - -TOP = .. -include $(TOP)/Makefile -VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib -T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown) -X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-) -XCFG = $(or $(findstring -win,$T),-unx) -S = $(if $(findstring yes,$(SILENT)),@$(info * $@)) - -TCC = $(TOP)/$(X)tcc$(EXESUF) -XTCC ?= $(TOP)/$(X)tcc$(EXESUF) -XCC = $(XTCC) -XAR = $(XTCC) -ar -XFLAGS-unx = -B$(TOPSRC) -XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include -XFLAGS = $(XFLAGS$(XCFG)) -BFLAGS = -bt - -# in order to use gcc, type: make -libtcc1-usegcc=yes -arm-libtcc1-usegcc ?= no - -# This makes bounds checking 40%..60% faster. -#x86_64-libtcc1-usegcc=yes -#i386-libtcc1-usegcc=yes - -ifeq "$($(T)-libtcc1-usegcc)" "yes" - XCC = $(CC) - XAR = $(AR) - XFLAGS = $(CFLAGS) -fPIC -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable - BFLAGS = $(if $(CONFIG_dwarf),-gdwarf,-gstabs) -endif - -I386_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O) -X86_64_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O) -ARM_O = libtcc1.o armeabi.o alloca.o armflush.o $(COMMON_O) -ARM64_O = lib-arm64.o $(COMMON_O) -RISCV64_O = lib-arm64.o $(COMMON_O) -COMMON_O = stdatomic.o atomic.o builtin.o -WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o -LIN_O = dsohandle.o -OSX_O = - -# backtrace/bcheck/run only for native compiler -Nat = $(if $X,no,) -Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace)) -Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck)) - -$(Nat)COMMON_O += runmain.o tcov.o -$(Cbt)COMMON_O += bt-exe.o bt-log.o -$(Cbt)WIN_O += bt-dll.o -$(Cbc)COMMON_O += bcheck.o - -# not in libtcc1.a -EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o - -OBJ-i386 = $(I386_O) $(LIN_O) -OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O) -OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O) -OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O) -OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O) -OBJ-arm64 = $(ARM64_O) $(LIN_O) -OBJ-arm64-osx = $(ARM64_O) $(OSX_O) -OBJ-arm = $(ARM_O) $(LIN_O) -OBJ-arm-fpa = $(OBJ-arm) -OBJ-arm-fpa-ld = $(OBJ-arm) -OBJ-arm-vfp = $(OBJ-arm) -OBJ-arm-eabi = $(OBJ-arm) -OBJ-arm-eabihf = $(OBJ-arm) -OBJ-arm-wince = $(ARM_O) $(WIN_O) -OBJ-riscv64 = $(RISCV64_O) $(LIN_O) - -OBJ-extra = $(filter $(EXTRA_O),$(OBJ-$T)) -OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) - -ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra)) - -all: $(ALL) - -$(TOP)/$(X)libtcc1.a : $(OBJ-libtcc1) $(TCC) - $S$(XAR) rcs $@ $(OBJ-libtcc1) - -$(X)%.o : %.c $(TCC) - $S$(XCC) -c $< -o $@ $(XFLAGS) - -$(X)%.o : %.S $(TCC) - $S$(XCC) -c $< -o $@ $(XFLAGS) - -$(TOP)/%.o : %.c $(TCC) - $S$(XCC) -c $< -o $@ $(XFLAGS) - -$(TOP)/bcheck.o : XFLAGS += $(BFLAGS) -I$(TOP) -# includes tccrun.c, $(TOP) for config.h (tccrun.c prerequisite via $(TCC)) -$(TOP)/bt-exe.o : XFLAGS += -I$(TOP) - -$(X)crt1w.o : crt1.c -$(X)wincrt1w.o : wincrt1.c - -# don't try to make it -$(TCC) : ; - -clean : - rm -f *.o $(addprefix $(TOP)/,*libtcc1.a $(EXTRA_O)) diff --git a/libtcc.h b/libtcc.h deleted file mode 100644 index 5949c807..00000000 --- a/libtcc.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef LIBTCC_H -#define LIBTCC_H - -#ifndef LIBTCCAPI -# define LIBTCCAPI -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************/ -/* set custom allocator for all allocations (optional), NULL for default. */ -typedef void *TCCReallocFunc(void *ptr, unsigned long size); -LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc); - -/*****************************/ -typedef struct TCCState TCCState; - -/* create a new TCC compilation context */ -LIBTCCAPI TCCState *tcc_new(void); - -/* free a TCC compilation context */ -LIBTCCAPI void tcc_delete(TCCState *s); - -/* set CONFIG_TCCDIR at runtime */ -LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); - -/* set error/warning callback (optional) */ -typedef void TCCErrorFunc(void *opaque, const char *msg); -LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func); - -/* set options as from command line (multiple supported) */ -LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); - -/*****************************/ -/* preprocessor */ - -/* add include path */ -LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname); - -/* add in system include path */ -LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname); - -/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */ -LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value); - -/* undefine preprocess symbol 'sym' */ -LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym); - -/*****************************/ -/* compiling */ - -/* add a file (C file, dll, object, library, ld script). Return -1 if error. */ -LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename); - -/* compile a string containing a C source. Return -1 if error. */ -LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); - -/* Tip: to have more specific errors/warnings from tcc_compile_string(), - you can prefix the string with "#line \"\"\n" */ - -/*****************************/ -/* linking commands */ - -/* set output type. MUST BE CALLED before any compilation */ -LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type); -#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */ -#define TCC_OUTPUT_EXE 2 /* executable file */ -#define TCC_OUTPUT_DLL 4 /* dynamic library */ -#define TCC_OUTPUT_OBJ 3 /* object file */ -#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */ - -/* equivalent to -Lpath option */ -LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname); - -/* the library name is the same as the argument of the '-l' option */ -LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname); - -/* add a symbol to the compiled program */ -LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val); - -/* output an executable, library or object file. DO NOT call - tcc_relocate() before. */ -LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename); - -/* link and run main() function and return its value. DO NOT call - tcc_relocate() before. */ -LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv); - -/* do all relocations (needed before using tcc_get_symbol()) */ -LIBTCCAPI int tcc_relocate(TCCState *s1); - -/* return symbol value or NULL if not found */ -LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); - -/* list all (global) symbols and their values via 'symbol_cb()' */ -LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, - void (*symbol_cb)(void *ctx, const char *name, const void *val)); - -/* experimental/advanced section (see libtcc_test_mt.c for an example) */ - -/* catch runtime exceptions (optionally limit backtraces at top_func), - when using tcc_set_options("-bt") and when not using tcc_run() */ -LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp); -#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp)) - -/* custom error printer for runtime exceptions. Returning 0 stops backtrace */ -typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg); -LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libtcc/Makefile.am b/libtcc/Makefile.am new file mode 100644 index 00000000..8f07c714 --- /dev/null +++ b/libtcc/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = libtcc.a +libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c \ + tccasm.c tccelf.c \ + i386/gen.c i386/link.c \ + i386/asm.c tcccoff.c +libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/libtcc \ No newline at end of file diff --git a/coff.h b/libtcc/coff.h similarity index 99% rename from coff.h rename to libtcc/coff.h index 1fb43fc2..285dfc23 100644 --- a/coff.h +++ b/libtcc/coff.h @@ -2,7 +2,8 @@ /* COFF.H */ /* COFF data structures and related definitions used by the linker */ /**************************************************************************/ - +#ifndef COFF_H +# define COFF_H 1 # include /*------------------------------------------------------------------------*/ @@ -389,3 +390,5 @@ union auxent #define _DORIGIN "_dorigin" #define _SORIGIN "_sorigin" + +#endif /* COFF_H */ \ No newline at end of file diff --git a/elf.h b/libtcc/elf.h similarity index 100% rename from elf.h rename to libtcc/elf.h diff --git a/i386-asm.c b/libtcc/i386/asm.c similarity index 99% rename from i386-asm.c rename to libtcc/i386/asm.c index d1038128..6f101b8c 100644 --- a/i386-asm.c +++ b/libtcc/i386/asm.c @@ -141,9 +141,6 @@ static const uint8_t reg_to_size[9] = { [OP_REG8] = 0, [OP_REG16] = 1, [OP_REG32] = 2, -#ifdef TCC_TARGET_X86_64 - [OP_REG64] = 3, -#endif */ 0, 0, 1, 0, 2, 0, 0, 0, 3 }; @@ -204,7 +201,7 @@ static const ASMInstr asm_instrs[] = { #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }}, #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }}, -#include "i386-asm.h" +#include "asm.h" /* last operation */ { 0, }, }; @@ -216,7 +213,7 @@ static const uint16_t op0_codes[] = { #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) -#include "i386-asm.h" +#include "asm.h" }; static inline int get_reg_shift(TCCState *s1) @@ -1293,11 +1290,6 @@ ST_FUNC void subst_asm_operand(CString *add_str, size = 1; else if ((sv->type.t & VT_BTYPE) == VT_SHORT) size = 2; -#ifdef TCC_TARGET_X86_64 - else if ((sv->type.t & VT_BTYPE) == VT_LLONG || - (sv->type.t & VT_BTYPE) == VT_PTR) - size = 8; -#endif else size = 4; if (size == 1 && reg >= 4) diff --git a/i386-asm.h b/libtcc/i386/asm.h similarity index 100% rename from i386-asm.h rename to libtcc/i386/asm.h diff --git a/i386-gen.c b/libtcc/i386/gen.c similarity index 92% rename from i386-gen.c rename to libtcc/i386/gen.c index 1d521160..f50a422c 100644 --- a/i386-gen.c +++ b/libtcc/i386/gen.c @@ -99,13 +99,6 @@ ST_DATA const int reg_classes[NB_REGS] = { static unsigned long func_sub_sp_offset; static int func_ret_sub; -#ifdef CONFIG_TCC_BCHECK -static addr_t func_bound_offset; -static unsigned long func_bound_ind; -ST_DATA int func_bound_add_epilog; -static void gen_bounds_prolog(void); -static void gen_bounds_epilog(void); -#endif /* XXX: make it faster ? */ ST_FUNC void g(int c) @@ -335,17 +328,6 @@ static void gadd_sp(int val) } } -#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE -static void gen_static_call(int v) -{ - Sym *sym; - - sym = external_helper_sym(v); - oad(0xe8, -4); - greloc(cur_text_section, sym, ind-4, R_386_PC32); -} -#endif - /* 'is_jmp' is '1' if it is a jump */ static void gcall_or_jmp(int is_jmp) { @@ -401,11 +383,6 @@ ST_FUNC void gfunc_call(int nb_args) int size, align, r, args_size, i, func_call; Sym *func_sym; -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - gbound_args(nb_args); -#endif - args_size = 0; for(i = 0;i < nb_args; i++) { if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { @@ -591,10 +568,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) func_ret_sub = 4; #endif -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - gen_bounds_prolog(); -#endif } /* generate function epilog */ @@ -602,11 +575,6 @@ ST_FUNC void gfunc_epilog(void) { addr_t v, saved_ind; -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - gen_bounds_epilog(); -#endif - /* align local size to word & save local variables */ v = (-loc + 3) & -4; @@ -1043,55 +1011,6 @@ ST_FUNC void ggoto(void) vtop--; } -/* bound check support functions */ -#ifdef CONFIG_TCC_BCHECK - -static void gen_bounds_prolog(void) -{ - /* leave some room for bound checking code */ - func_bound_offset = lbounds_section->data_offset; - func_bound_ind = ind; - func_bound_add_epilog = 0; - oad(0xb8, 0); /* lbound section pointer */ - oad(0xb8, 0); /* call to function */ -} - -static void gen_bounds_epilog(void) -{ - addr_t saved_ind; - addr_t *bounds_ptr; - Sym *sym_data; - int offset_modified = func_bound_offset != lbounds_section->data_offset; - - if (!offset_modified && !func_bound_add_epilog) - return; - - /* add end of table info */ - bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t)); - *bounds_ptr = 0; - - sym_data = get_sym_ref(&char_pointer_type, lbounds_section, - func_bound_offset, PTR_SIZE); - - /* generate bound local allocation */ - if (offset_modified) { - saved_ind = ind; - ind = func_bound_ind; - greloc(cur_text_section, sym_data, ind + 1, R_386_32); - ind = ind + 5; - gen_static_call(TOK___bound_local_new); - ind = saved_ind; - } - - /* generate bound check local freeing */ - o(0x5250); /* save returned value, if any */ - greloc(cur_text_section, sym_data, ind + 1, R_386_32); - oad(0xb8, 0); /* mov %eax, xxx */ - gen_static_call(TOK___bound_local_delete); - o(0x585a); /* restore returned value, if any */ -} -#endif - /* Save the stack pointer onto the stack */ ST_FUNC void gen_vla_sp_save(int addr) { /* mov %esp,addr(%ebp)*/ @@ -1109,9 +1028,6 @@ ST_FUNC void gen_vla_sp_restore(int addr) { ST_FUNC void gen_vla_alloc(CType *type, int align) { int use_call = 0; -#if defined(CONFIG_TCC_BCHECK) - use_call = tcc_state->do_bounds_check; -#endif #ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */ use_call = 1; #endif diff --git a/i386-link.c b/libtcc/i386/link.c similarity index 88% rename from i386-link.c rename to libtcc/i386/link.c index 278df264..005a8ee2 100644 --- a/i386-link.c +++ b/libtcc/i386/link.c @@ -99,11 +99,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ int modrm; unsigned plt_offset, relofs; - /* on i386 if we build a DLL, we add a %ebx offset */ - if (s1->output_type & TCC_OUTPUT_DYN) - modrm = 0xa3; - else - modrm = 0x25; + modrm = 0x25; /* empty PLT: create PLT0 entry that pushes the library identifier (GOT + PTR_SIZE) and jumps to ld.so resolution routine @@ -148,7 +144,7 @@ ST_FUNC void relocate_plt(TCCState *s1) p = s1->plt->data; p_end = p + s1->plt->data_offset; - if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) { + if (p < p_end) { add32le(p + 2, s1->got->sh_addr); add32le(p + 8, s1->got->sh_addr); p += 16; @@ -179,31 +175,9 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, switch (type) { case R_386_32: - if (s1->output_type & TCC_OUTPUT_DYN) { - esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; - qrel->r_offset = rel->r_offset; - if (esym_index) { - qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32); - qrel++; - return; - } else { - qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE); - qrel++; - } - } add32le(ptr, val); return; case R_386_PC32: - if (s1->output_type == TCC_OUTPUT_DLL) { - /* DLL relocation */ - esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; - if (esym_index) { - qrel->r_offset = rel->r_offset; - qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32); - qrel++; - return; - } - } add32le(ptr, val - addr); return; case R_386_PLT32: diff --git a/i386-tok.h b/libtcc/i386/tok.h similarity index 99% rename from i386-tok.h rename to libtcc/i386/tok.h index 04844d26..b1450bdf 100644 --- a/i386-tok.h +++ b/libtcc/i386/tok.h @@ -266,7 +266,7 @@ #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) -#include "i386-asm.h" +#include "asm.h" #define ALT(x) #define DEF_ASM_OP0(name, opcode) @@ -274,4 +274,4 @@ #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name) -#include "i386-asm.h" +#include "asm.h" diff --git a/libtcc.c b/libtcc/libtcc.c similarity index 90% rename from libtcc.c rename to libtcc/libtcc.c index ca31aa7e..a79ead7d 100644 --- a/libtcc.c +++ b/libtcc/libtcc.c @@ -19,6 +19,7 @@ */ #include "tcc.h" +#include "utils/string.h" /********************************************************/ /* global variables */ @@ -78,44 +79,6 @@ PUB_FUNC void tcc_exit_state(TCCState *s1) POST_SEM(&tcc_compile_sem); } -/********************************************************/ -/* copy a string and truncate it. */ -ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s) -{ - char *q, *q_end; - int c; - - if (buf_size > 0) { - q = buf; - q_end = buf + buf_size - 1; - while (q < q_end) { - c = *s++; - if (c == '\0') - break; - *q++ = c; - } - *q = '\0'; - } - return buf; -} - -/* strcat and truncate. */ -ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s) -{ - size_t len; - len = strlen(buf); - if (len < buf_size) - pstrcpy(buf + len, buf_size - len, s); - return buf; -} - -ST_FUNC char *pstrncpy(char *out, const char *in, size_t num) -{ - memcpy(out, in, num); - out[num] = '\0'; - return out; -} - /* extract the basename of a file */ PUB_FUNC char *tcc_basename(const char *name) { @@ -180,7 +143,7 @@ ST_FUNC void libc_free(void *ptr) /* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */ static void *(*reallocator)(void*, unsigned long) = default_reallocator; -LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc) +void tcc_set_realloc(TCCReallocFunc *realloc) { reallocator = realloc ? realloc : default_reallocator; } @@ -574,7 +537,7 @@ static void error1(int mode, const char *fmt, va_list ap) } } -LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func) +void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func) { s->error_opaque = error_opaque; s->error_func = error_func; @@ -720,13 +683,13 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd) return s1->nb_errors != 0 ? -1 : 0; } -LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) +int tcc_compile_string(TCCState *s, const char *str) { return tcc_compile(s, s->filetype, str, -1); } /* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */ -LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) +void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) { const char *eq; if (NULL == (eq = strchr(sym, '='))) @@ -737,13 +700,13 @@ LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *valu } /* undefine a preprocessor symbol */ -LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym) +void tcc_undefine_symbol(TCCState *s1, const char *sym) { cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym); } -LIBTCCAPI TCCState *tcc_new(void) +TCCState *tcc_new(void) { TCCState *s; @@ -779,7 +742,7 @@ LIBTCCAPI TCCState *tcc_new(void) return s; } -LIBTCCAPI void tcc_delete(TCCState *s1) +void tcc_delete(TCCState *s1) { /* free sections */ tccelf_delete(s1); @@ -808,7 +771,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1) cstr_free(&s1->cmdline_defs); cstr_free(&s1->cmdline_incl); cstr_free(&s1->linker_arg); - tcc_free(s1->dState); /* free loaded dlls array */ dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); tcc_free(s1); @@ -817,12 +779,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1) #endif } -LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) +int tcc_set_output_type(TCCState *s, int output_type) { -#ifdef CONFIG_TCC_PIE - if (output_type == TCC_OUTPUT_EXE) - output_type |= TCC_OUTPUT_DYN; -#endif s->output_type = output_type; if (!s->nostdinc) { @@ -832,7 +790,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) } if (output_type == TCC_OUTPUT_PREPROCESS) { - s->do_debug = 0; return 0; } @@ -854,13 +811,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) return 0; } -LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) +int tcc_add_include_path(TCCState *s, const char *pathname) { tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); return 0; } -LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) +int tcc_add_sysinclude_path(TCCState *s, const char *pathname) { tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); return 0; @@ -932,45 +889,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE)); break; -#ifdef TCC_TARGET_PE - default: - ret = pe_load_file(s1, fd, filename); - goto check_success; + case AFF_BINTYPE_COFF: + ret = coff_load_file(s1, fd, filename); + break; -#elif defined TCC_TARGET_MACHO - case AFF_BINTYPE_DYN: - case_dyn_or_tbd: - if (s1->output_type == TCC_OUTPUT_MEMORY) { -#ifdef TCC_IS_NATIVE - void* dl; - const char* soname = filename; - if (obj_type != AFF_BINTYPE_DYN) - soname = macho_tbd_soname(filename); - dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY); - if (dl) - tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0; - if (filename != soname) - tcc_free((void *)soname); -#endif - } else if (obj_type == AFF_BINTYPE_DYN) { - ret = macho_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); - } else { - ret = macho_load_tbd(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); - } - goto check_success; - default: - { - const char *ext = tcc_fileextension(filename); - if (!strcmp(ext, ".tbd")) - goto case_dyn_or_tbd; - if (!strcmp(ext, ".dylib")) { - obj_type = AFF_BINTYPE_DYN; - goto case_dyn_or_tbd; - } - goto check_success; - } - -#else /* unix */ case AFF_BINTYPE_DYN: if (s1->output_type == TCC_OUTPUT_MEMORY) { } else @@ -980,20 +902,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) default: /* as GNU ld, consider it is an ld script if not recognized */ ret = tcc_load_ldscript(s1, fd); - goto check_success; - -#endif /* pe / macos / unix */ - -check_success: if (ret < 0) tcc_error_noabort("%s: unrecognized file type", filename); break; - -#ifdef TCC_TARGET_COFF - case AFF_BINTYPE_C67: - ret = tcc_load_coff(s1, fd); - break; -#endif } close(fd); } else { @@ -1030,12 +941,12 @@ static int guess_filetype(const char *filename) return filetype; } -LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) +int tcc_add_file(TCCState *s, const char *filename) { return tcc_add_file_internal(s, filename, s->filetype | AFF_PRINT_ERROR); } -LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) +int tcc_add_library_path(TCCState *s, const char *pathname) { tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname); return 0; @@ -1074,7 +985,7 @@ ST_FUNC int tcc_add_support(TCCState *s1, const char *filename) return tcc_add_dll(s1, filename, AFF_PRINT_ERROR); } -#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO +#if !defined TCC_TARGET_PE ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) { return tcc_add_library_internal(s1, "%s/%s", @@ -1083,7 +994,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) #endif /* the library name is the same as the argument of the '-l' option */ -LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) +int tcc_add_library(TCCState *s, const char *libraryname) { static const char * const libs[] = { "%s/lib%s.a", NULL }; const char * const *pp = libs; @@ -1106,7 +1017,7 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1) tcc_add_library(s1, s1->pragma_libs[i]); } -LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val) +int tcc_add_symbol(TCCState *s1, const char *name, const void *val) { char buf[256]; if (s1->leading_underscore) { @@ -1118,7 +1029,7 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val) return 0; } -LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path) +void tcc_set_lib_path(TCCState *s, const char *path) { tcc_free(s->tcc_lib_path); s->tcc_lib_path = tcc_strdup(path); @@ -1393,13 +1304,6 @@ static const TCCOption tcc_options[] = { { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG }, { "bench", TCC_OPTION_bench, 0 }, -#ifdef CONFIG_TCC_BACKTRACE - { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, -#endif -#ifdef CONFIG_TCC_BCHECK - { "b", TCC_OPTION_b, 0 }, -#endif - { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "c", TCC_OPTION_c, 0 }, { "dumpmachine", TCC_OPTION_dumpmachine, 0}, { "dumpversion", TCC_OPTION_dumpversion, 0}, @@ -1435,6 +1339,7 @@ static const TCCOption tcc_options[] = { { "ar", TCC_OPTION_ar, 0}, /* ignored (silently, except after -Wunsupported) */ { "arch", 0, TCC_OPTION_HAS_ARG}, + { "g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, { "C", 0, 0 }, { "-param", 0, TCC_OPTION_HAS_ARG }, { "pedantic", 0, 0 }, @@ -1470,7 +1375,6 @@ static const FlagDef options_f[] = { { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, { offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, - { offsetof(TCCState, test_coverage), 0, "test-coverage" }, { offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs" }, { offsetof(TCCState, gnu89_inline), 0, "gnu89-inline" }, { offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" }, @@ -1675,32 +1579,6 @@ dorun: case TCC_OPTION_bench: s->do_bench = 1; break; -#ifdef CONFIG_TCC_BACKTRACE - case TCC_OPTION_bt: - s->rt_num_callers = atoi(optarg); /* zero = default (6) */ - goto enable_backtrace; - enable_backtrace: - s->do_backtrace = 1; - s->do_debug = s->do_debug ? s->do_debug : 1; - s->dwarf = CONFIG_DWARF_VERSION; - break; -#ifdef CONFIG_TCC_BCHECK - case TCC_OPTION_b: - s->do_bounds_check = 1; - goto enable_backtrace; -#endif -#endif - case TCC_OPTION_g: - s->do_debug = 2; - s->dwarf = CONFIG_DWARF_VERSION; - if (strstart("dwarf", &optarg)) { - s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION; - } else if (isnum(*optarg)) { - x = *optarg - '0'; - /* -g0 = no info, -g1 = lines/functions only, -g2 = full info */ - s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x; - } - break; case TCC_OPTION_c: x = TCC_OUTPUT_OBJ; set_output_type: @@ -1713,8 +1591,6 @@ dorun: s->dflag = 3; else if (*optarg == 'M') s->dflag = 7; - else if (*optarg == 't') - s->dflag = 16; else if (isnum(*optarg)) s->g_debug |= atoi(optarg); else @@ -1727,9 +1603,6 @@ dorun: if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0) s->cversion = 201112; break; - case TCC_OPTION_shared: - x = TCC_OUTPUT_DLL; - goto set_output_type; case TCC_OPTION_soname: s->soname = tcc_strdup(optarg); break; @@ -1885,7 +1758,7 @@ unsupported_option: return OPT_HELP; } -LIBTCCAPI int tcc_set_options(TCCState *s, const char *r) +int tcc_set_options(TCCState *s, const char *r) { char **argv = NULL; int argc = 0, ret; @@ -1913,15 +1786,6 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) ); #ifdef MEM_DEBUG fprintf(stderr, "# memory usage"); -#ifdef TCC_IS_NATIVE - if (s1->run_size) { - Section *s = s1->symtab; - unsigned ms = s->data_offset + s->link->data_offset + s->hash->data_offset; - unsigned rs = s1->run_size; - fprintf(stderr, ": %d to run, %d symbols, %d other,", - rs, ms, mem_cur_size - rs - ms); - } -#endif fprintf(stderr, " %d max (bytes)\n", mem_max_size); #endif } diff --git a/libtcc/libtcc.h b/libtcc/libtcc.h new file mode 100644 index 00000000..fdb0c5c0 --- /dev/null +++ b/libtcc/libtcc.h @@ -0,0 +1,179 @@ +#ifndef LIBTCC_H +# define LIBTCC_H 1 + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +typedef void *TCCReallocFunc(void *ptr, unsigned long size); +/** + * @brief set custom allocator for all allocations (optional), NULL for default. + */ +void tcc_set_realloc(TCCReallocFunc *my_realloc); + +typedef struct TCCState TCCState; + +/** + * @brief create a new TCC compilation context. + */ +TCCState *tcc_new(void); + +/** + * @brief free a TCC compilation context. + */ +void tcc_delete(TCCState *s); + +/** + * @brief set CONFIG_TCCDIR at runtime. + */ +void tcc_set_lib_path(TCCState *s, const char *path); + +typedef void TCCErrorFunc(void *opaque, const char *msg); + +/** + * @brief set error/warning callback (optional). + */ +void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func); + +/** + * @brief set options as from command line (multiple supported) + */ +int tcc_set_options(TCCState *s, const char *str); + +/** + * @defgroup preprocessor Preprocessor + * @{ + */ + +/** + * @brief add include path + */ +int tcc_add_include_path(TCCState *s, const char *pathname); + +/** + * @brief add in system include path + */ +int tcc_add_sysinclude_path(TCCState *s, const char *pathname); + +/** + * @brief define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" + */ +void tcc_define_symbol(TCCState *s, const char *sym, const char *value); + +/** + * @brief undefine preprocess symbol 'sym' + */ +void tcc_undefine_symbol(TCCState *s, const char *sym); + +/** + * @} +*/ + +/** + * @defgroup compiling Compiling + * @{ + */ + +/** + * @brief add a file (C file, object, library, ld script). Return -1 if error. + */ +int tcc_add_file(TCCState *s, const char *filename); + +/** + * @brief compile a string containing a C source. Return -1 if error. + * + * Tip: to have more specific errors/warnings from tcc_compile_string(), + * you can prefix the string with "#line \"\"\n" + */ +int tcc_compile_string(TCCState *s, const char *buf); + +/** + * @} + */ + +/** + * @defgroup linking Linking commands + * @{ + */ +# define TCC_OUTPUT_MEMORY 1 /** output will be run in memory */ +# define TCC_OUTPUT_EXE 2 /** executable file */ +# define TCC_OUTPUT_OBJ 3 /** object file */ +# define TCC_OUTPUT_PREPROCESS 5 /** only preprocess */ + +/** + * @brief set output type. MUST BE CALLED before any compilation. + */ +int tcc_set_output_type(TCCState *s, int output_type); + +/** + * @brief equivalent to -Lpath option. + */ +int tcc_add_library_path(TCCState *s, const char *pathname); + +/** + * @brief the library name is the same as the argument of the '-l' option. + */ +int tcc_add_library(TCCState *s, const char *libraryname); + +/** + * @brief add a symbol to the compiled program. + */ +int tcc_add_symbol(TCCState *s, const char *name, const void *val); + +/** + * @brief output an executable, library or object file. + * + * DO NOT call tcc_relocate() before. + */ +int tcc_output_file(TCCState *s, const char *filename); + +/** + * @brief do all relocations (needed before using tcc_get_symbol()). + */ +int tcc_relocate(TCCState *s1); + +/** + * @brief return symbol value or NULL if not found. + */ +void *tcc_get_symbol(TCCState *s, const char *name); + +typedef void (TCCSymbolFunc)(void *ctx, const char *name, const void *val); + +/** + * @brief list all (global) symbols and their values via 'symbol_cb()'. + */ +void tcc_list_symbols(TCCState *s, void *ctx, TCCSymbolFunc *symbol_cb); + +/** + * @} + */ + +/** + * experimental/advanced section (see libtcc_test_mt.c for an example). + * @defgroup experimental Experimental/Advanced + * @{ + */ + +/** + * @brief catch runtime exceptions (optionally limit backtraces at top_func), when using tcc_set_options("-bt"). + */ +void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp); + +# define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp)) + +typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg); + +/** + * @brief custom error printer for runtime exceptions. Returning 0 stops backtrace. + */ +void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*); + +/** + * @} + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* !TCC_H */ \ No newline at end of file diff --git a/libtcc/object/archive.h b/libtcc/object/archive.h new file mode 100644 index 00000000..c560dd72 --- /dev/null +++ b/libtcc/object/archive.h @@ -0,0 +1,35 @@ +#ifndef LIBTCC_OBJECT_ARCHIVE_H +# define LIBTCC_OBJECT_ARCHIVE_H 1 + +/** + * @defgroup object_archive UNIX Archive + * @ingroup object + * @{ + */ + +# define ARCHIVE_MAGIC "!\n" +# define ARCHIVE_MAGSZ 8 +# define ARCHIVE_FILMAG "`\n" + +typedef struct ArchiveFileHeader { + char name[16]; + char last_mod[12]; + char uid[6]; + char gid[6]; + char mode[8]; + char size[10]; + char fmag[2]; +} ArchiveFileHeader; + +typedef struct ArchiveEntry { +} ArchiveEntry; + +typedef struct Archive { + char *filename; +} Archive; + +/** + * @} + */ + +#endif /* !LIBTCC_OBJECT_AR_H */ \ No newline at end of file diff --git a/libtcc/object/coff.h b/libtcc/object/coff.h new file mode 100644 index 00000000..e3af72cc --- /dev/null +++ b/libtcc/object/coff.h @@ -0,0 +1,69 @@ +#ifndef LIBTCC_OBJECT_COFF_H +# define LIBTCC_OBJECT_COFF_H 1 + +# include + +/** + * @defgroup object_coff COFF Object + * @ingroup object + * @{ + */ + +# define COFF_MAGIC 0x14c + +typedef struct COFFFileHeader { + uint16_t magic; + uint16_t nscns; + int32_t timdat; + int32_t nsyms; + uint16_t opthdr; + uint16_t flags; +} COFFFileHeader; + +# define COFF_FILHSZ sizeof(COFFFileHeader) + +# define COFF_F_RELFLG 0x0001 +# define COFF_F_EXEC 0x0002 +# define COFF_F_LNNO 0x0004 +# define COFF_F_LSYMS 0x0008 +# define COFF_F_LITTLE 0x0100 +# define COFF_F_BIG 0x0200 +# define COFF_F_SYMMERGE 0x1000 + +typedef struct AOutHeader { + int16_t magic; + int16_t vstamp; + int32_t tsize; + int32_t dsize; + int32_t bsize; + int32_t entry; + int32_t text_start; + int32_t data_start; +} AOutHeader; + +# define AOUT_HSZ sizeof(AOutHeader) + +# define AOUT_OMAGIC 0404 +# define AOUT_NMAGIC 0410 +# define AOUT_ZMAGIC 0413 +# define AOUT_STMAGIC 0401 +# define AOUT_SHMAGIC 0443 + +typedef struct COFFSectionHeader { + int8_t name[8]; + int32_t paddr; + int32_t vaddr; + int32_t size; + int32_t scnptr; + int32_t relptr; + int32_t lnnoptr; + uint16_t nreloc; + uint16_t nlnno; + int32_t flags; +} COFFSectionHeader; + +/** + * @} + */ + +#endif /* !LIBTCC_COFF_H */ \ No newline at end of file diff --git a/libtcc/option.c b/libtcc/option.c new file mode 100644 index 00000000..3091afc8 --- /dev/null +++ b/libtcc/option.c @@ -0,0 +1,2 @@ +#include "tcc.h" + diff --git a/libtcc/option.h b/libtcc/option.h new file mode 100644 index 00000000..4539f91a --- /dev/null +++ b/libtcc/option.h @@ -0,0 +1,6 @@ +#ifndef LIBTCC_OPTION_H +# define LIBTCC_OPTION_H 1 + +int tcc_parse_args(void *s, int *argc, char ***argv, int optind); + +#endif /* LIBTCC_OPTION_H */ \ No newline at end of file diff --git a/tcc.h b/libtcc/tcc.h similarity index 89% rename from tcc.h rename to libtcc/tcc.h index d6352880..90527855 100644 --- a/tcc.h +++ b/libtcc/tcc.h @@ -69,7 +69,7 @@ extern long double strtold (const char *__nptr, char **__endptr); # define strtoull _strtoui64 # endif # ifdef LIBTCC_AS_DLL -# define LIBTCCAPI __declspec(dllexport) +# define __declspec(dllexport) # define PUB_FUNC LIBTCCAPI # endif # ifdef _MSC_VER @@ -138,29 +138,8 @@ extern long double strtold (const char *__nptr, char **__endptr); /* assembler debug */ /* #define ASM_DEBUG */ -/* target selection */ -/* #define TCC_TARGET_I386 *//* i386 code generator */ -/* #define TCC_TARGET_X86_64 *//* x86-64 code generator */ -/* #define TCC_TARGET_ARM *//* ARMv4 code generator */ -/* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */ -/* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */ -/* #define TCC_TARGET_RISCV64 *//* risc-v code generator */ - -/* default target is I386 */ # define TCC_TARGET_I386 -#if defined CONFIG_TCC_BACKTRACE && CONFIG_TCC_BACKTRACE==0 -# undef CONFIG_TCC_BACKTRACE -#else -# define CONFIG_TCC_BACKTRACE 1 /* enable builtin stack backtraces */ -#endif - -#if defined CONFIG_TCC_BCHECK && CONFIG_TCC_BCHECK==0 -# undef CONFIG_TCC_BCHECK -#else -# define CONFIG_TCC_BCHECK 1 /* enable bound checking code */ -#endif - #ifdef CONFIG_TCC_PIE # define CONFIG_TCC_PIC 1 #endif @@ -231,14 +210,6 @@ extern long double strtold (const char *__nptr, char **__endptr); # define CONFIG_TCC_ELFINTERP "/lib/ld.so" # elif defined(TCC_TARGET_PE) # define CONFIG_TCC_ELFINTERP "-" -# elif defined TCC_TARGET_ARM64 -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-aarch64.so.1" -# elif defined(TCC_TARGET_X86_64) -# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" -# elif defined(TCC_TARGET_RISCV64) -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-riscv64-lp64d.so.1" -# elif defined(TCC_ARM_EABI) -# define DEFAULT_ELFINTERP(s) default_elfinterp(s) # else # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" # endif @@ -268,8 +239,7 @@ extern long double strtold (const char *__nptr, char **__endptr); #include "libtcc.h" #include "elf.h" -#include "stab.h" -#include "dwarf.h" +#include "coff.h" /* -------------------------------------------- */ @@ -290,8 +260,8 @@ extern long double strtold (const char *__nptr, char **__endptr); /* include the target specific definitions */ #define TARGET_DEFS_ONLY -# include "i386-gen.c" -# include "i386-link.c" +# include "i386/gen.c" +# include "i386/link.c" #undef TARGET_DEFS_ONLY # define ELFCLASSW ELFCLASS32 @@ -606,9 +576,6 @@ struct sym_attr { unsigned plt_offset; int plt_sym; int dyn_index; -#ifdef TCC_TARGET_ARM - unsigned char plt_thumb_stub:1; -#endif }; struct TCCState { @@ -653,16 +620,6 @@ struct TCCState { unsigned char include_sys_deps; /* option -MD */ unsigned char gen_phony_deps; /* option -MP */ - /* 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 */ - unsigned char do_bounds_check; -#endif - unsigned char test_coverage; /* generate test coverage code */ - /* use GNU C extensions */ unsigned char gnu_ext; /* use TinyCC extensions */ @@ -671,19 +628,11 @@ struct TCCState { unsigned char dflag; /* -dX value */ unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */ -#ifdef TCC_TARGET_X86_64 - unsigned char nosse; /* For -mno-sse support. */ -#endif -#ifdef TCC_TARGET_ARM - unsigned char float_abi; /* float ABI of the generated code*/ -#endif - unsigned char has_text_addr; addr_t text_addr; /* address of text section */ unsigned section_align; /* section alignment */ -#ifdef TCC_TARGET_I386 + int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ -#endif char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */ char *soname; /* as specified on the command line (-soname) */ @@ -697,8 +646,6 @@ struct TCCState { int output_type; /* output format, see TCC_OUTPUT_FORMAT_xxx */ int output_format; - /* nth test to run with -dt -run */ - int run_test; /* array of all loaded dlls (including those referenced by loaded dlls) */ DLLReference **loaded_dlls; @@ -772,11 +719,6 @@ struct TCCState { Section *text_section, *data_section, *rodata_section, *bss_section; Section *common_section; Section *cur_text_section; /* current section where function code is generated */ -#ifdef CONFIG_TCC_BCHECK - /* bound check related sections */ - Section *bounds_section; /* contains global data bound description */ - Section *lbounds_section; /* contains local data bound description */ -#endif /* symbol section */ union { Section *symtab_section, *symtab; }; /* historical alias */ /* temporary dynamic symbol sections (for dll loading) */ @@ -789,19 +731,6 @@ struct TCCState { Section *eh_frame_section; Section *eh_frame_hdr_section; unsigned long eh_start; - /* 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; - int dwlo, dwhi; /* dwarf section range */ - /* test coverage */ - Section *tcov_section; - /* debug state */ - struct _tccdbg *dState; /* Is there a new undefined sym since last new_undef_sym() */ int new_undef_sym; @@ -812,11 +741,6 @@ struct TCCState { ElfW_Rel *qrel; #define qrel s1->qrel -#ifdef TCC_TARGET_RISCV64 - struct pcrel_hi { addr_t addr, val; } last_hi; - #define last_hi s1->last_hi -#endif - #ifdef TCC_TARGET_PE /* PE info */ int pe_subsystem; @@ -824,17 +748,6 @@ struct TCCState { unsigned pe_file_align; unsigned pe_stack_size; addr_t pe_imagebase; -# ifdef TCC_TARGET_X86_64 - Section *uw_pdata; - int uw_sym; - unsigned uw_offs; -# endif -#endif - -#if defined TCC_TARGET_MACHO - char *install_name; - uint32_t compatibility_version; - uint32_t current_version; #endif #ifndef ELF_OBJ_ONLY @@ -847,24 +760,6 @@ struct TCCState { Section *verneed_section; #endif -#ifdef TCC_IS_NATIVE - const char *run_main; /* entry for tcc_run() */ - void *run_ptr; /* runtime_memory */ - unsigned run_size; /* size of runtime_memory */ -#ifdef _WIN64 - void *run_function_table; /* unwind data */ -#endif - struct TCCState *next; - struct rt_context *rc; /* pointer to backtrace info block */ - void *run_lj, *run_jb; /* sj/lj for tcc_setjmp()/tcc_run() */ - TCCBtFunc *bt_func; - void *bt_data; -#endif - -#ifdef CONFIG_TCC_BACKTRACE - int rt_num_callers; -#endif - /* benchmark info */ int total_idents; int total_lines; @@ -1079,9 +974,6 @@ ST_DATA void** stk_data; ST_DATA int nb_stk_data; /* public functions currently used by the tcc main function */ -ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s); -ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s); -ST_FUNC char *pstrncpy(char *out, const char *in, size_t num); PUB_FUNC char *tcc_basename(const char *name); PUB_FUNC char *tcc_fileextension (const char *name); @@ -1153,10 +1045,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) #define AFF_TYPE_LIB 8 #define AFF_TYPE_MASK (15 | AFF_TYPE_BIN) /* values from tcc_object_type(...) */ -#define AFF_BINTYPE_REL 1 -#define AFF_BINTYPE_DYN 2 -#define AFF_BINTYPE_AR 3 -#define AFF_BINTYPE_C67 4 +#define AFF_BINTYPE_REL 1 +#define AFF_BINTYPE_DYN 2 +#define AFF_BINTYPE_AR 3 +#define AFF_BINTYPE_COFF 4 /* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */ #define FILE_NOT_FOUND -2 @@ -1166,12 +1058,7 @@ ST_FUNC int tcc_add_crt(TCCState *s, const char *filename); #endif ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags); ST_FUNC int tcc_add_support(TCCState *s1, const char *filename); -#ifdef CONFIG_TCC_BCHECK -ST_FUNC void tcc_add_bcheck(TCCState *s1); -#endif -#ifdef CONFIG_TCC_BACKTRACE -ST_FUNC void tcc_add_btstub(TCCState *s1); -#endif + ST_FUNC void tcc_add_pragma_libs(TCCState *s1); PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); @@ -1353,9 +1240,6 @@ ST_FUNC void vpop(void); #if PTR_SIZE == 4 ST_FUNC void lexpand(void); #endif -#ifdef TCC_TARGET_ARM -ST_FUNC int get_reg_ex(int rc, int rc2); -#endif ST_FUNC void save_reg(int r); ST_FUNC void save_reg_upstack(int r, int n); ST_FUNC int get_reg(int rc); @@ -1374,23 +1258,12 @@ ST_FUNC void indir(void); ST_FUNC void unary(void); ST_FUNC void gexpr(void); ST_FUNC int expr_const(void); -#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67 -ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size); -#endif -#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE -ST_FUNC int classify_x86_64_va_arg(CType *ty); -#endif -#ifdef CONFIG_TCC_BCHECK -ST_FUNC void gbound_args(int nb_args); -ST_DATA int func_bound_add_epilog; -#endif /* ------------ tccelf.c ------------ */ #define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */ #define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */ #define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */ -#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL #define ARMAG "!\n" /* For COFF and a.out archives */ @@ -1455,9 +1328,11 @@ ST_FUNC void tccelf_add_crtend(TCCState *s1); ST_FUNC void tcc_add_runtime(TCCState *s1); #endif +int coff_load_file(TCCState *s1, int fd, const char *fname); + /* ------------ xxx-link.c ------------ */ -#if !defined ELF_OBJ_ONLY || defined TCC_TARGET_MACHO +#if !defined ELF_OBJ_ONLY ST_FUNC int code_reloc (int reloc_type); ST_FUNC int gotplt_entry_type (int reloc_type); /* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so @@ -1470,13 +1345,11 @@ enum gotplt_entry { }; #define NEED_RELOC_TYPE -#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr); ST_FUNC void relocate_plt(TCCState *s1); ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */ #define NEED_BUILD_GOT -#endif #endif ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); @@ -1504,9 +1377,7 @@ ST_FUNC void gen_cvt_ftoi(int t); ST_FUNC void gen_cvt_itof(int t); ST_FUNC void gen_cvt_ftof(int t); ST_FUNC void ggoto(void); -#ifndef TCC_TARGET_C67 ST_FUNC void o(unsigned int c); -#endif ST_FUNC void gen_vla_sp_save(int addr); ST_FUNC void gen_vla_sp_restore(int addr); ST_FUNC void gen_vla_alloc(CType *type, int align); @@ -1584,17 +1455,15 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end) /* ------------ i386-gen.c ------------ */ -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM ST_FUNC void g(int c); ST_FUNC void gen_le16(int c); ST_FUNC void gen_le32(int c); -#endif -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 + ST_FUNC void gen_addr32(int r, Sym *sym, int c); ST_FUNC void gen_addrpc32(int r, Sym *sym, int c); ST_FUNC void gen_cvt_csti(int t); ST_FUNC void gen_increment_tcov (SValue *sv); -#endif + @@ -1626,47 +1495,8 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str); #define ST_ASM_SET 0x04 -/* ------------ tcctools.c ----------------- */ -#if 0 /* included in tcc.c */ -ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv); -ST_FUNC int tcc_tool_cross(TCCState *s, char **argv, int option); -ST_FUNC int gen_makedeps(TCCState *s, const char *target, const char *filename); -#endif - /* ------------ tccdbg.c ------------ */ -ST_FUNC void tcc_debug_new(TCCState *s); - -ST_FUNC void tcc_debug_start(TCCState *s1); -ST_FUNC void tcc_debug_end(TCCState *s1); -ST_FUNC void tcc_debug_bincl(TCCState *s1); -ST_FUNC void tcc_debug_eincl(TCCState *s1); -ST_FUNC void tcc_debug_newfile(TCCState *s1); - -ST_FUNC void tcc_debug_line(TCCState *s1); -ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e); -ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym); -ST_FUNC void tcc_debug_prolog_epilog(TCCState *s1, int value); -ST_FUNC void tcc_debug_funcend(TCCState *s1, int size); -ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type); -ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym); -ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value); -ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t); - -#if !(defined ELF_OBJ_ONLY || defined TCC_TARGET_ARM || defined TARGETOS_BSD) -ST_FUNC void tcc_eh_frame_start(TCCState *s1); -ST_FUNC void tcc_eh_frame_end(TCCState *s1); -ST_FUNC void tcc_eh_frame_hdr(TCCState *s1, int final); -#define TCC_EH_FRAME 1 -#endif - -ST_FUNC void tcc_tcov_start(TCCState *s1); -ST_FUNC void tcc_tcov_end(TCCState *s1); -ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start); -ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line); -ST_FUNC void tcc_tcov_block_begin(TCCState *s1); -ST_FUNC void tcc_tcov_reset_ind(TCCState *s1); - #define stab_section s1->stab_section #define stabstr_section stab_section->link #define tcov_section s1->tcov_section @@ -1679,12 +1509,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1); #define dwarf_str_section s1->dwarf_str_section #define dwarf_line_str_section s1->dwarf_line_str_section -/* default dwarf version for "-gdwarf" */ -#ifdef TCC_TARGET_MACHO -# define DEFAULT_DWARF_VERSION 2 -#else -# define DEFAULT_DWARF_VERSION 5 -#endif /* default dwarf version for "-g". use 0 to emit stab debug infos */ #ifndef CONFIG_DWARF_VERSION @@ -1693,8 +1517,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1); #if defined TCC_TARGET_PE # define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */ -#elif defined TCC_TARGET_X86_64 -# define R_DATA_32DW R_X86_64_32 #else # define R_DATA_32DW R_DATA_32 #endif diff --git a/tccasm.c b/libtcc/tccasm.c similarity index 99% rename from tccasm.c rename to libtcc/tccasm.c index 52d81fa8..907ba5e8 100644 --- a/tccasm.c +++ b/libtcc/tccasm.c @@ -20,6 +20,7 @@ #define USING_GLOBALS #include "tcc.h" +#include "utils/string.h" #ifdef CONFIG_TCC_ASM static Section *last_text_section; /* to handle .previous asm directive */ @@ -958,7 +959,6 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) next(); if (tok == TOK_EOF) break; - tcc_debug_line(s1); parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ redo: if (tok == '#') { @@ -1009,14 +1009,12 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) { int ret; - tcc_debug_start(s1); /* default section is text */ cur_text_section = text_section; ind = cur_text_section->data_offset; nocode_wanted = 0; ret = tcc_assemble_internal(s1, do_preprocess, 1); cur_text_section->data_offset = ind; - tcc_debug_end(s1); return ret; } diff --git a/tcccoff.c b/libtcc/tcccoff.c similarity index 81% rename from tcccoff.c rename to libtcc/tcccoff.c index fbbc58ee..7fd44c96 100644 --- a/tcccoff.c +++ b/libtcc/tcccoff.c @@ -15,14 +15,29 @@ coff_load_lib(TCCState *s1, int fd) return (0); } +static int +coff_merge_or_create(void) +{ + return (0); +} + +static int +coff_resolve_symbols(void) +{ + return (0); +} + int coff_load_obj(TCCState *s1, int fd) { FILHDR hdr; SCNHDR *scns; SYMENT *syments; + RELOC *relocs; + Section *s; uint16_t i; int32_t j; + int k; char buff[9]; if (!read_mem(fd, 0, &hdr, FILHSZ)) @@ -31,8 +46,6 @@ coff_load_obj(TCCState *s1, int fd) if (hdr.f_magic != F_MACH_I386 || hdr.f_flags & F_EXEC) return (tcc_error_noabort("invalid coff object file")); - /* load symtab */ - /* read sections */ scns = tcc_malloc(SCNHSZ * hdr.f_nscns); if (!read_mem(fd, FILHSZ, scns, SCNHSZ * hdr.f_nscns)) @@ -46,6 +59,17 @@ coff_load_obj(TCCState *s1, int fd) memset(buff, 0, 9); memcpy(buff, scns[i].s_name, 8); printf("sec: %s\n", buff); + + for (k = 1; k < s1->nb_sections; k++) + { + if (strcmp(s1->sections[k]->name, buff) != 0) + { + continue; + } + + + } + } /* load symtab */ @@ -54,7 +78,7 @@ coff_load_obj(TCCState *s1, int fd) for (j = 0; j < hdr.f_nsyms; j++) { memset(buff, 0, 9); - memcpy(buff, syments[i].n_name, 8); + memcpy(buff, syments[j].n_name, 8); printf("sym: %s\n", buff); } diff --git a/libtcc/tcccoff.c_old.c b/libtcc/tcccoff.c_old.c new file mode 100644 index 00000000..56064cdd --- /dev/null +++ b/libtcc/tcccoff.c_old.c @@ -0,0 +1,951 @@ +/* + * COFF file handling for TCC + * + * Copyright (c) 2003, 2004 TK + * Copyright (c) 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" + +/* XXX: this file uses tcc_error() to the effect of exit(1) */ +#undef _tcc_error + +#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ +#define MAX_STR_TABLE 1000000 +AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ + +SCNHDR section_header[MAXNSCNS]; + +#define MAX_FUNCS 1000 +#define MAX_FUNC_NAME_LENGTH 128 + +int nFuncs; +char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; +char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; +int LineNoFilePtr[MAX_FUNCS]; +int EndAddress[MAX_FUNCS]; +int LastLineNo[MAX_FUNCS]; +int FuncEntries[MAX_FUNCS]; + +int OutputTheSection(Section * sect); +short int GetCoffFlags(const char *s); +void SortSymbolTable(TCCState *s1); +Section *FindSection(TCCState * s1, const char *sname); + +int C67_main_entry_point; + +int FindCoffSymbolIndex(TCCState * s1, const char *func_name); +int nb_syms; + +typedef struct { + long tag; + long size; + long fileptr; + long nextsym; + short int dummy; +} AUXFUNC; + +typedef struct { + long regmask; + unsigned short lineno; + unsigned short nentries; + int localframe; + int nextentry; + short int dummy; +} AUXBF; + +typedef struct { + long dummy; + unsigned short lineno; + unsigned short dummy1; + int dummy2; + int dummy3; + unsigned short dummy4; +} AUXEF; + +ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) +{ + Section *tcc_sect; + SCNHDR *coff_sec; + int file_pointer; + char *Coff_str_table, *pCoff_str_table; + int CoffTextSectionNo, coff_nb_syms; + FILHDR file_hdr; /* FILE HEADER STRUCTURE */ + Section *stext, *sdata, *sbss; + int i, NSectionsToOutput = 0; + + Coff_str_table = pCoff_str_table = NULL; + + stext = FindSection(s1, ".text"); + sdata = FindSection(s1, ".data"); + sbss = FindSection(s1, ".bss"); + + nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); + coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1"); + + file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ + file_hdr.f_timdat = 0; /* time & date stamp */ + file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ + file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ + file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ + + o_filehdr.magic = 0x0108; /* see magic.h */ + o_filehdr.vstamp = 0x0190; /* version stamp */ + o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */ + o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ + o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ + o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ + o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ + o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ + + + // create all the section headers + + file_pointer = FILHSZ + sizeof(AOUTHDR); + + CoffTextSectionNo = -1; + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + NSectionsToOutput++; + + if (CoffTextSectionNo == -1 && tcc_sect == stext) + CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is + + strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ + + coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */ + coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */ + coff_sec->s_size = tcc_sect->data_offset; /* section size */ + coff_sec->s_scnptr = 0; /* file ptr to raw data for section */ + coff_sec->s_relptr = 0; /* file ptr to relocation */ + coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */ + coff_sec->s_nreloc = 0; /* number of relocation entries */ + coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */ + coff_sec->s_reserved = 0; /* reserved byte */ + coff_sec->s_page = 0; /* memory page id */ + + file_pointer += sizeof(SCNHDR); + } + } + + file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ + + // now loop through and determine file pointer locations + // for the raw data + + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + // put raw data + coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */ + file_pointer += coff_sec->s_size; + } + } + + // now loop through and determine file pointer locations + // for the relocation data + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + // put relocations data + if (coff_sec->s_nreloc > 0) { + coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ + file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); + } + } + } + + // now loop through and determine file pointer locations + // for the line number data + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + coff_sec->s_nlnno = 0; + coff_sec->s_lnnoptr = 0; + + if (s1->do_debug && tcc_sect == stext) { + // count how many line nos data + + // also find association between source file name and function + // so we can sort the symbol table + + + Stab_Sym *sym, *sym_end; + char func_name[MAX_FUNC_NAME_LENGTH], + last_func_name[MAX_FUNC_NAME_LENGTH]; + unsigned long func_addr, last_pc, pc; + const char *incl_files[INCLUDE_STACK_SIZE]; + int incl_index, len, last_line_num; + const char *str, *p; + + coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */ + + + func_name[0] = '\0'; + func_addr = 0; + incl_index = 0; + last_func_name[0] = '\0'; + last_pc = 0xffffffff; + last_line_num = 1; + sym = (Stab_Sym *) stab_section->data + 1; + sym_end = + (Stab_Sym *) (stab_section->data + + stab_section->data_offset); + + nFuncs = 0; + while (sym < sym_end) { + switch (sym->n_type) { + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { + // end of function + + coff_sec->s_nlnno++; + file_pointer += LINESZ; + + pc = sym->n_value + func_addr; + func_name[0] = '\0'; + func_addr = 0; + EndAddress[nFuncs] = pc; + FuncEntries[nFuncs] = + (file_pointer - + LineNoFilePtr[nFuncs]) / LINESZ - 1; + LastLineNo[nFuncs++] = last_line_num + 1; + } else { + // beginning of function + + LineNoFilePtr[nFuncs] = file_pointer; + coff_sec->s_nlnno++; + file_pointer += LINESZ; + + str = + (const char *) stabstr_section->data + + sym->n_strx; + + p = strchr(str, ':'); + if (!p) { + pstrcpy(func_name, sizeof(func_name), str); + pstrcpy(Func[nFuncs], sizeof(func_name), str); + } else { + len = p - str; + if (len > sizeof(func_name) - 1) + len = sizeof(func_name) - 1; + memcpy(func_name, str, len); + memcpy(Func[nFuncs], str, len); + func_name[len] = '\0'; + } + + // save the file that it came in so we can sort later + pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), + incl_files[incl_index - 1]); + + func_addr = sym->n_value; + } + break; + + /* line number info */ + case N_SLINE: + pc = sym->n_value + func_addr; + + last_pc = pc; + last_line_num = sym->n_desc; + + /* XXX: slow! */ + strcpy(last_func_name, func_name); + + coff_sec->s_nlnno++; + file_pointer += LINESZ; + break; + /* include files */ + case N_BINCL: + str = + (const char *) stabstr_section->data + sym->n_strx; + add_incl: + if (incl_index < INCLUDE_STACK_SIZE) { + incl_files[incl_index++] = str; + } + break; + case N_EINCL: + if (incl_index > 1) + incl_index--; + break; + case N_SO: + if (sym->n_strx == 0) { + incl_index = 0; /* end of translation unit */ + } else { + str = + (const char *) stabstr_section->data + + sym->n_strx; + /* do not add path */ + len = strlen(str); + if (len > 0 && str[len - 1] != '/') + goto add_incl; + } + break; + } + sym++; + } + } + + } + + file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ + + if (s1->do_debug) + file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */ + else + file_hdr.f_nsyms = 0; + + file_pointer += file_hdr.f_nsyms * SYMNMLEN; + + // OK now we are all set to write the file + + + fwrite(&file_hdr, FILHSZ, 1, f); + fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); + + // write section headers + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + fwrite(coff_sec, sizeof(SCNHDR), 1, f); + } + } + + // write raw data + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f); + } + } + + // write relocation data + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { + // put relocations data + if (coff_sec->s_nreloc > 0) { + fwrite(tcc_sect->reloc, + coff_sec->s_nreloc * sizeof(struct reloc), 1, f); + } + } + } + + + // group the symbols in order of filename, func1, func2, etc + // finally global symbols + + if (s1->do_debug) + SortSymbolTable(s1); + + // write line no data + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (s1->do_debug && tcc_sect == stext) { + // count how many line nos data + + + Stab_Sym *sym, *sym_end; + char func_name[128], last_func_name[128]; + unsigned long func_addr, last_pc, pc; + const char *incl_files[INCLUDE_STACK_SIZE]; + int incl_index, len, last_line_num; + const char *str, *p; + + LINENO CoffLineNo; + + func_name[0] = '\0'; + func_addr = 0; + incl_index = 0; + last_func_name[0] = '\0'; + last_pc = 0; + last_line_num = 1; + sym = (Stab_Sym *) stab_section->data + 1; + sym_end = + (Stab_Sym *) (stab_section->data + + stab_section->data_offset); + + while (sym < sym_end) { + switch (sym->n_type) { + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { + // end of function + + CoffLineNo.l_addr.l_paddr = last_pc; + CoffLineNo.l_lnno = last_line_num + 1; + fwrite(&CoffLineNo, 6, 1, f); + + pc = sym->n_value + func_addr; + func_name[0] = '\0'; + func_addr = 0; + } else { + // beginning of function + + str = + (const char *) stabstr_section->data + + sym->n_strx; + + + p = strchr(str, ':'); + if (!p) { + pstrcpy(func_name, sizeof(func_name), str); + } else { + len = p - str; + if (len > sizeof(func_name) - 1) + len = sizeof(func_name) - 1; + memcpy(func_name, str, len); + func_name[len] = '\0'; + } + func_addr = sym->n_value; + last_pc = func_addr; + last_line_num = -1; + + // output a function begin + + CoffLineNo.l_addr.l_symndx = + FindCoffSymbolIndex(s1, func_name); + CoffLineNo.l_lnno = 0; + + fwrite(&CoffLineNo, 6, 1, f); + } + break; + + /* line number info */ + case N_SLINE: + pc = sym->n_value + func_addr; + + + /* XXX: slow! */ + strcpy(last_func_name, func_name); + + // output a line reference + + CoffLineNo.l_addr.l_paddr = last_pc; + + if (last_line_num == -1) { + CoffLineNo.l_lnno = sym->n_desc; + } else { + CoffLineNo.l_lnno = last_line_num + 1; + } + + fwrite(&CoffLineNo, 6, 1, f); + + last_pc = pc; + last_line_num = sym->n_desc; + + break; + + /* include files */ + case N_BINCL: + str = + (const char *) stabstr_section->data + sym->n_strx; + add_incl2: + if (incl_index < INCLUDE_STACK_SIZE) { + incl_files[incl_index++] = str; + } + break; + case N_EINCL: + if (incl_index > 1) + incl_index--; + break; + case N_SO: + if (sym->n_strx == 0) { + incl_index = 0; /* end of translation unit */ + } else { + str = + (const char *) stabstr_section->data + + sym->n_strx; + /* do not add path */ + len = strlen(str); + if (len > 0 && str[len - 1] != '/') + goto add_incl2; + } + break; + } + sym++; + } + } + } + + // write symbol table + if (s1->do_debug) { + int k; + struct syment csym; + AUXFUNC auxfunc; + AUXBF auxbf; + AUXEF auxef; + int i; + Elf32_Sym *p; + const char *name; + int nstr; + int n = 0; + + Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE); + pCoff_str_table = Coff_str_table; + nstr = 0; + + p = (Elf32_Sym *) symtab_section->data; + + + for (i = 0; i < nb_syms; i++) { + + name = symtab_section->link->data + p->st_name; + + for (k = 0; k < 8; k++) + csym._n._n_name[k] = 0; + + if (strlen(name) <= 8) { + strcpy(csym._n._n_name, name); + } else { + if (pCoff_str_table - Coff_str_table + strlen(name) > + MAX_STR_TABLE - 1) + tcc_error("String table too large"); + + csym._n._n_n._n_zeroes = 0; + csym._n._n_n._n_offset = + pCoff_str_table - Coff_str_table + 4; + + strcpy(pCoff_str_table, name); + pCoff_str_table += strlen(name) + 1; // skip over null + nstr++; + } + + if (p->st_info == 4) { + // put a filename symbol + csym.n_value = 33; // ????? + csym.n_scnum = N_DEBUG; + csym.n_type = 0; + csym.n_sclass = C_FILE; + csym.n_numaux = 0; + fwrite(&csym, 18, 1, f); + n++; + + } else if (p->st_info == 0x12) { + // find the function data + + for (k = 0; k < nFuncs; k++) { + if (strcmp(name, Func[k]) == 0) + break; + } + + if (k >= nFuncs) { + tcc_error("debug info can't find function: %s", name); + } + // put a Function Name + + csym.n_value = p->st_value; // physical address + csym.n_scnum = CoffTextSectionNo; + csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); + csym.n_sclass = C_EXT; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + // now put aux info + + auxfunc.tag = 0; + auxfunc.size = EndAddress[k] - p->st_value; + auxfunc.fileptr = LineNoFilePtr[k]; + auxfunc.nextsym = n + 6; // tktk + auxfunc.dummy = 0; + fwrite(&auxfunc, 18, 1, f); + + // put a .bf + + strcpy(csym._n._n_name, ".bf"); + csym.n_value = p->st_value; // physical address + csym.n_scnum = CoffTextSectionNo; + csym.n_type = 0; + csym.n_sclass = C_FCN; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + // now put aux info + + auxbf.regmask = 0; + auxbf.lineno = 0; + auxbf.nentries = FuncEntries[k]; + auxbf.localframe = 0; + auxbf.nextentry = n + 6; + auxbf.dummy = 0; + fwrite(&auxbf, 18, 1, f); + + // put a .ef + + strcpy(csym._n._n_name, ".ef"); + csym.n_value = EndAddress[k]; // physical address + csym.n_scnum = CoffTextSectionNo; + csym.n_type = 0; + csym.n_sclass = C_FCN; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + // now put aux info + + auxef.dummy = 0; + auxef.lineno = LastLineNo[k]; + auxef.dummy1 = 0; + auxef.dummy2 = 0; + auxef.dummy3 = 0; + auxef.dummy4 = 0; + fwrite(&auxef, 18, 1, f); + + n += 6; + + } else { + // try an put some type info + + if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { + csym.n_type = T_DOUBLE; // int + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { + csym.n_type = T_FLOAT; + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_INT) { + csym.n_type = T_INT; // int + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { + csym.n_type = T_SHORT; + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_BYTE) { + csym.n_type = T_CHAR; + csym.n_sclass = C_EXT; + } else { + csym.n_type = T_INT; // just mark as a label + csym.n_sclass = C_LABEL; + } + + + csym.n_value = p->st_value; + csym.n_scnum = 2; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + + auxfunc.tag = 0; + auxfunc.size = 0x20; + auxfunc.fileptr = 0; + auxfunc.nextsym = 0; + auxfunc.dummy = 0; + fwrite(&auxfunc, 18, 1, f); + n++; + n++; + + } + + p++; + } + } + + if (s1->do_debug) { + // write string table + + // first write the size + i = pCoff_str_table - Coff_str_table; + fwrite(&i, 4, 1, f); + + // then write the strings + fwrite(Coff_str_table, i, 1, f); + + tcc_free(Coff_str_table); + } + + return 0; +} + + + +// group the symbols in order of filename, func1, func2, etc +// finally global symbols + +void SortSymbolTable(TCCState *s1) +{ + int i, j, k, n = 0; + Elf32_Sym *p, *p2, *NewTable; + char *name, *name2; + + NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym)); + + p = (Elf32_Sym *) symtab_section->data; + + + // find a file symbol, copy it over + // then scan the whole symbol list and copy any function + // symbols that match the file association + + for (i = 0; i < nb_syms; i++) { + if (p->st_info == 4) { + name = (char *) symtab_section->link->data + p->st_name; + + // this is a file symbol, copy it over + + NewTable[n++] = *p; + + p2 = (Elf32_Sym *) symtab_section->data; + + for (j = 0; j < nb_syms; j++) { + if (p2->st_info == 0x12) { + // this is a func symbol + + name2 = + (char *) symtab_section->link->data + p2->st_name; + + // find the function data index + + for (k = 0; k < nFuncs; k++) { + if (strcmp(name2, Func[k]) == 0) + break; + } + + if (k >= nFuncs) { + tcc_error("debug (sort) info can't find function: %s", name2); + } + + if (strcmp(AssociatedFile[k], name) == 0) { + // yes they match copy it over + + NewTable[n++] = *p2; + } + } + p2++; + } + } + p++; + } + + // now all the filename and func symbols should have been copied over + // copy all the rest over (all except file and funcs) + + p = (Elf32_Sym *) symtab_section->data; + for (i = 0; i < nb_syms; i++) { + if (p->st_info != 4 && p->st_info != 0x12) { + NewTable[n++] = *p; + } + p++; + } + + if (n != nb_syms) + tcc_error("Internal Compiler error, debug info"); + + // copy it all back + + p = (Elf32_Sym *) symtab_section->data; + for (i = 0; i < nb_syms; i++) { + *p++ = NewTable[i]; + } + + tcc_free(NewTable); +} + + +int FindCoffSymbolIndex(TCCState *s1, const char *func_name) +{ + int i, n = 0; + Elf32_Sym *p; + char *name; + + p = (Elf32_Sym *) symtab_section->data; + + for (i = 0; i < nb_syms; i++) { + + name = (char *) symtab_section->link->data + p->st_name; + + if (p->st_info == 4) { + // put a filename symbol + n++; + } else if (p->st_info == 0x12) { + + if (strcmp(func_name, name) == 0) + return n; + + n += 6; + + // put a Function Name + + // now put aux info + + // put a .bf + + // now put aux info + + // put a .ef + + // now put aux info + + } else { + n += 2; + } + + p++; + } + + return n; // total number of symbols +} + +int OutputTheSection(Section * sect) +{ + const char *s = sect->name; + + if (!strcmp(s, ".text")) + return 1; + else if (!strcmp(s, ".data")) + return 1; + else + return 0; +} + +short int GetCoffFlags(const char *s) +{ + if (!strcmp(s, ".text")) + return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400; + else if (!strcmp(s, ".data")) + return STYP_DATA; + else if (!strcmp(s, ".bss")) + return STYP_BSS; + else if (!strcmp(s, ".stack")) + return STYP_BSS | STYP_ALIGN | 0x200; + else if (!strcmp(s, ".cinit")) + return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200; + else + return 0; +} + +Section *FindSection(TCCState * s1, const char *sname) +{ + Section *s; + int i; + + for (i = 1; i < s1->nb_sections; i++) { + s = s1->sections[i]; + + if (!strcmp(sname, s->name)) + return s; + } + + tcc_error("could not find section %s", sname); + return 0; +} + +ST_FUNC int tcc_load_coff(TCCState * s1, int fd) +{ +// tktk TokenSym *ts; + + FILE *f; + unsigned int str_size; + char *Coff_str_table, *name; + int i, k; + struct syment csym; + char name2[9]; + FILHDR file_hdr; /* FILE HEADER STRUCTURE */ + + f = fdopen(fd, "rb"); + if (!f) { + tcc_error("Unable to open .out file for input"); + } + + if (fread(&file_hdr, FILHSZ, 1, f) != 1) + tcc_error("error reading .out file for input"); + + if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) + tcc_error("error reading .out file for input"); + + // first read the string table + + if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) + tcc_error("error reading .out file for input"); + + if (fread(&str_size, sizeof(int), 1, f) != 1) + tcc_error("error reading .out file for input"); + + + Coff_str_table = (char *) tcc_malloc(str_size); + + if (fread(Coff_str_table, str_size - 4, 1, f) != 1) + tcc_error("error reading .out file for input"); + + // read/process all the symbols + + // seek back to symbols + + if (fseek(f, file_hdr.f_symptr, SEEK_SET)) + tcc_error("error reading .out file for input"); + + for (i = 0; i < file_hdr.f_nsyms; i++) { + if (fread(&csym, SYMESZ, 1, f) != 1) + tcc_error("error reading .out file for input"); + + if (csym._n._n_n._n_zeroes == 0) { + name = Coff_str_table + csym._n._n_n._n_offset - 4; + } else { + name = csym._n._n_name; + + if (name[7] != 0) { + for (k = 0; k < 8; k++) + name2[k] = name[k]; + + name2[8] = 0; + + name = name2; + } + } +// if (strcmp("_DAC_Buffer",name)==0) // tktk +// name[0]=0; + + if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures + (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure + (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles + (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats + { + // strip off any leading underscore (except for other main routine) + + if (name[0] == '_' && strcmp(name, "_main") != 0) + name++; + + tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value); + } + // skip any aux records + + if (csym.n_numaux == 1) { + if (fread(&csym, SYMESZ, 1, f) != 1) + tcc_error("error reading .out file for input"); + i++; + } + } + + return 0; +} diff --git a/tccelf.c b/libtcc/tccelf.c similarity index 86% rename from tccelf.c rename to libtcc/tccelf.c index c9286aa2..7fe67098 100644 --- a/tccelf.c +++ b/libtcc/tccelf.c @@ -19,6 +19,7 @@ */ #include "tcc.h" +#include "utils/string.h" /* Define this to get some debug output during relocation processing. */ #undef DEBUG_RELOC @@ -84,26 +85,6 @@ ST_FUNC void tccelf_new(TCCState *s) ".dynhashtab", SHF_PRIVATE); get_sym_attr(s, 0, 1); - if (s->do_debug) { - /* add debug sections */ - tcc_debug_new(s); - } - -#if TCC_EH_FRAME - if (s->output_format != TCC_OUTPUT_FORMAT_ELF) - s->unwind_tables = 0; - tcc_eh_frame_start(s); -#endif - -#ifdef CONFIG_TCC_BCHECK - if (s->do_bounds_check) { - /* if bound checking, then add corresponding sections */ - /* (make ro after relocation done with GNU_RELRO) */ - bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO); - lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO); - } -#endif - #ifdef TCC_TARGET_PE /* to make sure that -ltcc1 -Wl,-e,_start will grab the startup code from libtcc1.a (unless _start defined) */ @@ -158,10 +139,6 @@ ST_FUNC void tccelf_begin_file(TCCState *s1) } /* disable symbol hashing during compilation */ s = s1->symtab, s->reloc = s->hash, s->hash = NULL; -#if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE - s1->uw_sym = 0; - s1->uw_offs = 0; -#endif } static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym); @@ -520,7 +497,7 @@ ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc) } /* return elf symbol value */ -LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name) +void *tcc_get_symbol(TCCState *s, const char *name) { addr_t addr = get_sym_addr(s, name, 0, 1); return addr == -1 ? NULL : (void*)(uintptr_t)addr; @@ -551,7 +528,7 @@ ST_FUNC void list_elf_symbols(TCCState *s, void *ctx, } /* list elf symbol names and values */ -LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, +void tcc_list_symbols(TCCState *s, void *ctx, void (*symbol_cb)(void *ctx, const char *name, const void *val)) { list_elf_symbols(s, ctx, symbol_cb); @@ -1056,25 +1033,6 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve) name = (char *) s1->symtab->link->data + sym->st_name; /* Use ld.so to resolve symbol for us (for tcc -run) */ if (do_resolve) { -#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE - /* dlsym() needs the undecorated name. */ - void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]); -#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID - if (addr == NULL) { - int i; - for (i = 0; i < s1->nb_loaded_dlls; i++) - if ((addr = dlsym(s1->loaded_dlls[i]->handle, name))) - break; - } -#endif - if (addr) { - sym->st_value = (addr_t) addr; -#ifdef DEBUG_RELOC - printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); -#endif - goto found; - } -#endif /* if dynamic symbol exist, it will be used in relocate_section */ } else if (s1->dynsym && find_elf_sym(s1->dynsym, name)) goto found; @@ -1107,7 +1065,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) int type, sym_index; unsigned char *ptr; addr_t tgt, addr; - int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi; qrel = (ElfW_Rel *)sr->data; for_each_elem(sr, 0, rel, ElfW_Rel) { @@ -1119,12 +1076,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) #if SHT_RELX == SHT_RELA tgt += rel->r_addend; #endif - if (is_dwarf && type == R_DATA_32DW - && sym->st_shndx >= s1->dwlo && sym->st_shndx < s1->dwhi) { - /* dwarf section relocation to each other */ - add32le(ptr, tgt - s1->sections[sym->st_shndx]->sh_addr); - continue; - } addr = s->sh_addr + rel->r_offset; relocate(s1, rel, type, ptr, addr, tgt); } @@ -1132,17 +1083,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) /* if the relocation is allocated, we change its symbol table */ if (sr->sh_flags & SHF_ALLOC) { sr->link = s1->dynsym; - if (s1->output_type & TCC_OUTPUT_DYN) { - size_t r = (uint8_t*)qrel - sr->data; - if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE - && 0 == strcmp(s->name, ".stab")) - r = 0; /* cannot apply 64bit relocation to 32bit value */ - sr->data_offset = sr->sh_size = r; -#ifdef CONFIG_TCC_PIE - if (r && (s->sh_flags & SHF_EXECINSTR)) - tcc_warning("%d relocations to %s", (unsigned)(r / sizeof *qrel), s->name); -#endif - } } #endif } @@ -1158,11 +1098,9 @@ ST_FUNC void relocate_sections(TCCState *s1) if (sr->sh_type != SHT_RELX) continue; s = s1->sections[sr->sh_info]; -#ifndef TCC_TARGET_MACHO if (s != s1->got || s1->static_link || s1->output_type == TCC_OUTPUT_MEMORY) -#endif { relocate_section(s1, s, sr); } @@ -1183,15 +1121,13 @@ ST_FUNC void relocate_sections(TCCState *s1) static int prepare_dynamic_rel(TCCState *s1, Section *sr) { int count = 0; -#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \ - defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64) || \ - defined(TCC_TARGET_RISCV64) + ElfW_Rel *rel; for_each_elem(sr, 0, rel, ElfW_Rel) { int sym_index = ELFW(R_SYM)(rel->r_info); int type = ELFW(R_TYPE)(rel->r_info); switch(type) { -#if defined(TCC_TARGET_I386) + case R_386_32: if (!get_sym_attr(s1, sym_index, 0)->dyn_index && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) { @@ -1199,42 +1135,9 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE); break; } -#elif defined(TCC_TARGET_X86_64) - case R_X86_64_32: - case R_X86_64_32S: - case R_X86_64_64: -#elif defined(TCC_TARGET_ARM) - case R_ARM_ABS32: - case R_ARM_TARGET1: -#elif defined(TCC_TARGET_ARM64) - case R_AARCH64_ABS32: - case R_AARCH64_ABS64: -#elif defined(TCC_TARGET_RISCV64) - case R_RISCV_32: - case R_RISCV_64: -#endif count++; break; -#if defined(TCC_TARGET_I386) case R_386_PC32: -#elif defined(TCC_TARGET_X86_64) - case R_X86_64_PC32: - { - ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - /* Hidden defined symbols can and must be resolved locally. - We're misusing a PLT32 reloc for this, as that's always - resolved to its address even in shared libs. */ - if (sym->st_shndx != SHN_UNDEF && - ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) { - rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32); - break; - } - } -#elif defined(TCC_TARGET_ARM64) - case R_AARCH64_PREL32: -#endif - if (s1->output_type != TCC_OUTPUT_DLL) - break; if (get_sym_attr(s1, sym_index, 0)->dyn_index) count++; break; @@ -1242,7 +1145,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) break; } } -#endif + return count; } #endif @@ -1399,9 +1302,7 @@ redo: if (sym->st_shndx == SHN_UNDEF) { ElfW(Sym) *esym; int dynindex; - if (!PCRELATIVE_DLLPLT - && (s1->output_type & TCC_OUTPUT_DYN)) - continue; + /* Relocations for UNDEF symbols would normally need to be transferred into the executable or shared object. If that were done AUTO_GOTPLT_ENTRY wouldn't exist. @@ -1425,28 +1326,14 @@ redo: } else if (sym->st_shndx == SHN_ABS) { if (sym->st_value == 0) /* from tcc_add_btstub() */ continue; -#ifndef TCC_TARGET_ARM if (PTR_SIZE != 8) continue; -#endif /* from tcc_add_symbol(): on 64 bit platforms these need to go through .got */ } else continue; } -#ifdef TCC_TARGET_X86_64 - if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) && - sym->st_shndx != SHN_UNDEF && - (ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT || - ELFW(ST_BIND)(sym->st_info) == STB_LOCAL || - s1->output_type & TCC_OUTPUT_EXE)) { - if (pass != 0) - continue; - rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); - continue; - } -#endif reloc_type = code_reloc(type); if (reloc_type == -1) { tcc_error_noabort ("Unknown relocation type: %d", type); @@ -1523,15 +1410,6 @@ ST_FUNC void add_array (TCCState *s1, const char *sec, int c) section_ptr_add(s, PTR_SIZE); } -#ifdef CONFIG_TCC_BCHECK -ST_FUNC void tcc_add_bcheck(TCCState *s1) -{ - if (0 == s1->do_bounds_check) - return; - section_ptr_add(bounds_section, sizeof(addr_t)); -} -#endif - /* set symbol to STB_LOCAL and resolve. The point is to not export it as a dynamic symbol to allow so's to have one each with a different value. */ static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset) @@ -1548,209 +1426,23 @@ static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset /* avoid generating debug/test_coverage code for stub functions */ static void tcc_compile_string_no_debug(TCCState *s, const char *str) { - int save_do_debug = s->do_debug; - int save_test_coverage = s->test_coverage; - - s->do_debug = 0; - s->test_coverage = 0; tcc_compile_string(s, str); - s->do_debug = save_do_debug; - s->test_coverage = save_test_coverage; } -#ifdef CONFIG_TCC_BACKTRACE -static void put_ptr(TCCState *s1, Section *s, int offs) -{ - int c; - c = set_global_sym(s1, NULL, s, offs); - s = data_section; - put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c); - section_ptr_add(s, PTR_SIZE); -} -ST_FUNC void tcc_add_btstub(TCCState *s1) -{ - Section *s; - int n, o, *p; - CString cstr; - const char *__rt_info = &"___rt_info"[!s1->leading_underscore]; - - s = data_section; - /* Align to PTR_SIZE */ - section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1)); - o = s->data_offset; - /* create a struct rt_context (see tccrun.c) */ - if (s1->dwarf) { - put_ptr(s1, dwarf_line_section, 0); - put_ptr(s1, dwarf_line_section, -1); - if (s1->dwarf >= 5) - put_ptr(s1, dwarf_line_str_section, 0); - else - put_ptr(s1, dwarf_str_section, 0); - } - else - { - put_ptr(s1, stab_section, 0); - put_ptr(s1, stab_section, -1); - put_ptr(s1, stab_section->link, 0); - } - - /* skip esym_start/esym_end/elf_str (not loaded) */ - section_ptr_add(s, 3 * PTR_SIZE); - - if (s1->output_type == TCC_OUTPUT_MEMORY && 0 == s1->dwarf) { - put_ptr(s1, text_section, 0); - } else { - /* prog_base : local nameless symbol with offset 0 at SHN_ABS */ - put_ptr(s1, NULL, 0); -#if defined TCC_TARGET_MACHO - /* adjust for __PAGEZERO */ - if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE) - write64le(data_section->data + data_section->data_offset - PTR_SIZE, - (uint64_t)1 << 32); -#endif - } - n = 3 * PTR_SIZE; -#ifdef CONFIG_TCC_BCHECK - if (s1->do_bounds_check) { - put_ptr(s1, bounds_section, 0); - n -= PTR_SIZE; - } -#endif - section_ptr_add(s, n); - p = section_ptr_add(s, 2 * sizeof (int)); - p[0] = s1->rt_num_callers; - p[1] = s1->dwarf; - // if (s->data_offset - o != 10*PTR_SIZE + 2*sizeof (int)) exit(99); - - if (s1->output_type == TCC_OUTPUT_MEMORY) { - set_global_sym(s1, __rt_info, s, o); - return; - } - - cstr_new(&cstr); - cstr_printf(&cstr, - "extern void __bt_init(),__bt_exit(),__bt_init_dll();" - "static void *__rt_info[];" - "__attribute__((constructor)) static void __bt_init_rt(){"); -#ifdef TCC_TARGET_PE - if (s1->output_type == TCC_OUTPUT_DLL) -#ifdef CONFIG_TCC_BCHECK - cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check); -#else - cstr_printf(&cstr, "__bt_init_dll(0);"); -#endif -#endif - cstr_printf(&cstr, "__bt_init(__rt_info,%d);}", - s1->output_type != TCC_OUTPUT_DLL); - /* In case dlcose is called by application */ - cstr_printf(&cstr, - "__attribute__((destructor)) static void __bt_exit_rt(){" - "__bt_exit(__rt_info);}"); - tcc_compile_string_no_debug(s1, cstr.data); - cstr_free(&cstr); - set_local_sym(s1, __rt_info, s, o); -} -#endif /* def CONFIG_TCC_BACKTRACE */ - -static void tcc_tcov_add_file(TCCState *s1, const char *filename) -{ - CString cstr; - void *ptr; - char wd[1024]; - - if (tcov_section == NULL) - return; - section_ptr_add(tcov_section, 1); - write32le (tcov_section->data, tcov_section->data_offset); - - cstr_new (&cstr); - if (filename[0] == '/') - cstr_printf (&cstr, "%s.tcov", filename); - else { - getcwd (wd, sizeof(wd)); - cstr_printf (&cstr, "%s/%s.tcov", wd, filename); - } - ptr = section_ptr_add(tcov_section, cstr.size + 1); - strcpy((char *)ptr, cstr.data); - unlink((char *)ptr); -#ifdef _WIN32 - normalize_slashes((char *)ptr); -#endif - cstr_free (&cstr); - - cstr_new(&cstr); - cstr_printf(&cstr, - "extern char *__tcov_data[];" - "extern void __store_test_coverage ();" - "__attribute__((destructor)) static void __tcov_exit() {" - "__store_test_coverage(__tcov_data);" - "}"); - tcc_compile_string_no_debug(s1, cstr.data); - cstr_free(&cstr); - set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0); -} - -#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO +#if !defined TCC_TARGET_PE /* add libc crt1/crti objects */ ST_FUNC void tccelf_add_crtbegin(TCCState *s1) { -#if TARGETOS_OpenBSD - if (s1->output_type != TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crt0.o"); - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crtbeginS.o"); - else - tcc_add_crt(s1, "crtbegin.o"); -#elif TARGETOS_FreeBSD || TARGETOS_NetBSD - if (s1->output_type != TCC_OUTPUT_DLL) -#if TARGETOS_FreeBSD - tcc_add_crt(s1, "crt1.o"); -#else - tcc_add_crt(s1, "crt0.o"); -#endif + tcc_add_crt(s1, "crt1.o"); tcc_add_crt(s1, "crti.o"); - if (s1->static_link) - tcc_add_crt(s1, "crtbeginT.o"); - else if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crtbeginS.o"); - else - tcc_add_crt(s1, "crtbegin.o"); -#elif TARGETOS_ANDROID - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crtbegin_so.o"); - else - tcc_add_crt(s1, "crtbegin_dynamic.o"); -#else - if (s1->output_type != TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crt1.o"); - tcc_add_crt(s1, "crti.o"); -#endif } ST_FUNC void tccelf_add_crtend(TCCState *s1) { -#if TARGETOS_OpenBSD - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crtendS.o"); - else - tcc_add_crt(s1, "crtend.o"); -#elif TARGETOS_FreeBSD || TARGETOS_NetBSD - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crtendS.o"); - else - tcc_add_crt(s1, "crtend.o"); tcc_add_crt(s1, "crtn.o"); -#elif TARGETOS_ANDROID - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_crt(s1, "crtend_so.o"); - else - tcc_add_crt(s1, "crtend_android.o"); -#else - tcc_add_crt(s1, "crtn.o"); -#endif } -#endif /* !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO */ +#endif /* !defined TCC_TARGET_PE */ #ifndef TCC_TARGET_PE /* add tcc runtime libraries */ @@ -1758,34 +1450,12 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) { s1->filetype = 0; -#ifdef CONFIG_TCC_BCHECK - tcc_add_bcheck(s1); -#endif tcc_add_pragma_libs(s1); /* add libc */ if (!s1->nostdlib) { int lpthread = s1->option_pthread; -#ifdef CONFIG_TCC_BCHECK - if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) { - tcc_add_support(s1, "bcheck.o"); -# if !(TARGETOS_OpenBSD || TARGETOS_NetBSD) - tcc_add_library(s1, "dl"); -# endif - lpthread = 1; - } -#endif -#ifdef CONFIG_TCC_BACKTRACE - if (s1->do_backtrace) { - if (s1->output_type & TCC_OUTPUT_EXE) - tcc_add_support(s1, "bt-exe.o"); - if (s1->output_type != TCC_OUTPUT_DLL) - tcc_add_support(s1, "bt-log.o"); - tcc_add_btstub(s1); - lpthread = 1; - } -#endif if (lpthread) tcc_add_library(s1, "pthread"); tcc_add_library(s1, "c"); @@ -1797,15 +1467,11 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR); } #endif -#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD - tcc_add_library(s1, "gcc_s"); // unwind code -#endif + if (TCC_LIBTCC1[0]) tcc_add_support(s1, TCC_LIBTCC1); -#ifndef TCC_TARGET_MACHO if (s1->output_type != TCC_OUTPUT_MEMORY) tccelf_add_crtend(s1); -#endif } } #endif /* ndef TCC_TARGET_PE */ @@ -1822,13 +1488,7 @@ static void tcc_add_linker_symbols(TCCState *s1) set_global_sym(s1, "_etext", text_section, -1); set_global_sym(s1, "_edata", data_section, -1); set_global_sym(s1, "_end", bss_section, -1); -#if TARGETOS_OpenBSD - set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR); -#endif -#ifdef TCC_TARGET_RISCV64 - /* XXX should be .sdata+0x800, not .data+0x800 */ - set_global_sym(s1, "__global_pointer$", data_section, 0x800); -#endif + /* horrible new standard ldscript defines */ add_init_array_defines(s1, ".preinit_array"); add_init_array_defines(s1, ".init_array"); @@ -2097,33 +1757,10 @@ static int set_sec_sizes(TCCState *s1) if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) { /* when generating a DLL, we include relocations but we may patch them */ - if ((file_type & TCC_OUTPUT_DYN) - && (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) { - int count = prepare_dynamic_rel(s1, s); - if (count) { - /* allocate the section */ - s->sh_flags |= SHF_ALLOC; - s->sh_size = count * sizeof(ElfW_Rel); - if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) - textrel += count; - } - } - } else if ((s->sh_flags & SHF_ALLOC) -#ifdef TCC_TARGET_ARM - || s->sh_type == SHT_ARM_ATTRIBUTES -#endif - || s1->do_debug) { + } else if ((s->sh_flags & SHF_ALLOC)) { s->sh_size = s->data_offset; } -#ifdef TCC_TARGET_ARM - /* XXX: Suppress stack unwinding section. */ - if (s->sh_type == SHT_ARM_EXIDX) { - s->sh_flags = 0; - s->sh_size = 0; - } -#endif - } return textrel; } @@ -2313,8 +1950,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) s_align = s1->section_align; addr = ELF_START_ADDR; - if (s1->output_type & TCC_OUTPUT_DYN) - addr = 0; if (s1->has_text_addr) { addr = s1->text_addr; @@ -2509,8 +2144,6 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) if (s && s->data_offset) { put_dt(dynamic, DT_FINI, s->sh_addr); } - if (s1->do_debug) - put_dt(dynamic, DT_DEBUG, 0); put_dt(dynamic, DT_NULL, 0); } @@ -2574,26 +2207,10 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr) ehdr.e_ident[5] = ELFDATA2LSB; ehdr.e_ident[6] = EV_CURRENT; -#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel - ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; -#elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI - ehdr.e_flags = EF_ARM_EABI_VER5; - ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT - ? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT; -#elif defined TCC_TARGET_ARM - ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; -#elif defined TCC_TARGET_RISCV64 - /* XXX should be configurable */ - ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE; -#endif - if (file_type == TCC_OUTPUT_OBJ) { ehdr.e_type = ET_REL; } else { - if (file_type & TCC_OUTPUT_DYN) - ehdr.e_type = ET_DYN; - else - ehdr.e_type = ET_EXEC; + ehdr.e_type = ET_EXEC; if (s1->elf_entryname) ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0); else @@ -2752,63 +2369,6 @@ static void reorder_sections(TCCState *s1, int *sec_order) tcc_free(backmap); } -#ifdef TCC_TARGET_ARM -static void create_arm_attribute_section(TCCState *s1) -{ - // Needed for DLL support. - static const unsigned char arm_attr[] = { - 0x41, // 'A' - 0x2c, 0x00, 0x00, 0x00, // size 0x2c - 'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi" - 0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22 - 0x05, 0x36, 0x00, // 'CPU_name', "6" - 0x06, 0x06, // 'CPU_arch', 'v6' - 0x08, 0x01, // 'ARM_ISA_use', 'Yes' - 0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1' - 0x0a, 0x02, // 'FP_arch', 'VFPv2' - 0x12, 0x04, // 'ABI_PCS_wchar_t', 4 - 0x14, 0x01, // 'ABI_FP_denormal', 'Needed' - 0x15, 0x01, // 'ABI_FP_exceptions', 'Needed' - 0x17, 0x03, // 'ABI_FP_number_model', 'IEEE 754' - 0x18, 0x01, // 'ABI_align_needed', '8-byte' - 0x19, 0x01, // 'ABI_align_preserved', '8-byte, except leaf SP' - 0x1a, 0x02, // 'ABI_enum_size', 'int' - 0x1c, 0x01, // 'ABI_VFP_args', 'VFP registers' - 0x22, 0x01 // 'CPU_unaligned_access', 'v6' - }; - Section *attr = new_section(s1, ".ARM.attributes", SHT_ARM_ATTRIBUTES, 0); - unsigned char *ptr = section_ptr_add(attr, sizeof(arm_attr)); - attr->sh_addralign = 1; - memcpy(ptr, arm_attr, sizeof(arm_attr)); - if (s1->float_abi != ARM_HARD_FLOAT) { - ptr[26] = 0x00; // 'FP_arch', 'No' - ptr[41] = 0x1e; // 'ABI_optimization_goals' - ptr[42] = 0x06; // 'Aggressive Debug' - } -} -#endif - -#if TARGETOS_OpenBSD || TARGETOS_NetBSD -static Section *create_bsd_note_section(TCCState *s1, - const char *name, - const char *value) -{ - Section *s = find_section (s1, name); - - if (s->data_offset == 0) { - char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4); - ElfW(Nhdr) *note = (ElfW(Nhdr) *) ptr; - - s->sh_type = SHT_NOTE; - note->n_namesz = 8; - note->n_descsz = 4; - note->n_type = ELF_NOTE_OS_GNU; - strcpy (ptr + sizeof(ElfW(Nhdr)), value); - } - return s; -} -#endif - static void alloc_sec_names(TCCState *s1, int is_obj); /* Output an elf, coff or binary file */ @@ -2827,21 +2387,6 @@ static int elf_output_file(TCCState *s1, const char *filename) sec_order = NULL; dyninf.roinf = &dyninf._roinf; -#ifdef TCC_TARGET_ARM - create_arm_attribute_section (s1); -#endif - -#if TARGETOS_OpenBSD - dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD"); -#endif - -#if TARGETOS_NetBSD - dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD"); -#endif - -#if TARGETOS_FreeBSD || TARGETOS_NetBSD - dyninf.roinf = NULL; -#endif /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ tcc_add_runtime(s1); resolve_common_syms(s1); @@ -2876,7 +2421,6 @@ static int elf_output_file(TCCState *s1, const char *filename) got_sym = build_got(s1); if (file_type & TCC_OUTPUT_EXE) { - bind_exe_dynsyms(s1, file_type & TCC_OUTPUT_DYN); if (s1->nb_errors) goto the_end; } @@ -2887,10 +2431,6 @@ static int elf_output_file(TCCState *s1, const char *filename) /* shared library case: simply export all global symbols */ export_global_syms(s1); } -#if TCC_EH_FRAME - /* fill with initial data */ - tcc_eh_frame_hdr(s1, 0); -#endif dyninf.gnu_hash = create_gnu_hash(s1); } else { build_got_entries(s1, 0); @@ -2912,16 +2452,6 @@ static int elf_output_file(TCCState *s1, const char *filename) put_elf_str(dynstr, s1->rpath)); dt_flags_1 = DF_1_NOW; - if (file_type & TCC_OUTPUT_DYN) { - if (s1->soname) - put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); - /* XXX: currently, since we do not handle PIC code, we - must relocate the readonly segments */ - if (textrel) - put_dt(dynamic, DT_TEXTREL, 0); - if (file_type & TCC_OUTPUT_EXE) - dt_flags_1 = DF_1_NOW | DF_1_PIE; - } put_dt(dynamic, DT_FLAGS, DF_BIND_NOW); put_dt(dynamic, DT_FLAGS_1, dt_flags_1); if (s1->symbolic) @@ -2946,8 +2476,7 @@ static int elf_output_file(TCCState *s1, const char *filename) if (dynamic) { /* put in GOT the dynamic section address and relocate PLT */ write32le(s1->got->data, dynamic->sh_addr); - if (file_type == TCC_OUTPUT_EXE - || (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN))) + if (file_type == TCC_OUTPUT_EXE) relocate_plt(s1); /* relocate symbols in .dynsym now that final addresses are known */ relocate_syms(s1, s1->dynsym, 2); @@ -2974,10 +2503,7 @@ static int elf_output_file(TCCState *s1, const char *filename) update_gnu_hash(s1, dyninf.gnu_hash); reorder_sections(s1, sec_order); -#if TCC_EH_FRAME - /* fill with final data */ - tcc_eh_frame_hdr(s1, 1); -#endif + /* Create the ELF file with name 'filename' */ ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr); the_end: @@ -3027,16 +2553,12 @@ static int elf_output_obj(TCCState *s1, const char *filename) return ret; } -LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) +int tcc_output_file(TCCState *s, const char *filename) { - if (s->test_coverage) - tcc_tcov_add_file(s, filename); if (s->output_type == TCC_OUTPUT_OBJ) return elf_output_obj(s, filename); #ifdef TCC_TARGET_PE return pe_output_file(s, filename); -#elif defined TCC_TARGET_MACHO - return macho_output_file(s, filename); #else return elf_output_file(s, filename); #endif @@ -3082,10 +2604,8 @@ ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h) } else if (size >= 8) { if (0 == memcmp(h, ARMAG, 8)) return AFF_BINTYPE_AR; -#ifdef TCC_TARGET_COFF - if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC) - return AFF_BINTYPE_C67; -#endif + else if (((FILHDR *)h)->f_magic == F_MACH_I386) + return (AFF_BINTYPE_COFF); } return 0; } @@ -3167,7 +2687,7 @@ invalid: sh_name = strsec + sh->sh_name; if (0 == strncmp(sh_name, ".debug_", 7) || 0 == strncmp(sh_name, ".stab", 5)) { - if (!s1->do_debug || seencompressed) + if (seencompressed) continue; } else if (sh->sh_type != SHT_PROGBITS && @@ -3202,12 +2722,6 @@ invalid: sm_table[i].link_once = 1; goto next; } - if (stab_section) { - if (s == stab_section) - stab_index = i; - if (s == stab_section->link) - stabstr_index = i; - } goto found; } /* not found: create new section */ @@ -3335,12 +2849,6 @@ invalid: sym_index = old_to_new_syms[sym_index]; /* ignore link_once in rel section. */ if (!sym_index && !sm_table[sh->sh_info].link_once -#ifdef TCC_TARGET_ARM - && type != R_ARM_V4BX -#elif defined TCC_TARGET_RISCV64 - && type != R_RISCV_ALIGN - && type != R_RISCV_RELAX -#endif ) { invalid_reloc: tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x", @@ -3350,18 +2858,6 @@ invalid: rel->r_info = ELFW(R_INFO)(sym_index, type); /* offset the relocation offset */ rel->r_offset += offseti; -#ifdef TCC_TARGET_ARM - /* Jumps and branches from a Thumb code to a PLT entry need - special handling since PLT entries are ARM code. - Unconditional bl instructions referencing PLT entries are - handled by converting these instructions into blx - instructions. Other case of instructions referencing a PLT - entry require to add a Thumb stub before the PLT entry to - switch to ARM mode. We set bit plt_thumb_stub of the - attribute of a symbol to indicate such a case. */ - if (type == R_ARM_THM_JUMP24) - get_sym_attr(s1, sym_index, 1)->plt_thumb_stub = 1; -#endif } break; default: diff --git a/tccgen.c b/libtcc/tccgen.c similarity index 94% rename from tccgen.c rename to libtcc/tccgen.c index b7d35ba7..1606b3c4 100644 --- a/tccgen.c +++ b/libtcc/tccgen.c @@ -20,6 +20,7 @@ #define USING_GLOBALS #include "tcc.h" +#include "utils/string.h" /********************************************************/ /* global variables */ @@ -43,7 +44,6 @@ static int nb_sym_pools; static Sym *all_cleanups, *pending_gotos; static int local_scope; -ST_DATA char debug_modes; ST_DATA SValue *vtop; static SValue _vstack[1 + VSTACK_SIZE]; @@ -176,8 +176,6 @@ static int gind() { int t = ind; CODE_ON(); - if (debug_modes) - tcc_tcov_block_begin(tcc_state); return t; } @@ -233,13 +231,6 @@ static int R_RET(int t) { if (!is_float(t)) return REG_IRET; -#ifdef TCC_TARGET_X86_64 - if ((t & VT_BTYPE) == VT_LDOUBLE) - return TREG_ST0; -#elif defined TCC_TARGET_RISCV64 - if ((t & VT_BTYPE) == VT_LDOUBLE) - return REG_IRET; -#endif return REG_FRET; } @@ -250,14 +241,6 @@ static int R2_RET(int t) #if PTR_SIZE == 4 if (t == VT_LLONG) return REG_IRE2; -#elif defined TCC_TARGET_X86_64 - if (t == VT_QLONG) - return REG_IRE2; - if (t == VT_QFLOAT) - return REG_FRE2; -#elif defined TCC_TARGET_RISCV64 - if (t == VT_LDOUBLE) - return REG_IRE2; #endif return VT_CONST; } @@ -282,15 +265,6 @@ static int RC_TYPE(int t) { if (!is_float(t)) return RC_INT; -#ifdef TCC_TARGET_X86_64 - if ((t & VT_BTYPE) == VT_LDOUBLE) - return RC_ST0; - if ((t & VT_BTYPE) == VT_QFLOAT) - return RC_FRET; -#elif defined TCC_TARGET_RISCV64 - if ((t & VT_BTYPE) == VT_LDOUBLE) - return RC_INT; -#endif return RC_FLOAT; } @@ -323,10 +297,7 @@ ST_FUNC int ieee_finite(double d) } /* compiling intel long double natively */ -#if (defined __i386__ || defined __x86_64__) \ - && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) # define TCC_IS_NATIVE_387 -#endif ST_FUNC void test_lvalue(void) { @@ -386,13 +357,7 @@ ST_FUNC int tccgen_compile(TCCState *s1) func_ind = -1; anon_sym = SYM_FIRST_ANOM; nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */ - debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1; - tcc_debug_start(s1); - tcc_tcov_start (s1); -#ifdef TCC_TARGET_ARM - arm_init(s1); -#endif #ifdef INC_DEBUG printf("%s: **** new file\n", file->filename); #endif @@ -402,17 +367,12 @@ ST_FUNC int tccgen_compile(TCCState *s1) gen_inline_functions(s1); check_vstack(); /* end of translation unit info */ -#if TCC_EH_FRAME - tcc_eh_frame_end(s1); -#endif - tcc_debug_end(s1); - tcc_tcov_end(s1); + return 0; } ST_FUNC void tccgen_finish(TCCState *s1) { - tcc_debug_end(s1); /* just in case of errors: free memory */ free_inline_functions(s1); sym_pop(&global_stack, NULL, 0); sym_pop(&local_stack, NULL, 0); @@ -546,9 +506,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, info = ELFW(ST_INFO)(sym_bind, sym_type); sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name); - if (debug_modes) - tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind, sym_type); - } else { esym = elfsym(sym); esym->st_value = value; @@ -882,13 +839,10 @@ ST_FUNC void vpop(void) { int v; v = vtop->r & VT_VALMASK; -#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) /* for x86, we need to pop the FP stack */ if (v == TREG_ST0) { o(0xd8dd); /* fstp %st(0) */ - } else -#endif - if (v == VT_CMP) { + } else if (v == VT_CMP) { /* need to put correct jump if && or || without test */ gsym(vtop->jtrue); gsym(vtop->jfalse); @@ -1375,12 +1329,10 @@ ST_FUNC void save_reg_upstack(int r, int n) sv.r = VT_LOCAL | VT_LVAL; sv.c.i = l; store(p->r & VT_VALMASK, &sv); -#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) /* x86 specific: need to pop fp register ST0 if saved */ if (r == TREG_ST0) { o(0xd8dd); /* fstp %st(0) */ } -#endif /* special long long case */ if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) { sv.c.i += PTR_SIZE; @@ -1404,31 +1356,6 @@ ST_FUNC void save_reg_upstack(int r, int n) } } -#ifdef TCC_TARGET_ARM -/* find a register of class 'rc2' with at most one reference on stack. - * If none, call get_reg(rc) */ -ST_FUNC int get_reg_ex(int rc, int rc2) -{ - int r; - SValue *p; - - for(r=0;rr & VT_VALMASK) == r || - p->r2 == r) - n++; - } - if (n <= 1) - return r; - } - } - return get_reg(rc); -} -#endif - /* find a free register of class 'rc'. If none, save one register */ ST_FUNC int get_reg(int rc) { @@ -1536,155 +1463,9 @@ ST_FUNC void gaddrof(void) vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL; } -#ifdef CONFIG_TCC_BCHECK -/* generate a bounded pointer addition */ -static void gen_bounded_ptr_add(void) -{ - int save = (vtop[-1].r & VT_VALMASK) == VT_LOCAL; - if (save) { - vpushv(&vtop[-1]); - vrott(3); - } - vpush_helper_func(TOK___bound_ptr_add); - vrott(3); - gfunc_call(2); - vtop -= save; - vpushi(0); - /* returned pointer is in REG_IRET */ - vtop->r = REG_IRET | VT_BOUNDED; - if (nocode_wanted) - return; - /* relocation offset of the bounding function call point */ - vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW_Rel)); -} - -/* patch pointer addition in vtop so that pointer dereferencing is - also tested */ -static void gen_bounded_ptr_deref(void) -{ - addr_t func; - int size, align; - ElfW_Rel *rel; - Sym *sym; - - if (nocode_wanted) - return; - - size = type_size(&vtop->type, &align); - switch(size) { - case 1: func = TOK___bound_ptr_indir1; break; - case 2: func = TOK___bound_ptr_indir2; break; - case 4: func = TOK___bound_ptr_indir4; break; - case 8: func = TOK___bound_ptr_indir8; break; - case 12: func = TOK___bound_ptr_indir12; break; - case 16: func = TOK___bound_ptr_indir16; break; - default: - /* may happen with struct member access */ - return; - } - sym = external_helper_sym(func); - if (!sym->c) - put_extern_sym(sym, NULL, 0, 0); - /* patch relocation */ - /* XXX: find a better solution ? */ - rel = (ElfW_Rel *)(cur_text_section->reloc->data + vtop->c.i); - rel->r_info = ELFW(R_INFO)(sym->c, ELFW(R_TYPE)(rel->r_info)); -} - -/* generate lvalue bound code */ -static void gbound(void) -{ - CType type1; - - vtop->r &= ~VT_MUSTBOUND; - /* if lvalue, then use checking code before dereferencing */ - if (vtop->r & VT_LVAL) { - /* if not VT_BOUNDED value, then make one */ - if (!(vtop->r & VT_BOUNDED)) { - /* must save type because we must set it to int to get pointer */ - type1 = vtop->type; - vtop->type.t = VT_PTR; - gaddrof(); - vpushi(0); - gen_bounded_ptr_add(); - vtop->r |= VT_LVAL; - vtop->type = type1; - } - /* then check for dereferencing */ - gen_bounded_ptr_deref(); - } -} - -/* we need to call __bound_ptr_add before we start to load function - args into registers */ -ST_FUNC void gbound_args(int nb_args) -{ - int i, v; - SValue *sv; - - for (i = 1; i <= nb_args; ++i) - if (vtop[1 - i].r & VT_MUSTBOUND) { - vrotb(i); - gbound(); - vrott(i); - } - - sv = vtop - nb_args; - if (sv->r & VT_SYM) { - v = sv->sym->v; - if (v == TOK_setjmp - || v == TOK__setjmp -#ifndef TCC_TARGET_PE - || v == TOK_sigsetjmp - || v == TOK___sigsetjmp -#endif - ) { - vpush_helper_func(TOK___bound_setjmp); - vpushv(sv + 1); - gfunc_call(1); - func_bound_add_epilog = 1; - } -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 - if (v == TOK_alloca) - func_bound_add_epilog = 1; -#endif -#if TARGETOS_NetBSD - if (v == TOK_longjmp) /* undo rename to __longjmp14 */ - sv->sym->asm_label = TOK___bound_longjmp; -#endif - } -} - -/* Add bounds for local symbols from S to E (via ->prev) */ -static void add_local_bounds(Sym *s, Sym *e) -{ - for (; s != e; s = s->prev) { - if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL) - continue; - /* Add arrays/structs/unions because we always take address */ - if ((s->type.t & VT_ARRAY) - || (s->type.t & VT_BTYPE) == VT_STRUCT - || s->a.addrtaken) { - /* add local bound info */ - int align, size = type_size(&s->type, &align); - addr_t *bounds_ptr = section_ptr_add(lbounds_section, - 2 * sizeof(addr_t)); - bounds_ptr[0] = s->c; - bounds_ptr[1] = size; - } - } -} -#endif - /* Wrapper around sym_pop, that potentially also registers local bounds. */ static void pop_local_syms(Sym *b, int keep) { -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check && !keep && (local_scope || !func_var)) - add_local_bounds(local_stack, b); -#endif - if (debug_modes) - tcc_add_debug_info (tcc_state, !local_scope, local_stack, b); sym_pop(&local_stack, b, keep); } @@ -1846,18 +1627,9 @@ ST_FUNC int gv(int rc) init_putv(&p, &vtop->type, offset); vtop->r |= VT_LVAL; } -#ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); -#endif bt = vtop->type.t & VT_BTYPE; -#ifdef TCC_TARGET_RISCV64 - /* XXX mega hack */ - if (bt == VT_LDOUBLE && rc == RC_FLOAT) - rc = RC_INT; -#endif rc2 = RC2_TYPE(bt, rc); /* need to reload if: @@ -1932,11 +1704,6 @@ ST_FUNC int gv(int rc) } } vtop->r = r; -#ifdef TCC_TARGET_C67 - /* uses register pairs for doubles */ - if (bt == VT_DOUBLE) - vtop->r2 = r+1; -#endif } return r; } @@ -2066,10 +1833,6 @@ static void gen_opl(int op) case TOK_UMOD: func = TOK___umoddi3; gen_mod_func: -#ifdef TCC_ARM_EABI - reg_iret = TREG_R2; - reg_lret = TREG_R3; -#endif gen_func: /* call generic long long function */ vpush_helper_func(func); @@ -2445,38 +2208,8 @@ static void gen_opic(int op) } } -#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386 -# define gen_negf gen_opf -#elif defined TCC_TARGET_ARM -void gen_negf(int op) -{ - /* arm will detect 0-x and replace by vneg */ - vpushi(0), vswap(), gen_op('-'); -} -#else -/* XXX: implement in gen_opf() for other backends too */ -void gen_negf(int op) -{ - /* In IEEE negate(x) isn't subtract(0,x). Without NaNs it's - subtract(-0, x), but with them it's really a sign flip - operation. We implement this with bit manipulation and have - to do some type reinterpretation for this, which TCC can do - only via memory. */ +#define gen_negf gen_opf - int align, size, bt; - - size = type_size(&vtop->type, &align); - bt = vtop->type.t & VT_BTYPE; - save_reg(gv(RC_TYPE(bt))); - vdup(); - incr_bf_adr(size - 1); - vdup(); - vpushi(0x80); /* flip sign */ - gen_op('^'); - vstore(); - vpop(); -} -#endif /* generate a floating point operation with constant propagation */ static void gen_opif(int op) @@ -3037,21 +2770,7 @@ op_err: type1 = vtop[-1].type; vpush_type_size(pointed_type(&vtop[-1].type), &align); gen_op('*'); -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check && !CONST_WANTED) { - /* if bounded pointers, we generate a special code to - test bounds */ - if (op == '-') { - vpushi(0); - vswap(); - gen_op('-'); - } - gen_bounded_ptr_add(); - } else -#endif - { - gen_opic(op); - } + gen_opic(op); type1.t &= ~(VT_ARRAY|VT_VLA); /* put again type if gen_opic() swaped operands */ vtop->type = type1; @@ -3107,9 +2826,6 @@ op_err: gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT); } -#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 || defined TCC_TARGET_ARM -#define gen_cvt_itof1 gen_cvt_itof -#else /* generic itof for unsigned long long case */ static void gen_cvt_itof1(int t) { @@ -3132,11 +2848,7 @@ static void gen_cvt_itof1(int t) gen_cvt_itof(t); } } -#endif -#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 -#define gen_cvt_ftoi1 gen_cvt_ftoi -#else /* generic ftoi for unsigned long long case */ static void gen_cvt_ftoi1(int t) { @@ -3160,7 +2872,6 @@ static void gen_cvt_ftoi1(int t) gen_cvt_ftoi(t); } } -#endif /* special delayed cast for char/short */ static void force_charshort_cast(void) @@ -3217,7 +2928,7 @@ error: } c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; -#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 +#if !defined TCC_IS_NATIVE_387 /* don't try to convert to ldouble when cross-compiling (except when it's '0' which is needed for arm:gen_negf()) */ if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0)) @@ -3373,13 +3084,7 @@ error: if (ds == 8) { /* need to convert from 32bit to 64bit */ if (sbt & VT_UNSIGNED) { -#if defined(TCC_TARGET_RISCV64) - /* RISC-V keeps 32bit vals in registers sign-extended. - So here we need a zero-extension. */ - trunc = 32; -#else goto done; -#endif } else { gen_cvt_sxtw(); goto done; @@ -3389,9 +3094,7 @@ error: /* RISC-V keeps 32bit vals in registers sign-extended. So here we need a sign-extension for signed types and zero-extension. for unsigned types. */ -#if !defined(TCC_TARGET_RISCV64) trunc = 32; /* zero upper 32 bits for non RISC-V targets */ -#endif } else { ss = 4; } @@ -3399,12 +3102,10 @@ error: if (ds >= ss) goto done; -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 if (ss == 4) { gen_cvt_csti(dbt); goto done; } -#endif bits = (ss - ds) * 8; /* for unsigned, gen_op will convert SAR to SHR */ vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED); @@ -3451,8 +3152,7 @@ ST_FUNC int type_size(CType *type, int *a) *a = LDOUBLE_ALIGN; return LDOUBLE_SIZE; } else if (bt == VT_DOUBLE || bt == VT_LLONG) { -#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) \ - || (defined TCC_TARGET_ARM && !defined TCC_ARM_EABI) +#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) *a = 4; #else *a = 8; @@ -3632,27 +3332,16 @@ ST_FUNC void vstore(void) size = type_size(&vtop->type, &align); /* destination, keep on stack() as result */ vpushv(vtop - 1); -#ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); /* check would be wrong after gaddrof() */ -#endif + vtop->type.t = VT_PTR; gaddrof(); /* source */ vswap(); -#ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); -#endif vtop->type.t = VT_PTR; gaddrof(); #ifdef TCC_TARGET_NATIVE_STRUCT_COPY - if (1 -#ifdef CONFIG_TCC_BCHECK - && !tcc_state->do_bounds_check -#endif - ) { + if (1) { gen_struct_copy(size); } else #endif @@ -3660,13 +3349,6 @@ ST_FUNC void vstore(void) /* type size */ vpushi(size); /* Use memmove, rather than memcpy, as dest and src may be same: */ -#ifdef TCC_ARM_EABI - if(!(align & 7)) - vpush_helper_func(TOK_memmove8); - else if(!(align & 3)) - vpush_helper_func(TOK_memmove4); - else -#endif vpush_helper_func(TOK_memmove); vrott(4); gfunc_call(3); @@ -3740,14 +3422,6 @@ ST_FUNC void vstore(void) gen_cast(&vtop[-1].type); } -#ifdef CONFIG_TCC_BCHECK - /* bound check case */ - if (vtop[-1].r & VT_MUSTBOUND) { - vswap(); - gbound(); - vswap(); - } -#endif gv(RC_TYPE(dbt)); /* generate value */ if (delayed_cast) { @@ -4283,11 +3957,7 @@ static void struct_layout(CType *type, AttributeDef *ad) bit_pos = BIT_POS(f->type.t); size = type_size(&f->type, &align); - if (bit_pos + bit_size <= size * 8 && f->c + size <= c -#ifdef TCC_TARGET_ARM - && !(f->c & (align - 1)) -#endif - ) + if (bit_pos + bit_size <= size * 8 && f->c + size <= c) continue; /* try to access the field using a different type */ @@ -4313,11 +3983,7 @@ static void struct_layout(CType *type, AttributeDef *ad) c0 = cx; } - if (px + bit_size <= s * 8 && cx + s <= c -#ifdef TCC_TARGET_ARM - && !(cx & (align - 1)) -#endif - ) { + if (px + bit_size <= s * 8 && cx + s <= c) { /* update offset and bit position */ f->c = cx; bit_pos = px; @@ -4590,8 +4256,6 @@ do_decl: check_fields(type, 1); check_fields(type, 0); struct_layout(type, &ad); - if (debug_modes) - tcc_debug_fix_anon(tcc_state, type); } } } @@ -4696,13 +4360,6 @@ static int parse_btype(CType *type, AttributeDef *ad, int ignore_label) } next(); break; -#ifdef TCC_TARGET_ARM64 - case TOK_UINT128: - /* GCC's __uint128_t appears in some Linux header files. Make it a - synonym for long double to get the size and alignment right. */ - u = VT_LDOUBLE; - goto basic_type; -#endif case TOK_BOOL: u = VT_BOOL; goto basic_type; @@ -5222,11 +4879,6 @@ ST_FUNC void indir(void) if (!(vtop->type.t & (VT_ARRAY | VT_VLA)) && (vtop->type.t & VT_BTYPE) != VT_FUNC) { vtop->r |= VT_LVAL; - /* if bound checking, the referenced pointer must be checked */ -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - vtop->r |= VT_MUSTBOUND; -#endif } } @@ -5487,10 +5139,6 @@ ST_FUNC void unary(void) Sym *s; AttributeDef ad; - /* generate line number info */ - if (debug_modes) - tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1); - type.ref = NULL; /* XXX: GCC 2.95.3 does not generate a table although it should be better here */ @@ -5764,92 +5412,18 @@ ST_FUNC void unary(void) mk_pointer(&type); vset(&type, VT_LOCAL, 0); /* local frame */ while (level--) { -#ifdef TCC_TARGET_RISCV64 - vpushi(2*PTR_SIZE); - gen_op('-'); -#endif mk_pointer(&vtop->type); indir(); /* -> parent frame */ } if (tok1 == TOK_builtin_return_address) { // assume return address is just above frame pointer on stack -#ifdef TCC_TARGET_ARM - vpushi(2*PTR_SIZE); - gen_op('+'); -#elif defined TCC_TARGET_RISCV64 - vpushi(PTR_SIZE); - gen_op('-'); -#else vpushi(PTR_SIZE); gen_op('+'); -#endif mk_pointer(&vtop->type); indir(); } } break; -#ifdef TCC_TARGET_RISCV64 - case TOK_builtin_va_start: - parse_builtin_params(0, "ee"); - r = vtop->r & VT_VALMASK; - if (r == VT_LLOCAL) - r = VT_LOCAL; - if (r != VT_LOCAL) - tcc_error("__builtin_va_start expects a local variable"); - gen_va_start(); - vstore(); - break; -#endif -#ifdef TCC_TARGET_X86_64 -#ifdef TCC_TARGET_PE - case TOK_builtin_va_start: - parse_builtin_params(0, "ee"); - r = vtop->r & VT_VALMASK; - if (r == VT_LLOCAL) - r = VT_LOCAL; - if (r != VT_LOCAL) - tcc_error("__builtin_va_start expects a local variable"); - vtop->r = r; - vtop->type = char_pointer_type; - vtop->c.i += 8; - vstore(); - break; -#else - case TOK_builtin_va_arg_types: - parse_builtin_params(0, "t"); - vpushi(classify_x86_64_va_arg(&vtop->type)); - vswap(); - vpop(); - break; -#endif -#endif - -#ifdef TCC_TARGET_ARM64 - case TOK_builtin_va_start: { - parse_builtin_params(0, "ee"); - //xx check types - gen_va_start(); - vpushi(0); - vtop->type.t = VT_VOID; - break; - } - case TOK_builtin_va_arg: { - parse_builtin_params(0, "et"); - type = vtop->type; - vpop(); - //xx check types - gen_va_arg(&type); - vtop->type = type; - break; - } - case TOK___arm64_clear_cache: { - parse_builtin_params(0, "ee"); - gen_clear_cache(); - vpushi(0); - vtop->type.t = VT_VOID; - break; - } -#endif /* atomic operations */ case TOK___atomic_store: @@ -6066,11 +5640,6 @@ special_math_val: /* an array is never an lvalue */ if (!(vtop->type.t & VT_ARRAY)) { vtop->r |= VT_LVAL; -#ifdef CONFIG_TCC_BCHECK - /* if bound checking, the referenced pointer must be checked */ - if (tcc_state->do_bounds_check) - vtop->r |= VT_MUSTBOUND; -#endif } next(); } else if (tok == '[') { @@ -6113,25 +5682,12 @@ special_math_val: if (ret_nregs <= 0) { /* get some space for the returned structure */ size = type_size(&s->type, &align); -#ifdef TCC_TARGET_ARM64 - /* On arm64, a small struct is return in registers. - It is much easier to write it to memory if we know - that we are allowed to write some extra bytes, so - round the allocated space up to a power of 2: */ - if (size < 16) - while (size & (size - 1)) - size = (size | (size - 1)) + 1; -#endif loc = (loc - size) & -align; ret.type = s->type; ret.r = VT_LOCAL | VT_LVAL; /* pass it as 'int' to avoid structure arg passing problems */ vseti(VT_LOCAL, loc); -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) - --loc; -#endif ret.c = vtop->c; if (ret_nregs < 0) vtop--; @@ -6191,9 +5747,6 @@ special_math_val: if (ret_nregs < 0) { vsetc(&ret.type, ret.r, &ret.c); -#ifdef TCC_TARGET_RISCV64 - arch_transfer_ret_regs(1); -#endif } else { /* return value */ n = ret_nregs; @@ -6251,8 +5804,6 @@ special_math_val: } } if (s->f.func_noreturn) { - if (debug_modes) - tcc_tcov_block_end(tcc_state, -1); CODE_OFF(); } } else { @@ -6679,7 +6230,7 @@ ST_FUNC int expr_const(void) /* ------------------------------------------------------------------------- */ /* return from function */ -#ifndef TCC_TARGET_ARM64 + static void gfunc_return(CType *func_type) { if ((func_type->t & VT_BTYPE) == VT_STRUCT) { @@ -6688,9 +6239,6 @@ static void gfunc_return(CType *func_type) ret_nregs = gfunc_sret(func_type, func_var, &ret_type, &ret_align, ®size); if (ret_nregs < 0) { -#ifdef TCC_TARGET_RISCV64 - arch_transfer_ret_regs(0); -#endif } else if (0 == ret_nregs) { /* if returning structure, must copy it to implicit first pointer arg location */ @@ -6739,7 +6287,6 @@ static void gfunc_return(CType *func_type) } vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ } -#endif static void check_func_return(void) { @@ -7027,9 +6574,6 @@ again: goto expr; next(); - if (debug_modes) - tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state); - if (t == TOK_IF) { new_scope_s(&o); skip('('); @@ -7063,8 +6607,6 @@ again: prev_scope_s(&o); } else if (t == '{') { - if (debug_modes) - tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind); new_scope(&o); /* handle local labels declarations */ @@ -7089,8 +6631,6 @@ again: } prev_scope(&o, flags & STMT_EXPR); - if (debug_modes) - tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind); if (local_scope) next(); else if (!nocode_wanted) @@ -7118,8 +6658,6 @@ again: /* jump unless last stmt in top-level block */ if (tok != '}' || local_scope != 1) rsym = gjmp(rsym); - if (debug_modes) - tcc_tcov_block_end (tcc_state, -1); CODE_OFF(); } else if (t == TOK_BREAK) { @@ -7332,8 +6870,6 @@ again: AttributeDef ad_tmp; parse_attribute(&ad_tmp); } - if (debug_modes) - tcc_tcov_reset_ind(tcc_state); vla_restore(cur_scope->vla.loc); if (tok != '}') { @@ -7360,9 +6896,6 @@ again: } } } - - if (debug_modes) - tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_end (tcc_state, 0); } /* This skips over a stream of tokens containing balanced {} and () @@ -7459,9 +6992,6 @@ static void init_putz(init_params *p, unsigned long c, int size) vseti(VT_LOCAL, c); vpushi(0); vpushs(size); -#if defined TCC_TARGET_ARM && defined TCC_ARM_EABI - vswap(); /* using __aeabi_memset(void*, size_t, int) */ -#endif gfunc_call(3); } } @@ -7834,10 +7364,6 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f Sym indexsym; CType *t1; - /* generate line number info */ - if (debug_modes && !(flags & DIF_SIZE_ONLY) && !p->sec) - tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1); - if (!(flags & DIF_HAVE_ELEM) && tok != '{' && /* In case of strings we have special handling for arrays, so don't consume them as initializer value (which would commit them @@ -8060,9 +7586,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, Sym *flexible_array; Sym *sym; int saved_nocode_wanted = nocode_wanted; -#ifdef CONFIG_TCC_BCHECK - int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; -#endif init_params p = {0}; /* Always allocate static or global variables */ @@ -8151,21 +7674,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if ((r & VT_VALMASK) == VT_LOCAL) { sec = NULL; -#ifdef CONFIG_TCC_BCHECK - if (bcheck && v) { - /* add padding between stack variables for bound checking */ - loc -= align; - } -#endif + loc = (loc - size) & -align; addr = loc; p.local_offset = addr + size; -#ifdef CONFIG_TCC_BCHECK - if (bcheck && v) { - /* add padding between stack variables for bound checking */ - loc -= align; - } -#endif if (v) { /* local variable */ #ifdef CONFIG_TCC_ASM @@ -8229,11 +7741,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (sec) { addr = section_add(sec, size, align); -#ifdef CONFIG_TCC_BCHECK - /* add padding if bound check */ - if (bcheck) - section_add(sec, 1, 1); -#endif + } else { addr = align; /* SHN_COMMON is special, symbol value is align */ sec = common_section; @@ -8253,19 +7761,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, vtop->r |= r; } -#ifdef CONFIG_TCC_BCHECK - /* handles bounds now because the symbol must be defined - before for the relocation */ - if (bcheck) { - addr_t *bounds_ptr; - - greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0); - /* then add global bound info */ - bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t)); - bounds_ptr[0] = 0; /* relocated */ - bounds_ptr[1] = size; - } -#endif } if (type->t & VT_VLA) { @@ -8286,11 +7781,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, vpush_type_size(type, &a); gen_vla_alloc(type, a); -#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 - /* on _WIN64, because of the function args scratch area, the - result of alloca differs from RSP and is returned in RAX. */ - gen_vla_result(addr), addr = (loc -= PTR_SIZE); -#endif gen_vla_sp_save(addr); cur_scope->vla.loc = addr; cur_scope->vla.num++; @@ -8381,15 +7871,12 @@ static void gen_function(Sym *sym) if (sym->type.ref->f.func_dtor) add_array (tcc_state, ".fini_array", sym->c); - /* put debug symbol */ - tcc_debug_funcstart(tcc_state, sym); /* push a dummy symbol to enable local sym storage */ sym_push2(&local_stack, SYM_FIELD, 0, 0); local_scope = 1; /* for function parameters */ nb_temp_local_vars = 0; gfunc_prolog(sym); - tcc_debug_prolog_epilog(tcc_state, 0); local_scope = 0; rsym = 0; @@ -8400,11 +7887,8 @@ static void gen_function(Sym *sym) nocode_wanted = 0; /* reset local stack */ pop_local_syms(NULL, 0); - tcc_debug_prolog_epilog(tcc_state, 1); gfunc_epilog(); - /* end of function */ - tcc_debug_funcend(tcc_state, ind - func_ind); /* patch symbol size */ elfsym(sym)->st_size = ind - func_ind; @@ -8691,8 +8175,6 @@ static int decl(int l) sym->a = ad.a; if ((type.t & VT_BTYPE) == VT_FUNC) merge_funcattr(&sym->type.ref->f, &ad.f); - if (debug_modes) - tcc_debug_typedef (tcc_state, sym); } else if ((type.t & VT_BTYPE) == VT_VOID && !(type.t & VT_EXTERN)) { tcc_error("declaration of void object"); diff --git a/tccpe.c b/libtcc/tccpe.c similarity index 99% rename from tccpe.c rename to libtcc/tccpe.c index a1fbb32c..e39d7a46 100644 --- a/tccpe.c +++ b/libtcc/tccpe.c @@ -20,6 +20,8 @@ #include "tcc.h" +#define TCC_OUTPUT_DLL 666 + #define PE_MERGE_DATA 1 #define PE_PRINT_SECTIONS 0 @@ -1880,22 +1882,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe) ++start_symbol; } -#ifdef CONFIG_TCC_BACKTRACE - if (s1->do_backtrace) { -#ifdef CONFIG_TCC_BCHECK - if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) - tcc_add_support(s1, "bcheck.o"); -#endif - if (s1->output_type == TCC_OUTPUT_EXE) - tcc_add_support(s1, "bt-exe.o"); - if (s1->output_type == TCC_OUTPUT_DLL) - tcc_add_support(s1, "bt-dll.o"); - if (s1->output_type != TCC_OUTPUT_DLL) - tcc_add_support(s1, "bt-log.o"); - tcc_add_btstub(s1); - } -#endif - /* grab the startup code from libtcc1.a */ #ifdef TCC_IS_NATIVE if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main) @@ -1982,9 +1968,6 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) pe.s1 = s1; s1->filetype = 0; -#ifdef CONFIG_TCC_BCHECK - tcc_add_bcheck(s1); -#endif tcc_add_pragma_libs(s1); pe_add_runtime(s1, &pe); resolve_common_syms(s1); diff --git a/tccpp.c b/libtcc/tccpp.c similarity index 99% rename from tccpp.c rename to libtcc/tccpp.c index 2bfe8954..15b540f7 100644 --- a/tccpp.c +++ b/libtcc/tccpp.c @@ -20,6 +20,7 @@ #define USING_GLOBALS #include "tcc.h" +#include "utils/string.h" /* #define to 1 to enable (see parse_pp_string()) */ #define ACCEPT_LF_IN_STRINGS 0 @@ -946,12 +947,8 @@ redo_start: else if (parse_flags & PARSE_FLAG_ASM_FILE) p = parse_line_comment(p - 1); } -#if !defined(TCC_TARGET_ARM) else if (parse_flags & PARSE_FLAG_ASM_FILE) p = parse_line_comment(p - 1); -#else - /* ARM assembly uses '#' for constants */ -#endif break; _default: default: @@ -1326,8 +1323,8 @@ static void maybe_run_test(TCCState *s) p = get_tok_str(tok, NULL); if (0 != memcmp(p, "test_", 5)) return; - if (0 != --s->run_test) - return; + /*if (0 != --s->run_test) + return;*/ fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp); define_push(tok, MACRO_OBJ, NULL, NULL); } @@ -1446,8 +1443,6 @@ static int parse_include(TCCState *s1, int do_next, int test) dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(buf)); } - /* add include file debug info */ - tcc_debug_bincl(s1); } return 1; } @@ -1479,8 +1474,6 @@ static int expr_preprocess(TCCState *s1) parse_flags |= PARSE_FLAG_PREPROCESS; if (tok < TOK_IDENT) expect("identifier after 'defined'"); - if (s1->run_test) - maybe_run_test(s1); c = 0; if (define_find(tok) || tok == TOK___HAS_INCLUDE @@ -1806,7 +1799,6 @@ ST_FUNC void tccpp_putfile(const char *filename) if (file->true_filename == file->filename) file->true_filename = tcc_strdup(file->filename); pstrcpy(file->filename, sizeof file->filename, buf); - tcc_debug_newfile(tcc_state); } /* is_bof is true if first non space token at beginning of file */ @@ -2615,8 +2607,6 @@ static void next_nomacro(void) tok_flags &= ~TOK_FLAG_ENDIF; } - /* add end of include file debug info */ - tcc_debug_eincl(tcc_state); /* pop include stack */ tcc_close(); s1->include_stack_ptr--; @@ -2653,12 +2643,10 @@ maybe_newline: p++; tok = TOK_TWOSHARPS; } else { -#if !defined(TCC_TARGET_ARM) if (parse_flags & PARSE_FLAG_ASM_FILE) { p = parse_line_comment(p - 1); goto redo_no_start; } else -#endif { tok = '#'; } @@ -3576,24 +3564,12 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm) putdefs(cs, target_machine_defs); putdefs(cs, target_os_defs); -#ifdef TCC_TARGET_ARM - if (s1->float_abi == ARM_HARD_FLOAT) - putdef(cs, "__ARM_PCS_VFP"); -#endif if (is_asm) putdef(cs, "__ASSEMBLER__"); if (s1->output_type == TCC_OUTPUT_PREPROCESS) putdef(cs, "__TCC_PP__"); if (s1->output_type == TCC_OUTPUT_MEMORY) putdef(cs, "__TCC_RUN__"); -#ifdef CONFIG_TCC_BACKTRACE - if (s1->do_backtrace) - putdef(cs, "__TCC_BACKTRACE__"); -#endif -#ifdef CONFIG_TCC_BCHECK - if (s1->do_bounds_check) - putdef(cs, "__TCC_BCHECK__"); -#endif if (s1->char_is_unsigned) putdef(cs, "__CHAR_UNSIGNED__"); if (s1->optimize > 0) diff --git a/tcctok.h b/libtcc/tcctok.h similarity index 61% rename from tcctok.h rename to libtcc/tcctok.h index bcd67f19..c1cfbe9e 100644 --- a/tcctok.h +++ b/libtcc/tcctok.h @@ -68,10 +68,6 @@ DEF(TOK_TYPEOF3, "__typeof__") DEF(TOK_LABEL, "__label__") -#ifdef TCC_TARGET_ARM64 - DEF(TOK_UINT128, "__uint128_t") -#endif - /*********************************************************************/ /* the following are not keywords. They are included to ease parsing */ /* preprocessor only */ @@ -105,10 +101,6 @@ DEF(TOK___NAN__, "__nan__") DEF(TOK___SNAN__, "__snan__") DEF(TOK___INF__, "__inf__") -#if defined TCC_TARGET_X86_64 - DEF(TOK___mzerosf, "__mzerosf") /* -0.0 */ - DEF(TOK___mzerodf, "__mzerodf") /* -0.0 */ -#endif /* attribute identifiers */ /* XXX: handle all tokens generically since speed is not critical */ @@ -173,16 +165,6 @@ DEF(TOK_builtin_expect, "__builtin_expect") DEF(TOK_builtin_unreachable, "__builtin_unreachable") /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/ -#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64 - DEF(TOK_builtin_va_start, "__builtin_va_start") -#elif defined TCC_TARGET_X86_64 - DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types") -#elif defined TCC_TARGET_ARM64 - DEF(TOK_builtin_va_start, "__builtin_va_start") - DEF(TOK_builtin_va_arg, "__builtin_va_arg") -#elif defined TCC_TARGET_RISCV64 - DEF(TOK_builtin_va_start, "__builtin_va_start") -#endif /* atomic operations */ #define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID) @@ -205,13 +187,6 @@ /* pragma */ DEF(TOK_pack, "pack") -#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \ - !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_ARM64) && \ - !defined(TCC_TARGET_RISCV64) - /* already defined for assembler */ - DEF(TOK_ASM_push, "push") - DEF(TOK_ASM_pop, "pop") -#endif DEF(TOK_comment, "comment") DEF(TOK_lib, "lib") DEF(TOK_push_macro, "push_macro") @@ -220,7 +195,6 @@ DEF(TOK_option, "option") /* builtin functions or variables */ -#ifndef TCC_ARM_EABI DEF(TOK_memcpy, "memcpy") DEF(TOK_memmove, "memmove") DEF(TOK_memset, "memset") @@ -233,134 +207,16 @@ DEF(TOK___ashldi3, "__ashldi3") DEF(TOK___floatundisf, "__floatundisf") DEF(TOK___floatundidf, "__floatundidf") -# ifndef TCC_ARM_VFP DEF(TOK___floatundixf, "__floatundixf") DEF(TOK___fixunsxfdi, "__fixunsxfdi") -# endif DEF(TOK___fixunssfdi, "__fixunssfdi") DEF(TOK___fixunsdfdi, "__fixunsdfdi") -#endif -#if defined TCC_TARGET_ARM -# ifdef TCC_ARM_EABI - DEF(TOK_memcpy, "__aeabi_memcpy") - DEF(TOK_memmove, "__aeabi_memmove") - DEF(TOK_memmove4, "__aeabi_memmove4") - DEF(TOK_memmove8, "__aeabi_memmove8") - DEF(TOK_memset, "__aeabi_memset") - DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod") - DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod") - DEF(TOK___aeabi_idivmod, "__aeabi_idivmod") - DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod") - DEF(TOK___divsi3, "__aeabi_idiv") - DEF(TOK___udivsi3, "__aeabi_uidiv") - DEF(TOK___floatdisf, "__aeabi_l2f") - DEF(TOK___floatdidf, "__aeabi_l2d") - DEF(TOK___fixsfdi, "__aeabi_f2lz") - DEF(TOK___fixdfdi, "__aeabi_d2lz") - DEF(TOK___ashrdi3, "__aeabi_lasr") - DEF(TOK___lshrdi3, "__aeabi_llsr") - DEF(TOK___ashldi3, "__aeabi_llsl") - DEF(TOK___floatundisf, "__aeabi_ul2f") - DEF(TOK___floatundidf, "__aeabi_ul2d") - DEF(TOK___fixunssfdi, "__aeabi_f2ulz") - DEF(TOK___fixunsdfdi, "__aeabi_d2ulz") -# else - DEF(TOK___modsi3, "__modsi3") - DEF(TOK___umodsi3, "__umodsi3") - DEF(TOK___divsi3, "__divsi3") - DEF(TOK___udivsi3, "__udivsi3") - DEF(TOK___floatdisf, "__floatdisf") - DEF(TOK___floatdidf, "__floatdidf") -# ifndef TCC_ARM_VFP - DEF(TOK___floatdixf, "__floatdixf") - DEF(TOK___fixunssfsi, "__fixunssfsi") - DEF(TOK___fixunsdfsi, "__fixunsdfsi") - DEF(TOK___fixunsxfsi, "__fixunsxfsi") - DEF(TOK___fixxfdi, "__fixxfdi") -# endif - DEF(TOK___fixsfdi, "__fixsfdi") - DEF(TOK___fixdfdi, "__fixdfdi") -# endif -#endif - -#if defined TCC_TARGET_C67 - DEF(TOK__divi, "_divi") - DEF(TOK__divu, "_divu") - DEF(TOK__divf, "_divf") - DEF(TOK__divd, "_divd") - DEF(TOK__remi, "_remi") - DEF(TOK__remu, "_remu") -#endif - -#if defined TCC_TARGET_I386 DEF(TOK___fixsfdi, "__fixsfdi") DEF(TOK___fixdfdi, "__fixdfdi") DEF(TOK___fixxfdi, "__fixxfdi") -#endif -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 DEF(TOK_alloca, "alloca") -#endif - -#if defined TCC_TARGET_PE - DEF(TOK___chkstk, "__chkstk") -#endif -#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 - DEF(TOK___arm64_clear_cache, "__arm64_clear_cache") - DEF(TOK___addtf3, "__addtf3") - DEF(TOK___subtf3, "__subtf3") - DEF(TOK___multf3, "__multf3") - DEF(TOK___divtf3, "__divtf3") - DEF(TOK___extendsftf2, "__extendsftf2") - DEF(TOK___extenddftf2, "__extenddftf2") - DEF(TOK___trunctfsf2, "__trunctfsf2") - DEF(TOK___trunctfdf2, "__trunctfdf2") - DEF(TOK___fixtfsi, "__fixtfsi") - DEF(TOK___fixtfdi, "__fixtfdi") - DEF(TOK___fixunstfsi, "__fixunstfsi") - DEF(TOK___fixunstfdi, "__fixunstfdi") - DEF(TOK___floatsitf, "__floatsitf") - DEF(TOK___floatditf, "__floatditf") - DEF(TOK___floatunsitf, "__floatunsitf") - DEF(TOK___floatunditf, "__floatunditf") - DEF(TOK___eqtf2, "__eqtf2") - DEF(TOK___netf2, "__netf2") - DEF(TOK___lttf2, "__lttf2") - DEF(TOK___letf2, "__letf2") - DEF(TOK___gttf2, "__gttf2") - DEF(TOK___getf2, "__getf2") -#endif - -/* bound checking symbols */ -#ifdef CONFIG_TCC_BCHECK - DEF(TOK___bound_ptr_add, "__bound_ptr_add") - DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1") - DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2") - DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4") - DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8") - DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12") - DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16") - DEF(TOK___bound_main_arg, "__bound_main_arg") - DEF(TOK___bound_local_new, "__bound_local_new") - DEF(TOK___bound_local_delete, "__bound_local_delete") - DEF(TOK___bound_setjmp, "__bound_setjmp") - DEF(TOK___bound_longjmp, "__bound_longjmp") - DEF(TOK___bound_new_region, "__bound_new_region") -# ifdef TCC_TARGET_PE -# ifdef TCC_TARGET_X86_64 - DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") -# endif -# else - DEF(TOK_sigsetjmp, "sigsetjmp") - DEF(TOK___sigsetjmp, "__sigsetjmp") - DEF(TOK_siglongjmp, "siglongjmp") -# endif - DEF(TOK_setjmp, "setjmp") - DEF(TOK__setjmp, "_setjmp") - DEF(TOK_longjmp, "longjmp") -#endif - /*********************************************************************/ /* Tiny Assembler */ @@ -401,28 +257,12 @@ DEF_ASMDIR(endr) DEF_ASMDIR(org) DEF_ASMDIR(quad) -#if defined(TCC_TARGET_I386) DEF_ASMDIR(code16) DEF_ASMDIR(code32) -#elif defined(TCC_TARGET_X86_64) - DEF_ASMDIR(code64) -#elif defined(TCC_TARGET_RISCV64) - DEF_ASMDIR(option) -#endif DEF_ASMDIR(short) DEF_ASMDIR(long) DEF_ASMDIR(int) DEF_ASMDIR(symver) DEF_ASMDIR(section) /* must be last directive */ -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -#include "i386-tok.h" -#endif - -#if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 -#include "arm-tok.h" -#endif - -#if defined TCC_TARGET_RISCV64 -#include "riscv64-tok.h" -#endif +#include "i386/tok.h" diff --git a/libtcc/utils/string.h b/libtcc/utils/string.h new file mode 100644 index 00000000..a44b0c4b --- /dev/null +++ b/libtcc/utils/string.h @@ -0,0 +1,47 @@ +#ifndef LIBTCC_UTILS_STRING_H +# define LIBTCC_UTILS_STRING_H 1 + +# include +# include + +/* copy a string and truncate it. */ +static inline char * +pstrcpy(char *buf, size_t buf_size, const char *s) +{ + char *q, *q_end; + int c; + + if (buf_size > 0) { + q = buf; + q_end = buf + buf_size - 1; + while (q < q_end) { + c = *s++; + if (c == '\0') + break; + *q++ = c; + } + *q = '\0'; + } + return buf; +} + +/* strcat and truncate. */ +static inline char * +pstrcat(char *buf, size_t buf_size, const char *s) +{ + size_t len; + len = strlen(buf); + if (len < buf_size) + pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +static inline char * +pstrncpy(char *out, const char *in, size_t num) +{ + memcpy(out, in, num); + out[num] = '\0'; + return out; +} + +#endif /* !LIBTCC_UTILS_STRING_H */ \ No newline at end of file diff --git a/lib/alloca-bt.S b/libtcc1/alloca-bt.S similarity index 100% rename from lib/alloca-bt.S rename to libtcc1/alloca-bt.S diff --git a/lib/alloca.S b/libtcc1/alloca.S similarity index 100% rename from lib/alloca.S rename to libtcc1/alloca.S diff --git a/lib/armeabi.c b/libtcc1/armeabi.c similarity index 100% rename from lib/armeabi.c rename to libtcc1/armeabi.c diff --git a/lib/armflush.c b/libtcc1/armflush.c similarity index 100% rename from lib/armflush.c rename to libtcc1/armflush.c diff --git a/lib/atomic.S b/libtcc1/atomic.S similarity index 100% rename from lib/atomic.S rename to libtcc1/atomic.S diff --git a/lib/bcheck.c b/libtcc1/bcheck.c similarity index 100% rename from lib/bcheck.c rename to libtcc1/bcheck.c diff --git a/lib/bt-dll.c b/libtcc1/bt-dll.c similarity index 100% rename from lib/bt-dll.c rename to libtcc1/bt-dll.c diff --git a/lib/bt-exe.c b/libtcc1/bt-exe.c similarity index 100% rename from lib/bt-exe.c rename to libtcc1/bt-exe.c diff --git a/lib/bt-log.c b/libtcc1/bt-log.c similarity index 100% rename from lib/bt-log.c rename to libtcc1/bt-log.c diff --git a/lib/builtin.c b/libtcc1/builtin.c similarity index 100% rename from lib/builtin.c rename to libtcc1/builtin.c diff --git a/lib/dsohandle.c b/libtcc1/dsohandle.c similarity index 100% rename from lib/dsohandle.c rename to libtcc1/dsohandle.c diff --git a/lib/lib-arm64.c b/libtcc1/lib-arm64.c similarity index 100% rename from lib/lib-arm64.c rename to libtcc1/lib-arm64.c diff --git a/lib/libtcc1.c b/libtcc1/libtcc1.c similarity index 100% rename from lib/libtcc1.c rename to libtcc1/libtcc1.c diff --git a/lib/runmain.c b/libtcc1/runmain.c similarity index 100% rename from lib/runmain.c rename to libtcc1/runmain.c diff --git a/lib/stdatomic.c b/libtcc1/stdatomic.c similarity index 100% rename from lib/stdatomic.c rename to libtcc1/stdatomic.c diff --git a/tcclib.h b/libtcc1/tcclib.h similarity index 100% rename from tcclib.h rename to libtcc1/tcclib.h diff --git a/lib/tcov.c b/libtcc1/tcov.c similarity index 100% rename from lib/tcov.c rename to libtcc1/tcov.c diff --git a/lib/va_list.c b/libtcc1/va_list.c similarity index 100% rename from lib/va_list.c rename to libtcc1/va_list.c diff --git a/stab.def b/stab.def deleted file mode 100644 index 48ea231e..00000000 --- a/stab.def +++ /dev/null @@ -1,234 +0,0 @@ -/* Table of DBX symbol codes for the GNU system. - Copyright (C) 1988, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* This contains contribution from Cygnus Support. */ - -/* Global variable. Only the name is significant. - To find the address, look in the corresponding external symbol. */ -__define_stab (N_GSYM, 0x20, "GSYM") - -/* Function name for BSD Fortran. Only the name is significant. - To find the address, look in the corresponding external symbol. */ -__define_stab (N_FNAME, 0x22, "FNAME") - -/* Function name or text-segment variable for C. Value is its address. - Desc is supposedly starting line number, but GCC doesn't set it - and DBX seems not to miss it. */ -__define_stab (N_FUN, 0x24, "FUN") - -/* Data-segment variable with internal linkage. Value is its address. - "Static Sym". */ -__define_stab (N_STSYM, 0x26, "STSYM") - -/* BSS-segment variable with internal linkage. Value is its address. */ -__define_stab (N_LCSYM, 0x28, "LCSYM") - -/* Name of main routine. Only the name is significant. - This is not used in C. */ -__define_stab (N_MAIN, 0x2a, "MAIN") - -/* Global symbol in Pascal. - Supposedly the value is its line number; I'm skeptical. */ -__define_stab (N_PC, 0x30, "PC") - -/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ -__define_stab (N_NSYMS, 0x32, "NSYMS") - -/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ -__define_stab (N_NOMAP, 0x34, "NOMAP") - -/* New stab from Solaris. I don't know what it means, but it - don't seem to contain useful information. */ -__define_stab (N_OBJ, 0x38, "OBJ") - -/* New stab from Solaris. I don't know what it means, but it - don't seem to contain useful information. Possibly related to the - optimization flags used in this module. */ -__define_stab (N_OPT, 0x3c, "OPT") - -/* Register variable. Value is number of register. */ -__define_stab (N_RSYM, 0x40, "RSYM") - -/* Modula-2 compilation unit. Can someone say what info it contains? */ -__define_stab (N_M2C, 0x42, "M2C") - -/* Line number in text segment. Desc is the line number; - value is corresponding address. */ -__define_stab (N_SLINE, 0x44, "SLINE") - -/* Similar, for data segment. */ -__define_stab (N_DSLINE, 0x46, "DSLINE") - -/* Similar, for bss segment. */ -__define_stab (N_BSLINE, 0x48, "BSLINE") - -/* Sun's source-code browser stabs. ?? Don't know what the fields are. - Supposedly the field is "path to associated .cb file". THIS VALUE - OVERLAPS WITH N_BSLINE! */ -__define_stab (N_BROWS, 0x48, "BROWS") - -/* GNU Modula-2 definition module dependency. Value is the modification time - of the definition file. Other is non-zero if it is imported with the - GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there - are enough empty fields? */ -__define_stab(N_DEFD, 0x4a, "DEFD") - -/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 - and one is for C++. Still,... */ -/* GNU C++ exception variable. Name is variable name. */ -__define_stab (N_EHDECL, 0x50, "EHDECL") -/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ -__define_stab (N_MOD2, 0x50, "MOD2") - -/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if - this entry is immediately followed by a CAUGHT stab saying what exception - was caught. Multiple CAUGHT stabs means that multiple exceptions - can be caught here. If Desc is 0, it means all exceptions are caught - here. */ -__define_stab (N_CATCH, 0x54, "CATCH") - -/* Structure or union element. Value is offset in the structure. */ -__define_stab (N_SSYM, 0x60, "SSYM") - -/* Name of main source file. - Value is starting text address of the compilation. */ -__define_stab (N_SO, 0x64, "SO") - -/* Automatic variable in the stack. Value is offset from frame pointer. - Also used for type descriptions. */ -__define_stab (N_LSYM, 0x80, "LSYM") - -/* Beginning of an include file. Only Sun uses this. - In an object file, only the name is significant. - The Sun linker puts data into some of the other fields. */ -__define_stab (N_BINCL, 0x82, "BINCL") - -/* Name of sub-source file (#include file). - Value is starting text address of the compilation. */ -__define_stab (N_SOL, 0x84, "SOL") - -/* Parameter variable. Value is offset from argument pointer. - (On most machines the argument pointer is the same as the frame pointer. */ -__define_stab (N_PSYM, 0xa0, "PSYM") - -/* End of an include file. No name. - This and N_BINCL act as brackets around the file's output. - In an object file, there is no significant data in this entry. - The Sun linker puts data into some of the fields. */ -__define_stab (N_EINCL, 0xa2, "EINCL") - -/* Alternate entry point. Value is its address. */ -__define_stab (N_ENTRY, 0xa4, "ENTRY") - -/* Beginning of lexical block. - The desc is the nesting level in lexical blocks. - The value is the address of the start of the text for the block. - The variables declared inside the block *precede* the N_LBRAC symbol. */ -__define_stab (N_LBRAC, 0xc0, "LBRAC") - -/* Place holder for deleted include file. Replaces a N_BINCL and everything - up to the corresponding N_EINCL. The Sun linker generates these when - it finds multiple identical copies of the symbols from an include file. - This appears only in output from the Sun linker. */ -__define_stab (N_EXCL, 0xc2, "EXCL") - -/* Modula-2 scope information. Can someone say what info it contains? */ -__define_stab (N_SCOPE, 0xc4, "SCOPE") - -/* End of a lexical block. Desc matches the N_LBRAC's desc. - The value is the address of the end of the text for the block. */ -__define_stab (N_RBRAC, 0xe0, "RBRAC") - -/* Begin named common block. Only the name is significant. */ -__define_stab (N_BCOMM, 0xe2, "BCOMM") - -/* End named common block. Only the name is significant - (and it should match the N_BCOMM). */ -__define_stab (N_ECOMM, 0xe4, "ECOMM") - -/* End common (local name): value is address. - I'm not sure how this is used. */ -__define_stab (N_ECOML, 0xe8, "ECOML") - -/* These STAB's are used on Gould systems for Non-Base register symbols - or something like that. FIXME. I have assigned the values at random - since I don't have a Gould here. Fixups from Gould folk welcome... */ -__define_stab (N_NBTEXT, 0xF0, "NBTEXT") -__define_stab (N_NBDATA, 0xF2, "NBDATA") -__define_stab (N_NBBSS, 0xF4, "NBBSS") -__define_stab (N_NBSTS, 0xF6, "NBSTS") -__define_stab (N_NBLCS, 0xF8, "NBLCS") - -/* Second symbol entry containing a length-value for the preceding entry. - The value is the length. */ -__define_stab (N_LENG, 0xfe, "LENG") - -/* The above information, in matrix format. - - STAB MATRIX - _________________________________________________ - | 00 - 1F are not dbx stab symbols | - | In most cases, the low bit is the EXTernal bit| - - | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | - | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | - - | 08 BSS | 0A INDR | 0C FN_SEQ | 0E | - | 09 |EXT | 0B | 0D | 0F | - - | 10 | 12 COMM | 14 SETA | 16 SETT | - | 11 | 13 | 15 | 17 | - - | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| - | 19 | 1B | 1D | 1F FN | - - |_______________________________________________| - | Debug entries with bit 01 set are unused. | - | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | - | 28 LCSYM | 2A MAIN | 2C | 2E | - | 30 PC | 32 NSYMS | 34 NOMAP | 36 | - | 38 OBJ | 3A | 3C OPT | 3E | - | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | - | 48 BSLINE*| 4A DEFD | 4C | 4E | - | 50 EHDECL*| 52 | 54 CATCH | 56 | - | 58 | 5A | 5C | 5E | - | 60 SSYM | 62 | 64 SO | 66 | - | 68 | 6A | 6C | 6E | - | 70 | 72 | 74 | 76 | - | 78 | 7A | 7C | 7E | - | 80 LSYM | 82 BINCL | 84 SOL | 86 | - | 88 | 8A | 8C | 8E | - | 90 | 92 | 94 | 96 | - | 98 | 9A | 9C | 9E | - | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | - | A8 | AA | AC | AE | - | B0 | B2 | B4 | B6 | - | B8 | BA | BC | BE | - | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | - | C8 | CA | CC | CE | - | D0 | D2 | D4 | D6 | - | D8 | DA | DC | DE | - | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | - | E8 ECOML | EA | EC | EE | - | F0 | F2 | F4 | F6 | - | F8 | FA | FC | FE LENG | - +-----------------------------------------------+ - * 50 EHDECL is also MOD2. - * 48 BSLINE is also BROWS. - */ diff --git a/stab.h b/stab.h deleted file mode 100644 index 80bd594a..00000000 --- a/stab.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __GNU_STAB__ - -/* Indicate the GNU stab.h is in use. */ - -#define __GNU_STAB__ - -#define __define_stab(NAME, CODE, STRING) NAME=CODE, - -enum __stab_debug_code -{ -#include "stab.def" -LAST_UNUSED_STAB_CODE -}; - -#undef __define_stab - -#endif /* __GNU_STAB_ */ diff --git a/tcc.c b/tcc.c deleted file mode 100644 index c6bb4534..00000000 --- a/tcc.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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 "config.h" -#include "tcc.h" -#include "tcctools.c" - -static const char help[] = - "Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n" - "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n" - " tcc [options...] -run infile (or --) [arguments...]\n" - "General options:\n" - " -c compile only - generate an object file\n" - " -o outfile set output filename\n" - " -run run compiled source\n" - " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" - " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" - " -w disable all warnings\n" - " -v --version show version\n" - " -vv show search paths or loaded files\n" - " -h -hh show this, show more help\n" - " -bench show compilation statistics\n" - " - use stdin pipe as infile\n" - " @listfile read arguments from listfile\n" - "Preprocessor options:\n" - " -Idir add include path 'dir'\n" - " -Dsym[=val] define 'sym' with value 'val'\n" - " -Usym undefine 'sym'\n" - " -E preprocess only\n" - "Linker options:\n" - " -Ldir add library path 'dir'\n" - " -llib link with dynamic or static library 'lib'\n" - " -r generate (relocatable) object file\n" - " -shared generate a shared library/dll\n" - " -rdynamic export all global symbols to dynamic linker\n" - " -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 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 -#ifdef CONFIG_TCC_BACKTRACE - " -bt[N] link with backtrace (stack dump) support [show max N callers]\n" -#endif - "Misc. options:\n" - " -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n" - " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n" - " -nostdinc do not use standard system include paths\n" - " -nostdlib do not link with standard crt and libraries\n" - " -Bdir set tcc's private include/library dir\n" - " -M[M]D generate make dependency file [ignore system files]\n" - " -M[M] as above but no other output\n" - " -MF file specify dependency file name\n" - "Tools:\n" - " create library : tcc -ar [crstvx] lib [files]\n" - ; - -static const char help2[] = - "Tiny C Compiler "PACKAGE_VERSION" - More Options\n" - "Special options:\n" - " -P -P1 with -E: no/alternative #line output\n" - " -dD -dM with -E: output #define directives\n" - " -pthread same as -D_REENTRANT and -lpthread\n" - " -On same as -D__OPTIMIZE__ for n > 0\n" - " -Wp,-opt same as -opt\n" - " -include file include 'file' above each input file\n" - " -isystem dir add 'dir' to system include path\n" - " -static link to static libraries (not recommended)\n" - " -dumpversion print version\n" - " -print-search-dirs print search paths\n" - " -dt with -run/-E: auto-define 'test_...' macros\n" - "Ignored options:\n" - " -arch -C --param -pedantic -pipe -s -traditional\n" - "-W[no-]... warnings:\n" - " all turn on some (*) warnings\n" - " error[=warning] stop after warning (any or specified)\n" - " write-strings strings are const\n" - " unsupported warn about ignored options, pragmas, etc.\n" - " implicit-function-declaration warn for missing prototype (*)\n" - " discarded-qualifiers warn when const is dropped (*)\n" - "-f[no-]... flags:\n" - " unsigned-char default char is unsigned\n" - " signed-char default char is signed\n" - " common use common section instead of bss\n" - " leading-underscore decorate extern symbols\n" - " ms-extensions allow anonymous struct in struct\n" - " dollars-in-identifiers allow '$' in C symbols\n" - " reverse-funcargs evaluate function arguments right to left\n" - " gnu89-inline 'extern inline' is like 'static inline'\n" - " asynchronous-unwind-tables create eh_frame section [on]\n" - " test-coverage create code coverage code\n" - "-m... target specific options:\n" - " ms-bitfields use MSVC bitfield layout\n" - "-Wl,... linker options:\n" - " -nostdlib do not link with standard crt/libs\n" - " -[no-]whole-archive load lib(s) fully/only as needed\n" - " -export-all-symbols same as -rdynamic\n" - " -export-dynamic same as -rdynamic\n" - " -image-base= -Ttext= set base address of executable\n" - " -section-alignment= set section alignment in executable\n" - " -rpath= set dynamic library search path\n" - " -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n" - " -soname= set DT_SONAME elf tag\n" - " -Bsymbolic set DT_SYMBOLIC elf tag\n" - " -oformat=[elf32/64-* binary] set executable output format\n" - " -init= -fini= -Map= -as-needed -O (ignored)\n" - "Predefined macros:\n" - " tcc -E -dM - < /dev/null\n" - "See also the manual for more details.\n" - ; - -static const char version[] = - "tcc version "PACKAGE_VERSION - " (i386)\n" - ; - -static void print_dirs(const char *msg, char **paths, int nb_paths) -{ - int i; - printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); - for(i = 0; i < nb_paths; i++) - printf(" %s\n", paths[i]); -} - -static void print_search_dirs(TCCState *s) -{ - printf("install: %s\n", s->tcc_lib_path); - /* print_dirs("programs", NULL, 0); */ - print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); - print_dirs("libraries", s->library_paths, s->nb_library_paths); - printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1); - print_dirs("crt", s->crt_paths, s->nb_crt_paths); - printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); -} - -static void set_environment(TCCState *s) -{ - char * path; - - path = getenv("C_INCLUDE_PATH"); - if(path != NULL) { - tcc_add_sysinclude_path(s, path); - } - path = getenv("CPATH"); - if(path != NULL) { - tcc_add_include_path(s, path); - } - path = getenv("LIBRARY_PATH"); - if(path != NULL) { - tcc_add_library_path(s, path); - } -} - -static char *default_outputfile(TCCState *s, const char *first_file) -{ - char buf[1024]; - char *ext; - const char *name = "a"; - - if (first_file && strcmp(first_file, "-")) - name = tcc_basename(first_file); - snprintf(buf, sizeof(buf), "%s", name); - ext = tcc_fileextension(buf); - if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext) - strcpy(ext, ".obj"); - else - strcpy(buf, "a.out"); - return tcc_strdup(buf); -} - -static unsigned getclock_ms(void) -{ -#ifdef _WIN32 - return GetTickCount(); -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec*1000 + (tv.tv_usec+500)/1000; -#endif -} - -int main(int argc0, char **argv0) -{ - TCCState *s, *s1; - int ret, opt, n = 0, t = 0, done; - unsigned start_time = 0, end_time = 0; - const char *first_file; - int argc; char **argv; - FILE *ppfp = stdout; - -redo: - argc = argc0, argv = argv0; - s = s1 = tcc_new(); -#ifdef CONFIG_TCC_SWITCHES /* predefined options */ - tcc_set_options(s, CONFIG_TCC_SWITCHES); -#endif - opt = tcc_parse_args(s, &argc, &argv, 1); - if (opt < 0) - return 1; - - if (n == 0) { - if (opt == OPT_HELP) { - fputs(help, stdout); - if (!s->verbose) - return 0; - ++opt; - } - if (opt == OPT_HELP2) { - fputs(help2, stdout); - return 0; - } - if (opt == OPT_M32 || opt == OPT_M64) - return tcc_tool_cross(s, argv, opt); - if (s->verbose) - printf("%s", version); - if (opt == OPT_AR) - return tcc_tool_ar(s, argc, argv); - if (opt == OPT_V) - return 0; - if (opt == OPT_PRINT_DIRS) { - /* initialize search dirs */ - set_environment(s); - tcc_set_output_type(s, TCC_OUTPUT_MEMORY); - print_search_dirs(s); - return 0; - } - - if (s->nb_files == 0) { - tcc_error_noabort("no input files"); - } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { - if (s->outfile && 0!=strcmp("-",s->outfile)) { - ppfp = fopen(s->outfile, "wb"); - if (!ppfp) - tcc_error_noabort("could not write '%s'", s->outfile); - } - } else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { - if (s->nb_libraries) - tcc_error_noabort("cannot specify libraries with -c"); - else if (s->nb_files > 1 && s->outfile) - tcc_error_noabort("cannot specify output file with -c many files"); - } - if (s->nb_errors) - return 1; - if (s->do_bench) - start_time = getclock_ms(); - } - - set_environment(s); - if (s->output_type == 0) - s->output_type = TCC_OUTPUT_EXE; - tcc_set_output_type(s, s->output_type); - s->ppfp = ppfp; - - if ((s->output_type == TCC_OUTPUT_MEMORY - || s->output_type == TCC_OUTPUT_PREPROCESS) - && (s->dflag & 16)) { /* -dt option */ - if (t) - s->dflag |= 32; - s->run_test = ++t; - if (n) - --n; - } - - /* compile or add each files or library */ - first_file = NULL; - do { - struct filespec *f = s->files[n]; - s->filetype = f->type; - if (f->type & AFF_TYPE_LIB) { - ret = tcc_add_library(s, f->name); - } else { - if (1 == s->verbose) - printf("-> %s\n", f->name); - if (!first_file) - first_file = f->name; - ret = tcc_add_file(s, f->name); - } - } while (++n < s->nb_files - && 0 == ret - && (s->output_type != TCC_OUTPUT_OBJ || s->option_r)); - - if (s->do_bench) - end_time = getclock_ms(); - - if (s->run_test) { - t = 0; - } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { - ; - } else if (0 == ret) { - if (s->output_type == TCC_OUTPUT_MEMORY) { - } else { - if (!s->outfile) - s->outfile = default_outputfile(s, first_file); - if (!s->just_deps) - ret = tcc_output_file(s, s->outfile); - if (!ret && s->gen_deps) - gen_makedeps(s, s->outfile, s->deps_outfile); - } - } - - done = 1; - if (t) - done = 0; /* run more tests with -dt -run */ - else if (ret) { - if (s->nb_errors) - ret = 1; - /* else keep the original exit code from tcc_run() */ - } else if (n < s->nb_files) - done = 0; /* compile more files with -c */ - else if (s->do_bench) - tcc_print_stats(s, end_time - start_time); - - tcc_delete(s); - - if (!done) - goto redo; - if (ppfp && ppfp != stdout) - fclose(ppfp); - return ret; -} diff --git a/tcc/Makefile.am b/tcc/Makefile.am new file mode 100644 index 00000000..a268a1df --- /dev/null +++ b/tcc/Makefile.am @@ -0,0 +1,5 @@ +bin_PROGRAMS = tcc + +tcc_SOURCES = tcc.c tcctools.c +tcc_LDADD = ../libtcc/libtcc.a +tcc_CPPFLAGS = -I$(top_srcdir) diff --git a/tcc/tcc.c b/tcc/tcc.c new file mode 100644 index 00000000..0d97bb3b --- /dev/null +++ b/tcc/tcc.c @@ -0,0 +1,314 @@ +/* + * 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 "config.h" +#include "libtcc/tcc.h" +#include "tcctools.h" + +static const char HELP_STR[] = + "Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n" + "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n" + " tcc [options...] -run infile (or --) [arguments...]\n" + "General options:\n" + " -c compile only - generate an object file\n" + " -o outfile set output filename\n" + " -run run compiled source\n" + " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" + " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" + " -w disable all warnings\n" + " -v --version show version\n" + " -vv show search paths or loaded files\n" + " -h -hh show this, show more help\n" + " -bench show compilation statistics\n" + " - use stdin pipe as infile\n" + " @listfile read arguments from listfile\n" + "Preprocessor options:\n" + " -Idir add include path 'dir'\n" + " -Dsym[=val] define 'sym' with value 'val'\n" + " -Usym undefine 'sym'\n" + " -E preprocess only\n" + "Linker options:\n" + " -Ldir add library path 'dir'\n" + " -llib link with dynamic or static library 'lib'\n" + " -r generate (relocatable) object file\n" + " -shared generate a shared library/dll\n" + " -rdynamic export all global symbols to dynamic linker\n" + " -soname set name for shared library to be used at runtime\n" + " -Wl,-opt[=val] set linker option (see tcc -hh)\n" + "Misc. options:\n" + " -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n" + " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n" + " -nostdinc do not use standard system include paths\n" + " -nostdlib do not link with standard crt and libraries\n" + " -Bdir set tcc's private include/library dir\n" + " -M[M]D generate make dependency file [ignore system files]\n" + " -M[M] as above but no other output\n" + " -MF file specify dependency file name\n" + "Tools:\n" + " create library : tcc -ar [crstvx] lib [files]\n" + ; + +static const char HELP_MORE_STR[] = + "Tiny C Compiler "PACKAGE_VERSION" - More Options\n" + "Special options:\n" + " -P -P1 with -E: no/alternative #line output\n" + " -dD -dM with -E: output #define directives\n" + " -pthread same as -D_REENTRANT and -lpthread\n" + " -On same as -D__OPTIMIZE__ for n > 0\n" + " -Wp,-opt same as -opt\n" + " -include file include 'file' above each input file\n" + " -isystem dir add 'dir' to system include path\n" + " -static link to static libraries (not recommended)\n" + " -dumpversion print version\n" + " -print-search-dirs print search paths\n" + "Ignored options:\n" + " -arch -C --param -pedantic -pipe -s -traditional\n" + "-W[no-]... warnings:\n" + " all turn on some (*) warnings\n" + " error[=warning] stop after warning (any or specified)\n" + " write-strings strings are const\n" + " unsupported warn about ignored options, pragmas, etc.\n" + " implicit-function-declaration warn for missing prototype (*)\n" + " discarded-qualifiers warn when const is dropped (*)\n" + "-f[no-]... flags:\n" + " unsigned-char default char is unsigned\n" + " signed-char default char is signed\n" + " common use common section instead of bss\n" + " leading-underscore decorate extern symbols\n" + " ms-extensions allow anonymous struct in struct\n" + " dollars-in-identifiers allow '$' in C symbols\n" + " reverse-funcargs evaluate function arguments right to left\n" + " gnu89-inline 'extern inline' is like 'static inline'\n" + " asynchronous-unwind-tables create eh_frame section [on]\n" + "-m... target specific options:\n" + " ms-bitfields use MSVC bitfield layout\n" + "-Wl,... linker options:\n" + " -nostdlib do not link with standard crt/libs\n" + " -[no-]whole-archive load lib(s) fully/only as needed\n" + " -export-all-symbols same as -rdynamic\n" + " -export-dynamic same as -rdynamic\n" + " -image-base= -Ttext= set base address of executable\n" + " -section-alignment= set section alignment in executable\n" + " -rpath= set dynamic library search path\n" + " -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n" + " -soname= set DT_SONAME elf tag\n" + " -Bsymbolic set DT_SYMBOLIC elf tag\n" + " -oformat=[coff,binary] set executable output format\n" + " -init= -fini= -Map= -as-needed -O (ignored)\n" + "Predefined macros:\n" + " tcc -E -dM - < /dev/null\n" + "See also the manual for more details.\n" + ; + +static const char VERSION_STR[] = + "tcc version "PACKAGE_VERSION" (i386)\n"; + +static void print_dirs(const char *msg, char **paths, int nb_paths) +{ + int i; + printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); + for(i = 0; i < nb_paths; i++) + printf(" %s\n", paths[i]); +} + +static void print_search_dirs(TCCState *s) +{ + printf("install: %s\n", s->tcc_lib_path); + /* print_dirs("programs", NULL, 0); */ + print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); + print_dirs("libraries", s->library_paths, s->nb_library_paths); + printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1); + print_dirs("crt", s->crt_paths, s->nb_crt_paths); + printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); +} + +static void set_environment(TCCState *s) +{ + char * path; + + path = getenv("C_INCLUDE_PATH"); + if(path != NULL) { + tcc_add_sysinclude_path(s, path); + } + path = getenv("CPATH"); + if(path != NULL) { + tcc_add_include_path(s, path); + } + path = getenv("LIBRARY_PATH"); + if(path != NULL) { + tcc_add_library_path(s, path); + } +} + +static char *default_outputfile(TCCState *s, const char *first_file) +{ + char buf[1024]; + char *ext; + const char *name = "a"; + + if (first_file && strcmp(first_file, "-")) + name = tcc_basename(first_file); + snprintf(buf, sizeof(buf), "%s", name); + ext = tcc_fileextension(buf); + if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext) + strcpy(ext, ".obj"); + else + strcpy(buf, "a.out"); + return tcc_strdup(buf); +} + +static unsigned getclock_ms(void) +{ +#ifdef _WIN32 + return GetTickCount(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000 + (tv.tv_usec+500)/1000; +#endif +} + +int main(int argc0, char **argv0) +{ + TCCState *s, *s1; + int ret, opt, n = 0, t = 0, done; + unsigned start_time = 0, end_time = 0; + const char *first_file; + int argc; char **argv; + FILE *ppfp = stdout; + +redo: + argc = argc0, argv = argv0; + s = s1 = tcc_new(); +#ifdef CONFIG_TCC_SWITCHES /* predefined options */ + tcc_set_options(s, CONFIG_TCC_SWITCHES); +#endif + opt = tcc_parse_args(s, &argc, &argv, 1); + if (opt < 0) + return 1; + + if (n == 0) { + if (opt == OPT_HELP) { + fputs(HELP_STR, stdout); + if (!s->verbose) + return 0; + ++opt; + } + if (opt == OPT_HELP2) { + fputs(HELP_MORE_STR, stdout); + return 0; + } + if (opt == OPT_M32 || opt == OPT_M64) + return tcc_tool_cross(s, argv, opt); + if (s->verbose) + printf("%s", VERSION_STR); + if (opt == OPT_AR) + return tcc_tool_ar(s, argc, argv); + if (opt == OPT_V) + return 0; + if (opt == OPT_PRINT_DIRS) { + /* initialize search dirs */ + set_environment(s); + tcc_set_output_type(s, TCC_OUTPUT_MEMORY); + print_search_dirs(s); + return 0; + } + + if (s->nb_files == 0) { + tcc_error_noabort("no input files"); + } else if (s->output_type == TCC_OUTPUT_PREPROCESS) { + if (s->outfile && 0!=strcmp("-",s->outfile)) { + ppfp = fopen(s->outfile, "wb"); + if (!ppfp) + tcc_error_noabort("could not write '%s'", s->outfile); + } + } else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { + if (s->nb_libraries) + tcc_error_noabort("cannot specify libraries with -c"); + else if (s->nb_files > 1 && s->outfile) + tcc_error_noabort("cannot specify output file with -c many files"); + } + if (s->nb_errors) + return 1; + if (s->do_bench) + start_time = getclock_ms(); + } + + set_environment(s); + if (s->output_type == 0) + s->output_type = TCC_OUTPUT_EXE; + tcc_set_output_type(s, s->output_type); + s->ppfp = ppfp; + + /* compile or add each files or library */ + first_file = NULL; + do { + struct filespec *f = s->files[n]; + s->filetype = f->type; + if (f->type & AFF_TYPE_LIB) { + ret = tcc_add_library(s, f->name); + } else { + if (1 == s->verbose) + printf("-> %s\n", f->name); + if (!first_file) + first_file = f->name; + ret = tcc_add_file(s, f->name); + } + } while (++n < s->nb_files + && 0 == ret + && (s->output_type != TCC_OUTPUT_OBJ || s->option_r)); + + if (s->do_bench) + end_time = getclock_ms(); + + if (s->output_type == TCC_OUTPUT_PREPROCESS) { + ; + } else if (0 == ret) { + if (s->output_type == TCC_OUTPUT_MEMORY) { + } else { + if (!s->outfile) + s->outfile = default_outputfile(s, first_file); + if (!s->just_deps) + ret = tcc_output_file(s, s->outfile); + if (!ret && s->gen_deps) + gen_makedeps(s, s->outfile, s->deps_outfile); + } + } + + done = 1; + if (t) + done = 0; /* run more tests with -dt -run */ + else if (ret) { + if (s->nb_errors) + ret = 1; + /* else keep the original exit code from tcc_run() */ + } else if (n < s->nb_files) + done = 0; /* compile more files with -c */ + else if (s->do_bench) + tcc_print_stats(s, end_time - start_time); + + tcc_delete(s); + + if (!done) + goto redo; + if (ppfp && ppfp != stdout) + fclose(ppfp); + return ret; +} diff --git a/tcc/tcc_new.c b/tcc/tcc_new.c new file mode 100644 index 00000000..db8e12b0 --- /dev/null +++ b/tcc/tcc_new.c @@ -0,0 +1,134 @@ +/* + * TCC - Tiny C Compiler + * + * Copyright (c) 2001-2004 Fabrice Bellard + * Copyright (c) 2025 d0p1 + * + * 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 + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "libtcc.h" + +static const char help_str[] = + "Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n" + "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n" + "General options:\n" + " -c compile only - generate an object file\n" + " -o outfile set output filename\n" + " -run run compiled source\n" + " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n" + " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n" + " -w disable all warnings\n" + " -v --version show version\n" + " -vv show search paths or loaded files\n" + " -h -hh show this, show more help\n" + " -bench show compilation statistics\n" + " - use stdin pipe as infile\n" + " @listfile read arguments from listfile\n" + "Preprocessor options:\n" + " -Idir add include path 'dir'\n" + " -Dsym[=val] define 'sym' with value 'val'\n" + " -Usym undefine 'sym'\n" + " -E preprocess only\n" + "Linker options:\n" + " -Ldir add library path 'dir'\n" + " -llib link with dynamic or static library 'lib'\n" + " -r generate (relocatable) object file\n" + " -rdynamic export all global symbols to dynamic linker\n" + " -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 stab runtime debug info\n" + " -gdwarf[-x] generate dwarf runtime debug info\n" + "Misc. options:\n" + " -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n" + " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n" + " -nostdinc do not use standard system include paths\n" + " -nostdlib do not link with standard crt and libraries\n" + " -Bdir set tcc's private include/library dir\n" + " -M[M]D generate make dependency file [ignore system files]\n" + " -M[M] as above but no other output\n" + " -MF file specify dependency file name\n" + "Tools:\n" + " create library : tcc -ar [crstvx] lib [files]\n" + ; + +static const char help_more_str[] = + "Tiny C Compiler "PACKAGE_VERSION" - More Options\n" + "Special options:\n" + " -P -P1 with -E: no/alternative #line output\n" + " -dD -dM with -E: output #define directives\n" + " -pthread same as -D_REENTRANT and -lpthread\n" + " -On same as -D__OPTIMIZE__ for n > 0\n" + " -Wp,-opt same as -opt\n" + " -include file include 'file' above each input file\n" + " -isystem dir add 'dir' to system include path\n" + " -static link to static libraries (not recommended)\n" + " -dumpversion print version\n" + " -print-search-dirs print search paths\n" + " -dt with -run/-E: auto-define 'test_...' macros\n" + "Ignored options:\n" + " -arch -C --param -pedantic -pipe -s -traditional\n" + "-W[no-]... warnings:\n" + " all turn on some (*) warnings\n" + " error[=warning] stop after warning (any or specified)\n" + " write-strings strings are const\n" + " unsupported warn about ignored options, pragmas, etc.\n" + " implicit-function-declaration warn for missing prototype (*)\n" + " discarded-qualifiers warn when const is dropped (*)\n" + "-f[no-]... flags:\n" + " unsigned-char default char is unsigned\n" + " signed-char default char is signed\n" + " common use common section instead of bss\n" + " leading-underscore decorate extern symbols\n" + " ms-extensions allow anonymous struct in struct\n" + " dollars-in-identifiers allow '$' in C symbols\n" + " reverse-funcargs evaluate function arguments right to left\n" + " gnu89-inline 'extern inline' is like 'static inline'\n" + " asynchronous-unwind-tables create eh_frame section [on]\n" + " test-coverage create code coverage code\n" + "-m... target specific options:\n" + " ms-bitfields use MSVC bitfield layout\n" + "-Wl,... linker options:\n" + " -nostdlib do not link with standard crt/libs\n" + " -[no-]whole-archive load lib(s) fully/only as needed\n" + " -export-all-symbols same as -rdynamic\n" + " -export-dynamic same as -rdynamic\n" + " -image-base= -Ttext= set base address of executable\n" + " -section-alignment= set section alignment in executable\n" + " -rpath= set dynamic library search path\n" + " -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n" + " -soname= set DT_SONAME elf tag\n" + " -Bsymbolic set DT_SYMBOLIC elf tag\n" + " -oformat=[coff,binary] set executable output format\n" + " -init= -fini= -Map= -as-needed -O (ignored)\n" + "Predefined macros:\n" + " tcc -E -dM - < /dev/null\n" + "See also the manual for more details.\n" + ; + +static const char version_str[] = "tcc version "PACKAGE_VERSION" (i386)\n"; + +int +main(int argc, char *argv[]) +{ + TCCState *s; +} \ No newline at end of file diff --git a/tcctools.c b/tcc/tcctools.c similarity index 99% rename from tcctools.c rename to tcc/tcctools.c index eccb22af..e36a388a 100644 --- a/tcctools.c +++ b/tcc/tcctools.c @@ -28,7 +28,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "tcc.h" +#include "libtcc/tcc.h" //#define ARMAG "!\n" #define ARFMAG "`\n" diff --git a/tcc/tcctools.h b/tcc/tcctools.h new file mode 100644 index 00000000..bcb0a7cf --- /dev/null +++ b/tcc/tcctools.h @@ -0,0 +1,10 @@ +#ifndef TCC_TCCTOOLS_H +# define TCC_TCCTOOLS_H 1 + +# include "libtcc/libtcc.h" + +int tcc_tool_ar(TCCState *s1, int argc, char **argv); +int tcc_tool_cross(TCCState *s1, char **argv, int target); +int gen_makedeps(TCCState *s1, const char *target, const char *filename); + +#endif /* !TCC_TCCTOOLS_H */ \ No newline at end of file diff --git a/tccdbg.c b/tccdbg.c deleted file mode 100644 index 711f1871..00000000 --- a/tccdbg.c +++ /dev/null @@ -1,2482 +0,0 @@ -/* - * 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 */ - -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; - - struct _debug_anon_hash { - Sym *type; - int n_debug_type; - int *debug_type; - } *debug_anon_hash; - - int n_debug_hash; - int n_debug_anon_hash; - - struct _debug_info { - int start; - int end; - 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; - - /* 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 s1->dState->debug_hash -#define debug_anon_hash s1->dState->debug_anon_hash -#define n_debug_hash s1->dState->n_debug_hash -#define n_debug_anon_hash s1->dState->n_debug_anon_hash -#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 tcov_data s1->dState->tcov_data - -#define FDE_ENCODING (DW_EH_PE_udata4 | DW_EH_PE_signed | DW_EH_PE_pcrel) - -/* ------------------------------------------------------------------------- */ -static void 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) { - 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); - 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); - } -} - -/* put stab debug information */ -static void put_stabs(TCCState *s1, const char *str, int type, int other, int desc, - unsigned long value) -{ - Stab_Sym *sym; - - unsigned offset; - if (type == N_SLINE - && (offset = stab_section->data_offset) - && (sym = (Stab_Sym*)(stab_section->data + offset) - 1) - && sym->n_type == type - && sym->n_value == value) { - /* just update line_number in previous entry */ - sym->n_desc = desc; - return; - } - - sym = section_ptr_add(stab_section, sizeof(Stab_Sym)); - if (str) { - sym->n_strx = put_elf_str(stab_section->link, str); - } else { - sym->n_strx = 0; - } - sym->n_type = type; - sym->n_other = other; - sym->n_desc = desc; - sym->n_value = value; -} - -static void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, - unsigned long value, Section *sec, int sym_index) -{ - put_elf_reloc(symtab_section, stab_section, - stab_section->data_offset + 8, - sizeof ((Stab_Sym*)0)->n_value == PTR_SIZE ? R_DATA_PTR : R_DATA_32, - sym_index); - put_stabs(s1, str, type, other, desc, value); -} - -static void put_stabn(TCCState *s1, int type, int other, int desc, int value) -{ - put_stabs(s1, NULL, type, other, desc, value); -} - -/* ------------------------------------------------------------------------- */ -#define dwarf_data1(s,data) \ - (*(uint8_t*)section_ptr_add((s), 1) = (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) -{ - TCCState *s1 = s->s1; - 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) -{ - TCCState *s1 = s->s1; - 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) -{ - TCCState *s1 = s->s1; - 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_32DW, sym, - PTR_SIZE == 4 ? 0 : offset); - dwarf_data4(s, PTR_SIZE == 4 ? offset : 0); -} - -static void dwarf_strp(Section *s, const char *str) -{ - TCCState *s1 = s->s1; - dwarf_string(s, dwarf_str_section, dwarf_sym.str, str); -} - -static void dwarf_line_strp(Section *s, const char *str) -{ - TCCState *s1 = s->s1; - dwarf_string(s, dwarf_line_str_section, dwarf_sym.line_str, str); -} - -static void dwarf_line_op(TCCState *s1, 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, j; - char *filename; - int index_offset = s1->dwarf < 5; - - if (!strcmp(file->filename, "")) { - dwarf_line.cur_file = 1; - 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 + index_offset; - return; - } - i = -index_offset; - filename = file->filename; - } - else { - char *undo = filename; - char *dir = file->filename; - - *filename++ = '\0'; - for (i = 0; i < dwarf_line.dir_size; i++) - if (strcmp(dwarf_line.dir_table[i], dir) == 0) { - for (j = 1; j < dwarf_line.filename_size; j++) - if (dwarf_line.filename_table[j].dir_entry - index_offset - == i && - strcmp(dwarf_line.filename_table[j].name, - filename) == 0) { - *undo = '/'; - dwarf_line.cur_file = j + index_offset; - return; - } - 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 = '/'; - } - 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 + index_offset; - dwarf_line.filename_table[dwarf_line.filename_size].name = - tcc_strdup(filename); - dwarf_line.cur_file = dwarf_line.filename_size++ + index_offset; - 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 size = 0; - long long end = value >> 63; - unsigned char last = end & 0x40; - unsigned char byte; - - do { - byte = value & 0x7f; - value >>= 7; - size++; - } while (value != end || (byte & 0x40) != last); - return size; -} - -static void dwarf_uleb128 (Section *s, unsigned long long value) -{ - do { - unsigned char byte = value & 0x7f; - - value >>= 7; - dwarf_data1(s, byte | (value ? 0x80 : 0)); - } while (value != 0); -} - -static void dwarf_sleb128 (Section *s, long long value) -{ - int more; - long long end = value >> 63; - unsigned char last = end & 0x40; - - do { - unsigned char byte = value & 0x7f; - - value >>= 7; - more = value != end || (byte & 0x40) != last; - dwarf_data1(s, byte | (0x80 * more)); - } while (more); -} - -static void dwarf_uleb128_op (TCCState *s1, unsigned long long value) -{ - do { - unsigned char byte = value & 0x7f; - - value >>= 7; - dwarf_line_op(s1, byte | (value ? 0x80 : 0)); - } while (value != 0); -} - -static void dwarf_sleb128_op (TCCState *s1, long long value) -{ - int more; - long long end = value >> 63; - unsigned char last = end & 0x40; - - do { - unsigned char byte = value & 0x7f; - - value >>= 7; - more = value != end || (byte & 0x40) != last; - dwarf_line_op(s1, byte | (0x80 * more)); - } while (more); -} - -#if TCC_EH_FRAME -ST_FUNC void tcc_eh_frame_start(TCCState *s1) -{ - if (!s1->unwind_tables) - return; - eh_frame_section = new_section(s1, ".eh_frame", SHT_PROGBITS, SHF_ALLOC); - - s1->eh_start = eh_frame_section->data_offset; - dwarf_data4(eh_frame_section, 0); // length - dwarf_data4(eh_frame_section, 0); // CIE ID - dwarf_data1(eh_frame_section, 1); // Version - dwarf_data1(eh_frame_section, 'z'); // Augmentation String - dwarf_data1(eh_frame_section, 'R'); - dwarf_data1(eh_frame_section, 0); -#if defined TCC_TARGET_I386 - dwarf_uleb128(eh_frame_section, 1); // code_alignment_factor - dwarf_sleb128(eh_frame_section, -4); // data_alignment_factor - dwarf_uleb128(eh_frame_section, 8); // return address column - dwarf_uleb128(eh_frame_section, 1); // Augmentation len - dwarf_data1(eh_frame_section, FDE_ENCODING); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 4); // r4 (esp) - dwarf_uleb128(eh_frame_section, 4); // ofs 4 - dwarf_data1(eh_frame_section, DW_CFA_offset + 8); // r8 (eip) - dwarf_uleb128(eh_frame_section, 1); // cfa-4 -#elif defined TCC_TARGET_X86_64 - dwarf_uleb128(eh_frame_section, 1); // code_alignment_factor - dwarf_sleb128(eh_frame_section, -8); // data_alignment_factor - dwarf_uleb128(eh_frame_section, 16); // return address column - dwarf_uleb128(eh_frame_section, 1); // Augmentation len - dwarf_data1(eh_frame_section, FDE_ENCODING); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 7); // r7 (rsp) - dwarf_uleb128(eh_frame_section, 8); // ofs 8 - dwarf_data1(eh_frame_section, DW_CFA_offset + 16); // r16 (rip) - dwarf_uleb128(eh_frame_section, 1); // cfa-8 -#elif defined TCC_TARGET_ARM - /* TODO: arm must be compiled with: -funwind-tables */ - /* arm also uses .ARM.extab and .ARM.exidx sections */ - dwarf_uleb128(eh_frame_section, 2); // code_alignment_factor - dwarf_sleb128(eh_frame_section, -4); // data_alignment_factor - dwarf_uleb128(eh_frame_section, 14); // return address column - dwarf_uleb128(eh_frame_section, 1); // Augmentation len - dwarf_data1(eh_frame_section, FDE_ENCODING); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 13); // r13 (sp) - dwarf_uleb128(eh_frame_section, 0); // ofs 0 -#elif defined TCC_TARGET_ARM64 - dwarf_uleb128(eh_frame_section, 4); // code_alignment_factor - dwarf_sleb128(eh_frame_section, -8); // data_alignment_factor - dwarf_uleb128(eh_frame_section, 30); // return address column - dwarf_uleb128(eh_frame_section, 1); // Augmentation len - dwarf_data1(eh_frame_section, FDE_ENCODING); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 31); // x31 (sp) - dwarf_uleb128(eh_frame_section, 0); // ofs 0 -#elif defined TCC_TARGET_RISCV64 - eh_frame_section->data[s1->eh_start + 8] = 3; // version = 3 - dwarf_uleb128(eh_frame_section, 1); // code_alignment_factor - dwarf_sleb128(eh_frame_section, -4); // data_alignment_factor - dwarf_uleb128(eh_frame_section, 1); // return address column - dwarf_uleb128(eh_frame_section, 1); // Augmentation len - dwarf_data1(eh_frame_section, FDE_ENCODING); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 2); // r2 (sp) - dwarf_uleb128(eh_frame_section, 0); // ofs 0 -#endif - while ((eh_frame_section->data_offset - s1->eh_start) & 3) - dwarf_data1(eh_frame_section, DW_CFA_nop); - write32le(eh_frame_section->data + s1->eh_start, // length - eh_frame_section->data_offset - s1->eh_start - 4); -} - -static void tcc_debug_frame_end(TCCState *s1, int size) -{ - int eh_section_sym; - unsigned long fde_start; - - if (!eh_frame_section) - return; - eh_section_sym = dwarf_get_section_sym(text_section); - fde_start = eh_frame_section->data_offset; - dwarf_data4(eh_frame_section, 0); // length - dwarf_data4(eh_frame_section, - fde_start - s1->eh_start + 4); // CIE Pointer -#if defined TCC_TARGET_I386 - dwarf_reloc(eh_frame_section, eh_section_sym, R_386_PC32); -#elif defined TCC_TARGET_X86_64 - dwarf_reloc(eh_frame_section, eh_section_sym, R_X86_64_PC32); -#elif defined TCC_TARGET_ARM - dwarf_reloc(eh_frame_section, eh_section_sym, R_ARM_REL32); -#elif defined TCC_TARGET_ARM64 - dwarf_reloc(eh_frame_section, eh_section_sym, R_AARCH64_PREL32); -#elif defined TCC_TARGET_RISCV64 - dwarf_reloc(eh_frame_section, eh_section_sym, R_RISCV_32_PCREL); -#endif - dwarf_data4(eh_frame_section, func_ind); // PC Begin - dwarf_data4(eh_frame_section, size); // PC Range - dwarf_data1(eh_frame_section, 0); // Augmentation Length -#if defined TCC_TARGET_I386 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 1); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 8); - dwarf_data1(eh_frame_section, DW_CFA_offset + 5); // r5 (ebp) - dwarf_uleb128(eh_frame_section, 2); // cfa-8 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 2); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_register); - dwarf_uleb128(eh_frame_section, 5); // r5 (ebp) - dwarf_data1(eh_frame_section, DW_CFA_advance_loc4); - dwarf_data4(eh_frame_section, size - 5); - dwarf_data1(eh_frame_section, DW_CFA_restore + 5); // r5 (ebp) - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 4); // r4 (esp) - dwarf_uleb128(eh_frame_section, 4); // ofs 4 -#elif defined TCC_TARGET_X86_64 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 1); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 16); - dwarf_data1(eh_frame_section, DW_CFA_offset + 6); // r6 (rbp) - dwarf_uleb128(eh_frame_section, 2); // cfa-16 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 3); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_register); - dwarf_uleb128(eh_frame_section, 6); // r6 (rbp) - dwarf_data1(eh_frame_section, DW_CFA_advance_loc4); - dwarf_data4(eh_frame_section, size - 5); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 7); // r7 (rsp) - dwarf_uleb128(eh_frame_section, 8); // ofs 8 -#elif defined TCC_TARGET_ARM - /* TODO */ - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 2); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 8); - dwarf_data1(eh_frame_section, DW_CFA_offset + 14); // r14 (lr) - dwarf_uleb128(eh_frame_section, 1); - dwarf_data1(eh_frame_section, DW_CFA_offset + 11); // r11 (fp) - dwarf_uleb128(eh_frame_section, 2); - dwarf_data1(eh_frame_section, DW_CFA_advance_loc4); - dwarf_data4(eh_frame_section, size / 2 - 5); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_register); - dwarf_uleb128(eh_frame_section, 11); // r11 (fp) -#elif defined TCC_TARGET_ARM64 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 1); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 224); - dwarf_data1(eh_frame_section, DW_CFA_offset + 29); // x29 (fp) - dwarf_uleb128(eh_frame_section, 28); // cfa-224 - dwarf_data1(eh_frame_section, DW_CFA_offset + 30); // x30 (lr) - dwarf_uleb128(eh_frame_section, 27); // cfa-216 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 3); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 224 + ((-loc + 15) & ~15)); - dwarf_data1(eh_frame_section, DW_CFA_advance_loc4); - dwarf_data4(eh_frame_section, size / 4 - 5); - dwarf_data1(eh_frame_section, DW_CFA_restore + 30); // x30 (lr) - dwarf_data1(eh_frame_section, DW_CFA_restore + 29); // x29 (fp) - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 0); -#elif defined TCC_TARGET_RISCV64 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 4); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 16); // ofs 16 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 8); - dwarf_data1(eh_frame_section, DW_CFA_offset + 1); // r1 (ra, lr) - dwarf_uleb128(eh_frame_section, 2); // cfa-8 - dwarf_data1(eh_frame_section, DW_CFA_offset + 8); // r8 (s0, fp) - dwarf_uleb128(eh_frame_section, 4); // cfa-16 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 8); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 8); // r8 (s0, fp) - dwarf_uleb128(eh_frame_section, 0); // ofs 0 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc4); - while (size >= 4 && - read32le(cur_text_section->data + func_ind + size - 4) != 0x00008067) - size -= 4; - dwarf_data4(eh_frame_section, size - 36); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa); - dwarf_uleb128(eh_frame_section, 2); // r2 (r2, sp) - dwarf_uleb128(eh_frame_section, 16); // ofs 16 - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 4); - dwarf_data1(eh_frame_section, DW_CFA_restore + 1); // r1 (lr) - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 4); - dwarf_data1(eh_frame_section, DW_CFA_restore + 8); // r8 (s0, fp) - dwarf_data1(eh_frame_section, DW_CFA_advance_loc + 4); - dwarf_data1(eh_frame_section, DW_CFA_def_cfa_offset); - dwarf_uleb128(eh_frame_section, 0); // ofs 0 -#endif - while ((eh_frame_section->data_offset - fde_start) & 3) - dwarf_data1(eh_frame_section, DW_CFA_nop); - write32le(eh_frame_section->data + fde_start, // length - eh_frame_section->data_offset - fde_start - 4); -} - -ST_FUNC void tcc_eh_frame_end(TCCState *s1) -{ - if (!eh_frame_section) - return; - dwarf_data4(eh_frame_section, 0); -} - -struct eh_search_table { - uint32_t pc_offset; - uint32_t fde_offset; -}; - -static int sort_eh_table(const void *a, const void *b) -{ - uint32_t pc1 = ((const struct eh_search_table *)a)->pc_offset; - uint32_t pc2 = ((const struct eh_search_table *)b)->pc_offset; - - return pc1 < pc2 ? -1 : pc1 > pc2 ? 1 : 0; -} - -ST_FUNC void tcc_eh_frame_hdr(TCCState *s1, int final) -{ - int count = 0, offset; - unsigned long count_offset, tab_offset; - unsigned char *ln, *end; - unsigned int last_cie_offset = 0xffffffff; - - if (!eh_frame_section || !eh_frame_section->data_offset) - return; - if (final && !eh_frame_hdr_section) - return; - if (final == 0) - eh_frame_hdr_section = - new_section(s1, ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC); - eh_frame_hdr_section->data_offset = 0; - dwarf_data1(eh_frame_hdr_section, 1); // Version - // Pointer Encoding Format - dwarf_data1(eh_frame_hdr_section, DW_EH_PE_sdata4 | DW_EH_PE_pcrel); - // Count Encoding Format - dwarf_data1(eh_frame_hdr_section, DW_EH_PE_udata4 | DW_EH_PE_absptr); - // Table Encoding Format - dwarf_data1(eh_frame_hdr_section, DW_EH_PE_sdata4 | DW_EH_PE_datarel); - offset = eh_frame_section->sh_addr - - eh_frame_hdr_section->sh_addr - - eh_frame_hdr_section->data_offset; - dwarf_data4(eh_frame_hdr_section, offset); // eh_frame_ptr - // Count - count_offset = eh_frame_hdr_section->data_offset; - dwarf_data4(eh_frame_hdr_section, 0); - tab_offset = eh_frame_hdr_section->data_offset; - ln = eh_frame_section->data; - end = eh_frame_section->data + eh_frame_section->data_offset; - while (ln < end) { - unsigned char *fde = ln, *rd = ln; - unsigned int cie_offset, version, length = dwarf_read_4(rd, end); - unsigned int pc_offset, fde_offset; - - if (length == 0) - goto next; - cie_offset = dwarf_read_4(rd, end); - if (cie_offset == 0) - goto next; - if (cie_offset != last_cie_offset) { - unsigned char *cie = rd - cie_offset + 4; - - if (cie < eh_frame_section->data) - goto next; - version = dwarf_read_1(cie, end); - if ((version == 1 || version == 3) && - dwarf_read_1(cie, end) == 'z' && // Augmentation String - dwarf_read_1(cie, end) == 'R' && - dwarf_read_1(cie, end) == 0) { - dwarf_read_uleb128(&cie, end); // code_alignment_factor - dwarf_read_sleb128(&cie, end); // data_alignment_factor - dwarf_read_1(cie, end); // return address column - if (dwarf_read_uleb128(&cie, end) == 1 && - dwarf_read_1(cie, end) == FDE_ENCODING) { - last_cie_offset = cie_offset; - } - else - goto next; - } - else - goto next; - } - count++; - fde_offset = eh_frame_section->sh_addr + - (fde - eh_frame_section->data) - - eh_frame_hdr_section->sh_addr; - pc_offset = dwarf_read_4(rd, end) + fde_offset + 8; - dwarf_data4(eh_frame_hdr_section, pc_offset); - dwarf_data4(eh_frame_hdr_section, fde_offset); -next: - ln += length + 4; - } - add32le(eh_frame_hdr_section->data + count_offset, count); - qsort(eh_frame_hdr_section->data + tab_offset, count, - sizeof(struct eh_search_table), sort_eh_table); -} -#endif - -/* start of translation unit info */ -ST_FUNC void tcc_debug_start(TCCState *s1) -{ - int i; - char buf[512]; - char *filename; - - /* we might currently #include the */ - filename = file->prev ? file->prev->filename : file->filename; - - /* an elf symbol of type STT_FILE must be put so that STB_LOCAL - symbols can be safely used */ - put_elf_sym(symtab_section, 0, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0, - SHN_ABS, filename); - - if (s1->do_debug) { - - new_file = last_line_num = 0; - debug_next_type = N_DEFAULT_DEBUG; - debug_hash = NULL; - debug_anon_hash = NULL; - n_debug_hash = 0; - n_debug_anon_hash = 0; - - getcwd(buf, sizeof(buf)); -#ifdef _WIN32 - normalize_slashes(buf); -#endif - - if (s1->dwarf) { - int start_abbrev; - unsigned char *ptr; - char *undo; - - /* 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; - if (s1->dwarf < 4) { - /* These are compatable for DW_TAG_compile_unit - DW_AT_stmt_list. */ - if (ptr[1] == DW_FORM_sec_offset) - ptr[1] = DW_FORM_data4; - /* This code uses only size < 0x80 so these are - compatible. */ - if (ptr[1] == DW_FORM_exprloc) - ptr[1] = DW_FORM_block1; - } - ptr += 2; - } - 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_32DW); - dwarf_data4(dwarf_info_section, start_abbrev); - } - else { - dwarf_reloc(dwarf_info_section, dwarf_sym.abbrev, R_DATA_32DW); - 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 " PACKAGE_VERSION); - dwarf_data1(dwarf_info_section, s1->cversion == 201112 ? DW_LANG_C11 : DW_LANG_C99); - 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_32DW); - 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)); - undo = strrchr(filename, '/'); - if (undo) - *undo = 0; - dwarf_line.dir_size = 1 + (undo != NULL); - dwarf_line.dir_table = (char **) tcc_malloc(sizeof (char *) * - dwarf_line.dir_size); - dwarf_line.dir_table[0] = tcc_strdup(buf); - if (undo) - dwarf_line.dir_table[1] = tcc_strdup(filename); - 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; - if (undo) { - dwarf_line.filename_table[0].name = tcc_strdup(undo + 1); - dwarf_line.filename_table[1].dir_entry = 1; - dwarf_line.filename_table[1].name = tcc_strdup(undo + 1); - *undo = '/'; - } - else { - 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(s1, 0); // extended - dwarf_uleb128_op(s1, 1 + PTR_SIZE); // extended size - dwarf_line_op(s1, DW_LNE_set_address); - for (i = 0; i < PTR_SIZE; i++) - dwarf_line_op(s1, 0); - memset(&dwarf_info.base_type_used, 0, sizeof(dwarf_info.base_type_used)); - } - else - { - /* file info: full path + filename */ - pstrcat(buf, sizeof(buf), "/"); - 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); - } - /* we're currently 'including' the */ - tcc_debug_bincl(s1); - } -} - -/* put end of translation unit info */ -ST_FUNC void tcc_debug_end(TCCState *s1) -{ - if (!s1->do_debug || debug_next_type == 0) - return; - - if (debug_info_root) - tcc_debug_funcend(s1, 0); /* free stuff in case of errors */ - - if (s1->dwarf) { - int i, j; - int start_aranges; - unsigned char *ptr; - int text_size = text_section->data_offset; - - /* dwarf_info */ - for (i = 0; i < n_debug_anon_hash; i++) { - Sym *t = debug_anon_hash[i].type; - int pos = dwarf_info_section->data_offset; - - dwarf_data1(dwarf_info_section, - IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_EMPTY_TYPE - : DWARF_ABBREV_STRUCTURE_EMPTY_TYPE); - dwarf_strp(dwarf_info_section, - (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM - ? "" : get_tok_str(t->v, NULL)); - dwarf_uleb128(dwarf_info_section, 0); - dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file); - dwarf_uleb128(dwarf_info_section, file->line_num); - for (j = 0; j < debug_anon_hash[i].n_debug_type; j++) - write32le(dwarf_info_section->data + - debug_anon_hash[i].debug_type[j], - pos - dwarf_info.start); - tcc_free (debug_anon_hash[i].debug_type); - } - tcc_free (debug_anon_hash); - 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_32DW); - 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(s1, 0); // extended - dwarf_uleb128_op(s1, 1); // extended size - dwarf_line_op(s1, 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); - debug_next_type = 0; -} - -static BufferedFile* put_new_file(TCCState *s1) -{ - BufferedFile *f = file; - /* use upper file if from inline ":asm:" */ - if (f->filename[0] == ':') - f = f->prev; - if (f && new_file) { - new_file = last_line_num = 0; - if (s1->dwarf) - dwarf_file(s1); - else - put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym); - } - return f; -} - -/* put alternative filename */ -ST_FUNC void tcc_debug_newfile(TCCState *s1) -{ - if (!s1->do_debug) - return; - if (s1->dwarf) - dwarf_file(s1); - new_file = 1; -} - -/* begin of #include */ -ST_FUNC void tcc_debug_bincl(TCCState *s1) -{ - if (!s1->do_debug) - return; - if (s1->dwarf) - dwarf_file(s1); - else - put_stabs(s1, file->filename, N_BINCL, 0, 0, 0); - new_file = 1; -} - -/* end of #include */ -ST_FUNC void tcc_debug_eincl(TCCState *s1) -{ - if (!s1->do_debug) - return; - if (s1->dwarf) - dwarf_file(s1); - else - put_stabn(s1, N_EINCL, 0, 0, 0); - new_file = 1; -} - -/* generate line number info */ -ST_FUNC void tcc_debug_line(TCCState *s1) -{ - BufferedFile *f; - - if (!s1->do_debug) - return; - if (cur_text_section != text_section || nocode_wanted) - return; - f = put_new_file(s1); - if (!f) - return; - if (last_line_num == f->line_num) - return; - last_line_num = f->line_num; - - 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(s1, DW_LNS_set_file); - dwarf_uleb128_op(s1, 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(s1, 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(s1, n); - else { - dwarf_line_op(s1, DW_LNS_advance_pc); - dwarf_uleb128_op(s1, 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(s1, n); - else { - dwarf_line_op(s1, DW_LNS_advance_line); - dwarf_sleb128_op(s1, 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); - } - } -} - -static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned long value, - Section *sec, int sym_index, int info) -{ - struct debug_sym *s; - - if (debug_info) { - debug_info->sym = - (struct debug_sym *)tcc_realloc (debug_info->sym, - sizeof(struct debug_sym) * - (debug_info->n_sym + 1)); - s = debug_info->sym + debug_info->n_sym++; - s->type = type; - s->value = value; - 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); - else - put_stabs (s1, str, type, 0, 0, value); -} - -ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value) -{ - if (!s1->do_debug) - return; - if (type == N_LBRAC) { - struct _debug_info *info = - (struct _debug_info *) tcc_mallocz(sizeof (*info)); - - info->start = value; - info->parent = debug_info; - if (debug_info) { - if (debug_info->child) { - if (debug_info->child->last) - debug_info->child->last->next = info; - else - debug_info->child->next = info; - debug_info->child->last = info; - } - else - debug_info->child = info; - } - else - debug_info_root = info; - debug_info = info; - } - else { - debug_info->end = value; - debug_info = debug_info->parent; - } -} - -static int tcc_debug_find(TCCState *s1, Sym *t, int dwarf) -{ - int i; - - if (!debug_info && dwarf && - (t->type.t & VT_BTYPE) == VT_STRUCT && t->c == -1) { - for (i = 0; i < n_debug_anon_hash; i++) - if (t == debug_anon_hash[i].type) - return 0; - debug_anon_hash = (struct _debug_anon_hash *) - tcc_realloc (debug_anon_hash, - (n_debug_anon_hash + 1) * sizeof(*debug_anon_hash)); - debug_anon_hash[n_debug_anon_hash].n_debug_type = 0; - debug_anon_hash[n_debug_anon_hash].debug_type = NULL; - debug_anon_hash[n_debug_anon_hash++].type = t; - return 0; - } - 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_get_dwarf_info(TCCState *s1, Sym *s); - -static void tcc_debug_check_anon(TCCState *s1, Sym *t, int debug_type) -{ - int i; - - if (!debug_info && (t->type.t & VT_BTYPE) == VT_STRUCT && t->type.ref->c == -1) - for (i = 0; i < n_debug_anon_hash; i++) - if (t->type.ref == debug_anon_hash[i].type) { - debug_anon_hash[i].debug_type = - tcc_realloc(debug_anon_hash[i].debug_type, - (debug_anon_hash[i].n_debug_type + 1) * sizeof(int)); - debug_anon_hash[i].debug_type[debug_anon_hash[i].n_debug_type++] = - debug_type; - } -} - -ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t) -{ - int i, j, debug_type; - - if (!(s1->do_debug & 2) || !s1->dwarf || debug_info) - return; - - if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1) - for (i = 0; i < n_debug_anon_hash; i++) - if (t->ref == debug_anon_hash[i].type) { - Sym sym = {0}; sym .type = *t ; - - /* Trick to not hash this struct */ - debug_info = (struct _debug_info *) t; - debug_type = tcc_get_dwarf_info(s1, &sym); - debug_info = NULL; - for (j = 0; j < debug_anon_hash[i].n_debug_type; j++) - write32le(dwarf_info_section->data + - debug_anon_hash[i].debug_type[j], - debug_type - dwarf_info.start); - tcc_free(debug_anon_hash[i].debug_type); - n_debug_anon_hash--; - for (; i < n_debug_anon_hash; i++) - debug_anon_hash[i] = debug_anon_hash[i + 1]; - } -} - -static int tcc_debug_add(TCCState *s1, 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(TCCState *s1, 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]; - } -} - -#define STRUCT_NODEBUG(s) \ - (s->a.nodebug || \ - ((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM && \ - ((s->type.t & VT_BTYPE) == VT_BYTE || \ - (s->type.t & VT_BTYPE) == VT_BOOL || \ - (s->type.t & VT_BTYPE) == VT_SHORT || \ - (s->type.t & VT_BTYPE) == VT_INT || \ - (s->type.t & VT_BTYPE) == VT_LLONG))) - -static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result) -{ - int type; - int n = 0; - int debug_type = -1; - Sym *t = s; - CString str; - - for (;;) { - type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA); - if ((type & VT_BTYPE) != VT_BYTE) - type &= ~VT_DEFSIGN; - if (type == VT_PTR || type == (VT_PTR | VT_ARRAY)) - n++, t = t->type.ref; - else - break; - } - if ((type & VT_BTYPE) == VT_STRUCT) { - Sym *e = t; - - t = t->type.ref; - debug_type = tcc_debug_find(s1, t, 0); - if (debug_type == -1) { - debug_type = tcc_debug_add(s1, t, 0); - cstr_new (&str); - cstr_printf (&str, "%s:T%d=%c%d", - (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM - ? "" : get_tok_str(t->v, NULL), - debug_type, - IS_UNION (t->type.t) ? 'u' : 's', - t->c); - while (t->next) { - int pos, size, align; - - t = t->next; - if (STRUCT_NODEBUG(t)) - continue; - cstr_printf (&str, "%s:", - get_tok_str(t->v, NULL)); - tcc_get_debug_info (s1, t, &str); - if (t->type.t & VT_BITFIELD) { - pos = t->c * 8 + BIT_POS(t->type.t); - size = BIT_SIZE(t->type.t); - } - else { - pos = t->c * 8; - size = type_size(&t->type, &align) * 8; - } - cstr_printf (&str, ",%d,%d;", pos, size); - } - cstr_printf (&str, ";"); - tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0); - cstr_free (&str); - if (debug_info) - tcc_debug_remove(s1, e); - } - } - else if (IS_ENUM(type)) { - Sym *e = t = t->type.ref; - - debug_type = tcc_debug_find(s1, t, 0); - if (debug_type == -1) { - debug_type = tcc_debug_add(s1, t, 0); - cstr_new (&str); - cstr_printf (&str, "%s:T%d=e", - (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM - ? "" : get_tok_str(t->v, 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, 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(s1, e); - } - } - else if ((type & VT_BTYPE) != VT_FUNC) { - type &= ~VT_STRUCT_MASK; - for (debug_type = 1; debug_type <= N_DEFAULT_DEBUG; debug_type++) - if (default_debug[debug_type - 1].type == type) - break; - if (debug_type > N_DEFAULT_DEBUG) - return; - } - if (n > 0) - cstr_printf (result, "%d=", ++debug_next_type); - t = s; - for (;;) { - type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA); - if ((type & VT_BTYPE) != VT_BYTE) - type &= ~VT_DEFSIGN; - if (type == VT_PTR) - cstr_printf (result, "%d=*", ++debug_next_type); - else if (type == (VT_PTR | VT_ARRAY)) - cstr_printf (result, "%d=ar1;0;%d;", - ++debug_next_type, t->type.ref->c - 1); - else if (type == VT_FUNC) { - cstr_printf (result, "%d=f", ++debug_next_type); - tcc_get_debug_info (s1, t->type.ref, result); - return; - } - else - break; - t = t->type.ref; - } - 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; - int last_pos = -1; - int retval; - - if (new_file) - put_new_file(s1); - for (;;) { - type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA); - 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(s1, t, 1); - if (debug_type == -1) { - int pos_sib = 0, i, *pos_type; - - debug_type = tcc_debug_add(s1, t, 1); - e = t; - i = 0; - while (e->next) { - e = e->next; - if (STRUCT_NODEBUG(e)) - continue; - i++; - } - pos_type = (int *) tcc_malloc(i * sizeof(int)); - dwarf_data1(dwarf_info_section, - IS_UNION (t->type.t) - ? t->next ? DWARF_ABBREV_UNION_TYPE - : DWARF_ABBREV_UNION_EMPTY_TYPE - : t->next ? DWARF_ABBREV_STRUCTURE_TYPE - : DWARF_ABBREV_STRUCTURE_EMPTY_TYPE); - dwarf_strp(dwarf_info_section, - (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM - ? "" : get_tok_str(t->v, 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); - if (t->next) { - pos_sib = dwarf_info_section->data_offset; - dwarf_data4(dwarf_info_section, 0); - } - e = t; - i = 0; - while (e->next) { - e = e->next; - if (STRUCT_NODEBUG(e)) - continue; - dwarf_data1(dwarf_info_section, - e->type.t & VT_BITFIELD ? DWARF_ABBREV_MEMBER_BF - : DWARF_ABBREV_MEMBER); - dwarf_strp(dwarf_info_section, - get_tok_str(e->v, 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); - if (e->type.t & VT_BITFIELD) { - int pos = e->c * 8 + BIT_POS(e->type.t); - int size = BIT_SIZE(e->type.t); - - dwarf_uleb128(dwarf_info_section, size); - dwarf_uleb128(dwarf_info_section, pos); - } - else - dwarf_uleb128(dwarf_info_section, e->c); - } - if (t->next) { - 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; - if (STRUCT_NODEBUG(e)) - continue; - type = tcc_get_dwarf_info(s1, e); - tcc_debug_check_anon(s1, e, pos_type[i]); - write32le(dwarf_info_section->data + pos_type[i++], - type - dwarf_info.start); - } - tcc_free(pos_type); - if (debug_info) - tcc_debug_remove(s1, t); - } - } - else if (IS_ENUM(type)) { - t = t->type.ref; - debug_type = tcc_debug_find(s1, t, 1); - if (debug_type == -1) { - int pos_sib, pos_type; - Sym sym = {0}; sym.type.t = VT_INT | (type & VT_UNSIGNED); - - pos_type = tcc_get_dwarf_info(s1, &sym); - debug_type = tcc_debug_add(s1, 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, 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, - type & VT_UNSIGNED ? DWARF_ABBREV_ENUMERATOR_UNSIGNED - : DWARF_ABBREV_ENUMERATOR_SIGNED); - dwarf_strp(dwarf_info_section, - (e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM - ? "" : get_tok_str(e->v, NULL)); - if (type & VT_UNSIGNED) - dwarf_uleb128(dwarf_info_section, e->enum_val); - else - dwarf_sleb128(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(s1, 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; - } - } - retval = debug_type; - e = NULL; - t = s; - for (;;) { - type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA); - if ((type & VT_BTYPE) != VT_BYTE) - type &= ~VT_DEFSIGN; - if (type == VT_PTR) { - i = dwarf_info_section->data_offset; - if (retval == debug_type) - retval = i; - dwarf_data1(dwarf_info_section, DWARF_ABBREV_POINTER); - dwarf_data1(dwarf_info_section, PTR_SIZE); - if (last_pos != -1) { - tcc_debug_check_anon(s1, e, last_pos); - write32le(dwarf_info_section->data + last_pos, - i - dwarf_info.start); - } - last_pos = dwarf_info_section->data_offset; - e = t->type.ref; - dwarf_data4(dwarf_info_section, 0); - } - else if (type == (VT_PTR | VT_ARRAY)) { - int sib_pos, sub_type; -#if LONG_SIZE == 4 - Sym sym = {0}; sym.type.t = VT_LONG | VT_INT | VT_UNSIGNED; -#else - Sym sym = {0}; sym.type.t = VT_LLONG | VT_LONG | VT_UNSIGNED; -#endif - - sub_type = tcc_get_dwarf_info(s1, &sym); - i = dwarf_info_section->data_offset; - if (retval == debug_type) - retval = i; - dwarf_data1(dwarf_info_section, DWARF_ABBREV_ARRAY_TYPE); - if (last_pos != -1) { - tcc_debug_check_anon(s1, e, last_pos); - write32le(dwarf_info_section->data + last_pos, - i - dwarf_info.start); - } - last_pos = dwarf_info_section->data_offset; - e = t->type.ref; - dwarf_data4(dwarf_info_section, 0); - 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); - } - else if (type == VT_FUNC) { - int sib_pos = 0, *pos_type; - Sym *f; - - i = dwarf_info_section->data_offset; - debug_type = tcc_get_dwarf_info(s1, t->type.ref); - if (retval == debug_type) - retval = i; - dwarf_data1(dwarf_info_section, - t->type.ref->next ? DWARF_ABBREV_SUBROUTINE_TYPE - : DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE); - if (last_pos != -1) { - tcc_debug_check_anon(s1, e, last_pos); - write32le(dwarf_info_section->data + last_pos, - i - dwarf_info.start); - } - last_pos = dwarf_info_section->data_offset; - e = t->type.ref; - dwarf_data4(dwarf_info_section, 0); - if (t->type.ref->next) { - sib_pos = dwarf_info_section->data_offset; - dwarf_data4(dwarf_info_section, 0); - } - f = t->type.ref; - i = 0; - while (f->next) { - f = f->next; - i++; - } - pos_type = (int *) tcc_malloc(i * sizeof(int)); - f = t->type.ref; - i = 0; - while (f->next) { - f = f->next; - dwarf_data1(dwarf_info_section, DWARF_ABBREV_FORMAL_PARAMETER2); - pos_type[i++] = dwarf_info_section->data_offset; - dwarf_data4(dwarf_info_section, 0); - } - if (t->type.ref->next) { - dwarf_data1(dwarf_info_section, 0); - write32le(dwarf_info_section->data + sib_pos, - dwarf_info_section->data_offset - dwarf_info.start); - } - f = t->type.ref; - i = 0; - while (f->next) { - f = f->next; - type = tcc_get_dwarf_info(s1, f); - tcc_debug_check_anon(s1, f, pos_type[i]); - write32le(dwarf_info_section->data + pos_type[i++], - type - dwarf_info.start); - } - tcc_free(pos_type); - } - else { - if (last_pos != -1) { - tcc_debug_check_anon(s1, e, last_pos); - write32le(dwarf_info_section->data + last_pos, - debug_type - dwarf_info.start); - } - break; - } - t = t->type.ref; - } - return retval; -} - -static void tcc_debug_finish (TCCState *s1, struct _debug_info *cur) -{ - while (cur) { - struct _debug_info *next = cur->next; - int i; - - if (s1->dwarf) { - - 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, - cur->child ? DWARF_ABBREV_LEXICAL_BLOCK - : DWARF_ABBREV_LEXICAL_EMPTY_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); - if (cur->child) - dwarf_data1(dwarf_info_section, 0); - } - else - { - for (i = 0; i < cur->n_sym; i++) { - struct debug_sym *s = &cur->sym[i]; - - if (s->sec) - put_stabs_r(s1, s->str, s->type, 0, 0, s->value, - s->sec, s->sym_index); - else - put_stabs(s1, s->str, s->type, 0, 0, s->value); - tcc_free (s->str); - } - tcc_free (cur->sym); - put_stabn(s1, N_LBRAC, 0, 0, cur->start); - tcc_debug_finish (s1, cur->child); - put_stabn(s1, N_RBRAC, 0, 0, cur->end); - } - tcc_free (cur); - cur = next; - } -} - -ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e) -{ - CString debug_str; - - if (!(s1->do_debug & 2)) - return; - - cstr_new (&debug_str); - for (; s != e; s = s->prev) { - if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL) - continue; - 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); -} - -/* put function symbol */ -ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym) -{ - CString debug_str; - BufferedFile *f; - - if (!s1->do_debug) - return; - debug_info_root = NULL; - debug_info = NULL; - tcc_debug_stabn(s1, N_LBRAC, ind - func_ind); - f = put_new_file(s1); - if (!f) - return; - - if (s1->dwarf) { - tcc_debug_line(s1); - dwarf_info.func = sym; - dwarf_info.line = file->line_num; - if (s1->do_backtrace) { - int i, len; - - dwarf_line_op(s1, 0); // extended - dwarf_uleb128_op(s1, strlen(funcname) + 2); - dwarf_line_op(s1, DW_LNE_hi_user - 1); - len = strlen(funcname) + 1; - for (i = 0; i < len; i++) - dwarf_line_op(s1, 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); - tcc_debug_line(s1); - } -} - -ST_FUNC void tcc_debug_prolog_epilog(TCCState *s1, int value) -{ - if (!s1->do_debug) - return; - if (s1->dwarf) { - dwarf_line_op(s1, value == 0 ? DW_LNS_set_prologue_end - : DW_LNS_set_epilogue_begin); - } -} - -/* put function size */ -ST_FUNC void tcc_debug_funcend(TCCState *s1, int size) -{ - /* lldb does not like function end and next function start at same pc */ - int min_instr_len; - -#if TCC_EH_FRAME - tcc_debug_frame_end(s1, size); -#endif - if (!s1->do_debug) - return; - min_instr_len = dwarf_line.last_pc == ind ? 0 : DWARF_MIN_INSTR_LEN; - ind -= min_instr_len; - tcc_debug_line(s1); - ind += min_instr_len; - tcc_debug_stabn(s1, N_RBRAC, size); - if (s1->dwarf) { - int func_sib = 0; - Sym *sym = dwarf_info.func; - int n_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); - tcc_debug_check_anon(s1, sym->type.ref, dwarf_info_section->data_offset); - dwarf_data4(dwarf_info_section, n_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); - dwarf_data1(dwarf_info_section, 0); - write32le(dwarf_info_section->data + func_sib, - dwarf_info_section->data_offset - dwarf_info.start); - } - else - { - tcc_debug_finish (s1, debug_info_root); - } - debug_info_root = 0; -} - - -ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type) -{ - if (!(s1->do_debug & 2)) - return; - - if (sym_type == STT_FUNC || sym->v >= SYM_FIRST_ANOM) - return; - 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); - tcc_debug_check_anon(s1, sym, dwarf_info_section->data_offset); - 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 - } - else - { - Section *s = sh_num == SHN_COMMON ? common_section - : s1->sections[sh_num]; - CString str; - - cstr_new (&str); - cstr_printf (&str, "%s:%c", - get_tok_str(sym->v, NULL), - sym_bind == STB_GLOBAL ? 'G' : func_ind != -1 ? '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, 0); - else - tcc_debug_stabs(s1, str.data, - (sym->type.t & VT_STATIC) && data_section == s - ? N_STSYM : N_LCSYM, 0, s, sym->c, 0); - cstr_free (&str); - } -} - -ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym) -{ - if (!(s1->do_debug & 2)) - 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, NULL)); - dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file); - dwarf_uleb128(dwarf_info_section, file->line_num); - tcc_debug_check_anon(s1, sym, dwarf_info_section->data_offset); - dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start); - } - } - else - { - CString str; - cstr_new (&str); - cstr_printf (&str, "%s:t", - (sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM - ? "" : get_tok_str(sym->v, NULL)); - tcc_get_debug_info(s1, sym, &str); - tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0); - cstr_free (&str); - } -} - -/* ------------------------------------------------------------------------- */ -/* for section layout see lib/tcov.c */ - -ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line); - -ST_FUNC void tcc_tcov_block_begin(TCCState *s1) -{ - SValue sv; - void *ptr; - unsigned long last_offset = tcov_data.offset; - - tcc_tcov_block_end (tcc_state, 0); - if (s1->test_coverage == 0 || nocode_wanted) - return; - - if (tcov_data.last_file_name == 0 || - strcmp ((const char *)(tcov_section->data + tcov_data.last_file_name), - file->true_filename) != 0) { - char wd[1024]; - CString cstr; - - if (tcov_data.last_func_name) - section_ptr_add(tcov_section, 1); - if (tcov_data.last_file_name) - section_ptr_add(tcov_section, 1); - tcov_data.last_func_name = 0; - cstr_new (&cstr); - if (file->true_filename[0] == '/') { - tcov_data.last_file_name = tcov_section->data_offset; - cstr_printf (&cstr, "%s", file->true_filename); - } - else { - getcwd (wd, sizeof(wd)); - tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1; - cstr_printf (&cstr, "%s/%s", wd, file->true_filename); - } - ptr = section_ptr_add(tcov_section, cstr.size + 1); - strcpy((char *)ptr, cstr.data); -#ifdef _WIN32 - normalize_slashes((char *)ptr); -#endif - cstr_free (&cstr); - } - if (tcov_data.last_func_name == 0 || - strcmp ((const char *)(tcov_section->data + tcov_data.last_func_name), - funcname) != 0) { - size_t len; - - if (tcov_data.last_func_name) - section_ptr_add(tcov_section, 1); - tcov_data.last_func_name = tcov_section->data_offset; - len = strlen (funcname); - ptr = section_ptr_add(tcov_section, len + 1); - strcpy((char *)ptr, funcname); - section_ptr_add(tcov_section, -tcov_section->data_offset & 7); - ptr = section_ptr_add(tcov_section, 8); - write64le (ptr, file->line_num); - } - if (ind == tcov_data.ind && tcov_data.line == file->line_num) - tcov_data.offset = last_offset; - else { - Sym label = {0}; - label.type.t = VT_LLONG | VT_STATIC; - - ptr = section_ptr_add(tcov_section, 16); - tcov_data.line = file->line_num; - write64le (ptr, (tcov_data.line << 8) | 0xff); - put_extern_sym(&label, tcov_section, - ((unsigned char *)ptr - tcov_section->data) + 8, 0); - sv.type = label.type; - sv.r = VT_SYM | VT_LVAL | VT_CONST; - sv.r2 = VT_CONST; - sv.c.i = 0; - sv.sym = &label; -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \ - defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || \ - defined TCC_TARGET_RISCV64 - gen_increment_tcov (&sv); -#else - vpushv(&sv); - inc(0, TOK_INC); - vpop(); -#endif - tcov_data.offset = (unsigned char *)ptr - tcov_section->data; - tcov_data.ind = ind; - } -} - -ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line) -{ - if (s1->test_coverage == 0) - return; - if (line == -1) - line = tcov_data.line; - if (tcov_data.offset) { - void *ptr = tcov_section->data + tcov_data.offset; - unsigned long long nline = line ? line : file->line_num; - - write64le (ptr, (read64le (ptr) & 0xfffffffffull) | (nline << 36)); - tcov_data.offset = 0; - } -} - -ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start) -{ - if (s1->test_coverage == 0) - return; - if (tcov_data.line != file->line_num) { - if ((tcov_data.line + 1) != file->line_num) { - tcc_tcov_block_end (s1, -1); - if (start) - tcc_tcov_block_begin (s1); - } - else - tcov_data.line = file->line_num; - } -} - -ST_FUNC void tcc_tcov_start(TCCState *s1) -{ - if (s1->test_coverage == 0) - return; - if (!s1->dState) - s1->dState = tcc_mallocz(sizeof *s1->dState); - memset (&tcov_data, 0, sizeof (tcov_data)); - if (tcov_section == NULL) { - tcov_section = new_section(tcc_state, ".tcov", SHT_PROGBITS, - SHF_ALLOC | SHF_WRITE); - section_ptr_add(tcov_section, 4); // pointer to executable name - } -} - -ST_FUNC void tcc_tcov_end(TCCState *s1) -{ - if (s1->test_coverage == 0) - return; - if (tcov_data.last_func_name) - section_ptr_add(tcov_section, 1); - if (tcov_data.last_file_name) - section_ptr_add(tcov_section, 1); -} - -ST_FUNC void tcc_tcov_reset_ind(TCCState *s1) -{ - tcov_data.ind = 0; -} - -/* ------------------------------------------------------------------------- */ -#undef last_line_num -#undef new_file -#undef section_sym -#undef debug_next_type -#undef debug_hash -#undef n_debug_hash -#undef debug_anon_hash -#undef n_debug_anon_hash -#undef debug_info -#undef debug_info_root -#undef dwarf_sym -#undef dwarf_line -#undef dwarf_info -#undef tcov_data diff --git a/tccmacho.c b/tccmacho.c deleted file mode 100644 index 0b70457c..00000000 --- a/tccmacho.c +++ /dev/null @@ -1,2480 +0,0 @@ -/* - * Mach-O file handling for TCC - * - * 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" - -/* In order to make life easy for us we are generating Mach-O files which - don't make use of some modern features, but which aren't entirely classic - either in that they do use some modern features. We're also only - generating 64bit Mach-O files, and only native endian at that. - - In particular we're generating executables that don't make use of - DYLD_INFO for dynamic linking info, as that requires us building a - trie of exported names. We're simply using classic symbol tables which - are still supported by modern dyld. - - But we do use LC_MAIN, which is a "modern" feature in order to not have - to setup our own crt code. We're not using lazy linking, so even function - calls are resolved at startup. */ - -#if !defined TCC_TARGET_X86_64 && !defined TCC_TARGET_ARM64 -#error Platform not supported -#endif - -/* XXX: this file uses tcc_error() to the effect of exit(1) */ -#undef _tcc_error - -#define DEBUG_MACHO 0 -#define dprintf if (DEBUG_MACHO) printf - -#define MH_EXECUTE (0x2) -#define MH_DYLDLINK (0x4) -#define MH_DYLIB (0x6) -#define MH_PIE (0x200000) - -#define CPU_SUBTYPE_LIB64 (0x80000000) -#define CPU_SUBTYPE_X86_ALL (3) -#define CPU_SUBTYPE_ARM64_ALL (0) - -#define CPU_ARCH_ABI64 (0x01000000) - -#define CPU_TYPE_X86 (7) -#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64) -#define CPU_TYPE_ARM (12) -#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) - -struct fat_header { - uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */ - uint32_t nfat_arch; /* number of structs that follow */ -}; - -struct fat_arch { - int cputype; /* cpu specifier (int) */ - int cpusubtype; /* machine specifier (int) */ - uint32_t offset; /* file offset to this object file */ - uint32_t size; /* size of this object file */ - uint32_t align; /* alignment as a power of 2 */ -}; - -#define FAT_MAGIC 0xcafebabe -#define FAT_CIGAM 0xbebafeca -#define FAT_MAGIC_64 0xcafebabf -#define FAT_CIGAM_64 0xbfbafeca - -struct mach_header { - uint32_t magic; /* mach magic number identifier */ - int cputype; /* cpu specifier */ - int cpusubtype; /* machine specifier */ - uint32_t filetype; /* type of file */ - uint32_t ncmds; /* number of load commands */ - uint32_t sizeofcmds; /* the size of all the load commands */ - uint32_t flags; /* flags */ -}; - -struct mach_header_64 { - struct mach_header mh; - uint32_t reserved; /* reserved, pad to 64bit */ -}; - -/* Constant for the magic field of the mach_header (32-bit architectures) */ -#define MH_MAGIC 0xfeedface /* the mach magic number */ -#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */ -#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ -#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ - -struct load_command { - uint32_t cmd; /* type of load command */ - uint32_t cmdsize; /* total size of command in bytes */ -}; - -#define LC_REQ_DYLD 0x80000000 -#define LC_SYMTAB 0x2 -#define LC_DYSYMTAB 0xb -#define LC_LOAD_DYLIB 0xc -#define LC_ID_DYLIB 0xd -#define LC_LOAD_DYLINKER 0xe -#define LC_SEGMENT_64 0x19 -#define LC_RPATH (0x1c | LC_REQ_DYLD) -#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) -#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) -#define LC_MAIN (0x28|LC_REQ_DYLD) -#define LC_SOURCE_VERSION 0x2A -#define LC_BUILD_VERSION 0x32 -#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) -#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) - -#define SG_READ_ONLY 0x10 /* This segment is made read-only after fixups */ - -typedef int vm_prot_t; - -struct segment_command_64 { /* for 64-bit architectures */ - uint32_t cmd; /* LC_SEGMENT_64 */ - uint32_t cmdsize; /* includes sizeof section_64 structs */ - char segname[16]; /* segment name */ - uint64_t vmaddr; /* memory address of this segment */ - uint64_t vmsize; /* memory size of this segment */ - uint64_t fileoff; /* file offset of this segment */ - uint64_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ - uint32_t nsects; /* number of sections in segment */ - uint32_t flags; /* flags */ -}; - -struct section_64 { /* for 64-bit architectures */ - char sectname[16]; /* name of this section */ - char segname[16]; /* segment this section goes in */ - uint64_t addr; /* memory address of this section */ - uint64_t size; /* size in bytes of this section */ - uint32_t offset; /* file offset of this section */ - uint32_t align; /* section alignment (power of 2) */ - uint32_t reloff; /* file offset of relocation entries */ - uint32_t nreloc; /* number of relocation entries */ - uint32_t flags; /* flags (section type and attributes)*/ - uint32_t reserved1; /* reserved (for offset or index) */ - uint32_t reserved2; /* reserved (for count or sizeof) */ - uint32_t reserved3; /* reserved */ -}; - -enum { - DYLD_CHAINED_IMPORT = 1, -}; - -struct dyld_chained_fixups_header { - uint32_t fixups_version; ///< 0 - uint32_t starts_offset; ///< Offset of dyld_chained_starts_in_image. - uint32_t imports_offset; ///< Offset of imports table in chain_data. - uint32_t symbols_offset; ///< Offset of symbol strings in chain_data. - uint32_t imports_count; ///< Number of imported symbol names. - uint32_t imports_format; ///< DYLD_CHAINED_IMPORT* - uint32_t symbols_format; ///< 0 => uncompressed, 1 => zlib compressed -}; - -struct dyld_chained_starts_in_image -{ - uint32_t seg_count; - uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment - // followed by pool of dyld_chain_starts_in_segment data -}; - -enum { - DYLD_CHAINED_PTR_64 = 2, // target is vmaddr - DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset -}; - -enum { - DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups -}; - -#define SEG_PAGE_SIZE 16384 - -struct dyld_chained_starts_in_segment -{ - uint32_t size; // size of this (amount kernel needs to copy) - uint16_t page_size; // 0x1000 or 0x4000 - uint16_t pointer_format; // DYLD_CHAINED_PTR_* - uint64_t segment_offset; // offset in memory to start of segment - uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer - uint16_t page_count; // how many pages are in array - uint16_t page_start[1]; // each entry is offset in each page of first element in chain - // or DYLD_CHAINED_PTR_START_NONE if no fixups on page -}; - -enum BindSpecialDylib { - BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2, -}; - -struct dyld_chained_import -{ - uint32_t lib_ordinal : 8, - weak_import : 1, - name_offset : 23; -}; - -struct dyld_chained_ptr_64_rebase -{ - uint64_t target : 36, // vmaddr, 64GB max image size - high8 : 8, // top 8 bits set to this after slide added - reserved : 7, // all zeros - next : 12, // 4-byte stride - bind : 1; // == 0 -}; - -struct dyld_chained_ptr_64_bind -{ - uint64_t ordinal : 24, - addend : 8, // 0 thru 255 - reserved : 19, // all zeros - next : 12, // 4-byte stride - bind : 1; // == 1 -}; - -#define S_REGULAR 0x0 -#define S_ZEROFILL 0x1 -#define S_NON_LAZY_SYMBOL_POINTERS 0x6 -#define S_LAZY_SYMBOL_POINTERS 0x7 -#define S_SYMBOL_STUBS 0x8 -#define S_MOD_INIT_FUNC_POINTERS 0x9 -#define S_MOD_TERM_FUNC_POINTERS 0xa - -#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 -#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 -#define S_ATTR_DEBUG 0x02000000 - - -typedef uint32_t lc_str; - -struct dylib_command { - uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, - LC_REEXPORT_DYLIB */ - uint32_t cmdsize; /* includes pathname string */ - lc_str name; /* library's path name */ - uint32_t timestamp; /* library's build time stamp */ - uint32_t current_version; /* library's current version number */ - uint32_t compatibility_version; /* library's compatibility vers number*/ -}; - -struct rpath_command { - uint32_t cmd; /* LC_RPATH */ - uint32_t cmdsize; /* includes string */ - lc_str path; /* path to add to run path */ -}; - -struct dylinker_command { - uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or - LC_DYLD_ENVIRONMENT */ - uint32_t cmdsize; /* includes pathname string */ - lc_str name; /* dynamic linker's path name */ -}; - -struct linkedit_data_command { - uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, - LC_FUNCTION_STARTS, LC_DATA_IN_CODE, - LC_DYLIB_CODE_SIGN_DRS, - LC_LINKER_OPTIMIZATION_HINT, - LC_DYLD_EXPORTS_TRIE, or - LC_DYLD_CHAINED_FIXUPS. */ - uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ - uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ - uint32_t datasize; /* file size of data in __LINKEDIT segment */ -}; - -#define PLATFORM_MACOS 1 - -struct build_version_command { - uint32_t cmd; /* LC_BUILD_VERSION */ - uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ - /* ntools * sizeof(struct build_tool_version) */ - uint32_t platform; /* platform */ - uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t ntools; /* number of tool entries following this */ -}; - -struct source_version_command { - uint32_t cmd; /* LC_SOURCE_VERSION */ - uint32_t cmdsize; /* 16 */ - uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ -}; - -struct symtab_command { - uint32_t cmd; /* LC_SYMTAB */ - uint32_t cmdsize; /* sizeof(struct symtab_command) */ - uint32_t symoff; /* symbol table offset */ - uint32_t nsyms; /* number of symbol table entries */ - uint32_t stroff; /* string table offset */ - uint32_t strsize; /* string table size in bytes */ -}; - -struct dysymtab_command { - uint32_t cmd; /* LC_DYSYMTAB */ - uint32_t cmdsize; /* sizeof(struct dysymtab_command) */ - - uint32_t ilocalsym; /* index to local symbols */ - uint32_t nlocalsym; /* number of local symbols */ - - uint32_t iextdefsym;/* index to externally defined symbols */ - uint32_t nextdefsym;/* number of externally defined symbols */ - - uint32_t iundefsym; /* index to undefined symbols */ - uint32_t nundefsym; /* number of undefined symbols */ - - uint32_t tocoff; /* file offset to table of contents */ - uint32_t ntoc; /* number of entries in table of contents */ - - uint32_t modtaboff; /* file offset to module table */ - uint32_t nmodtab; /* number of module table entries */ - - uint32_t extrefsymoff; /* offset to referenced symbol table */ - uint32_t nextrefsyms; /* number of referenced symbol table entries */ - - uint32_t indirectsymoff;/* file offset to the indirect symbol table */ - uint32_t nindirectsyms; /* number of indirect symbol table entries */ - - uint32_t extreloff; /* offset to external relocation entries */ - uint32_t nextrel; /* number of external relocation entries */ - uint32_t locreloff; /* offset to local relocation entries */ - uint32_t nlocrel; /* number of local relocation entries */ -}; - -#define BIND_OPCODE_DONE 0x00 -#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30 -#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40 -#define BIND_OPCODE_SET_TYPE_IMM 0x50 -#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 -#define BIND_OPCODE_DO_BIND 0x90 - -#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 - -#define BIND_TYPE_POINTER 1 -#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 - -#define REBASE_OPCODE_DONE 0x00 -#define REBASE_OPCODE_SET_TYPE_IMM 0x10 -#define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20 -#define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50 - -#define REBASE_TYPE_POINTER 1 - -#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00 -#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02 -#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04 - -struct dyld_info_command { - uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */ - uint32_t cmdsize; /* sizeof(struct dyld_info_command) */ - uint32_t rebase_off; /* file offset to rebase info */ - uint32_t rebase_size; /* size of rebase info */ - uint32_t bind_off; /* file offset to binding info */ - uint32_t bind_size; /* size of binding info */ - uint32_t weak_bind_off; /* file offset to weak binding info */ - uint32_t weak_bind_size; /* size of weak binding info */ - uint32_t lazy_bind_off; /* file offset to lazy binding info */ - uint32_t lazy_bind_size; /* size of lazy binding infs */ - uint32_t export_off; /* file offset to lazy binding info */ - uint32_t export_size; /* size of lazy binding infs */ -}; - -#define INDIRECT_SYMBOL_LOCAL 0x80000000 - -struct entry_point_command { - uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ - uint32_t cmdsize; /* 24 */ - uint64_t entryoff; /* file (__TEXT) offset of main() */ - uint64_t stacksize;/* if not zero, initial stack size */ -}; - -enum skind { - sk_unknown = 0, - sk_discard, - sk_text, - sk_stubs, - sk_stub_helper, - sk_ro_data, - sk_uw_info, - sk_nl_ptr, // non-lazy pointers, aka GOT - sk_debug_info, - sk_debug_abbrev, - sk_debug_line, - sk_debug_aranges, - sk_debug_str, - sk_debug_line_str, - sk_stab, - sk_stab_str, - sk_la_ptr, // lazy pointers - sk_init, - sk_fini, - sk_rw_data, - sk_bss, - sk_linkedit, - sk_last -}; - -struct nlist_64 { - uint32_t n_strx; /* index into the string table */ - uint8_t n_type; /* type flag, see below */ - uint8_t n_sect; /* section number or NO_SECT */ - uint16_t n_desc; /* see */ - uint64_t n_value; /* value of this symbol (or stab offset) */ -}; - -#define N_UNDF 0x0 -#define N_ABS 0x2 -#define N_EXT 0x1 -#define N_SECT 0xe - -#define N_WEAK_REF 0x0040 -#define N_WEAK_DEF 0x0080 - -struct macho { - struct mach_header_64 mh; - int *seg2lc, nseg; - struct load_command **lc; - struct entry_point_command *ep; - int nlc; - struct { - Section *s; - int machosect; - } sk_to_sect[sk_last]; - int *elfsectomacho; - int *e2msym; - Section *symtab, *strtab, *indirsyms, *stubs, *exports; - uint32_t ilocal, iextdef, iundef; - int stubsym, n_got, nr_plt; - int segment[sk_last]; -#ifdef CONFIG_NEW_MACHO - Section *chained_fixups; - int n_bind; - int n_bind_rebase; - struct bind_rebase { - int section; - int bind; - ElfW_Rel rel; - } *bind_rebase; -#else - Section *rebase, *binding, *weak_binding, *lazy_binding; - Section *stub_helper, *la_symbol_ptr; - struct dyld_info_command *dyldinfo; - int helpsym, lasym, dyld_private, dyld_stub_binder; - int n_lazy_bind; - struct s_lazy_bind { - int section; - int bind_offset; - int la_symbol_offset; - ElfW_Rel rel; - } *s_lazy_bind; - int n_rebase; - struct s_rebase { - int section; - ElfW_Rel rel; - } *s_rebase; - int n_bind; - struct bind { - int section; - ElfW_Rel rel; - } *bind; -#endif -}; - -#define SHT_LINKEDIT (SHT_LOOS + 42) -#define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */ - -static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize) -{ - struct load_command *lc = tcc_mallocz(cmdsize); - lc->cmd = cmd; - lc->cmdsize = cmdsize; - mo->lc = tcc_realloc(mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1)); - mo->lc[mo->nlc++] = lc; - return lc; -} - -static struct segment_command_64 * add_segment(struct macho *mo, const char *name) -{ - struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); - strncpy(sc->segname, name, 16); - mo->seg2lc = tcc_realloc(mo->seg2lc, sizeof(*mo->seg2lc) * (mo->nseg + 1)); - mo->seg2lc[mo->nseg++] = mo->nlc - 1; - return sc; -} - -static struct segment_command_64 * get_segment(struct macho *mo, int i) -{ - return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]); -} - -static int add_section(struct macho *mo, struct segment_command_64 **_seg, const char *name) -{ - struct segment_command_64 *seg = *_seg; - int ret = seg->nsects; - struct section_64 *sec; - seg->nsects++; - seg->cmdsize += sizeof(*sec); - seg = tcc_realloc(seg, sizeof(*seg) + seg->nsects * sizeof(*sec)); - sec = (struct section_64*)((char*)seg + sizeof(*seg)) + ret; - memset(sec, 0, sizeof(*sec)); - strncpy(sec->sectname, name, 16); - strncpy(sec->segname, seg->segname, 16); - *_seg = seg; - return ret; -} - -static struct section_64 *get_section(struct segment_command_64 *seg, int i) -{ - return (struct section_64*)((char*)seg + sizeof(*seg)) + i; -} - -static void * add_dylib(struct macho *mo, char *name) -{ - struct dylib_command *lc; - int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8; - lc = add_lc(mo, LC_LOAD_DYLIB, sz); - lc->name = sizeof(*lc); - strcpy((char*)lc + lc->name, name); - lc->timestamp = 2; - lc->current_version = 1 << 16; - lc->compatibility_version = 1 << 16; - return lc; -} - -static int uleb128_size (unsigned long long value) -{ - int size = 0; - - do { - value >>= 7; - size++; - } while (value != 0); - return size; -} - -static void write_uleb128(Section *section, uint64_t value) -{ - do { - unsigned char byte = value & 0x7f; - uint8_t *ptr = section_ptr_add(section, 1); - - value >>= 7; - *ptr = byte | (value ? 0x80 : 0); - } while (value != 0); -} - -static void tcc_macho_add_destructor(TCCState *s1) -{ - int init_sym, mh_execute_header, at_exit_sym; - Section *s; - ElfW_Rel *rel; - uint8_t *ptr; - - mh_execute_header = put_elf_sym(s1->symtab, -4096, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 0, - text_section->sh_num, "__mh_execute_header"); - s = find_section(s1, ".fini_array"); - if (s->data_offset == 0) - return; - init_sym = put_elf_sym(s1->symtab, text_section->data_offset, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_FUNC), 0, - text_section->sh_num, "___GLOBAL_init_65535"); - at_exit_sym = put_elf_sym(s1->symtab, 0, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, - SHN_UNDEF, "___cxa_atexit"); -#ifdef TCC_TARGET_X86_64 - ptr = section_ptr_add(text_section, 4); - ptr[0] = 0x55; // pushq %rbp - ptr[1] = 0x48; // movq %rsp, %rbp - ptr[2] = 0x89; - ptr[3] = 0xe5; - for_each_elem(s->reloc, 0, rel, ElfW_Rel) { - int sym_index = ELFW(R_SYM)(rel->r_info); - - ptr = section_ptr_add(text_section, 26); - ptr[0] = 0x48; // lea destructor(%rip),%rax - ptr[1] = 0x8d; - ptr[2] = 0x05; - put_elf_reloca(s1->symtab, text_section, - text_section->data_offset - 23, - R_X86_64_PC32, sym_index, -4); - ptr[7] = 0x48; // mov %rax,%rdi - ptr[8] = 0x89; - ptr[9] = 0xc7; - ptr[10] = 0x31; // xorl %ecx, %ecx - ptr[11] = 0xc9; - ptr[12] = 0x89; // movl %ecx, %esi - ptr[13] = 0xce; - ptr[14] = 0x48; // lea mh_execute_header(%rip),%rdx - ptr[15] = 0x8d; - ptr[16] = 0x15; - put_elf_reloca(s1->symtab, text_section, - text_section->data_offset - 9, - R_X86_64_PC32, mh_execute_header, -4); - ptr[21] = 0xe8; // call __cxa_atexit - put_elf_reloca(s1->symtab, text_section, - text_section->data_offset - 4, - R_X86_64_PLT32, at_exit_sym, -4); - } - ptr = section_ptr_add(text_section, 2); - ptr[0] = 0x5d; // pop %rbp - ptr[1] = 0xc3; // ret -#elif defined TCC_TARGET_ARM64 - ptr = section_ptr_add(text_section, 8); - write32le(ptr, 0xa9bf7bfd); // stp x29, x30, [sp, #-16]! - write32le(ptr + 4, 0x910003fd); // mov x29, sp - for_each_elem(s->reloc, 0, rel, ElfW_Rel) { - int sym_index = ELFW(R_SYM)(rel->r_info); - - ptr = section_ptr_add(text_section, 24); - put_elf_reloc(s1->symtab, text_section, - text_section->data_offset - 24, - R_AARCH64_ADR_PREL_PG_HI21, sym_index); - write32le(ptr, 0x90000000); // adrp x0, destructor@page - put_elf_reloc(s1->symtab, text_section, - text_section->data_offset - 20, - R_AARCH64_LDST8_ABS_LO12_NC, sym_index); - write32le(ptr + 4, 0x91000000); // add x0,x0,destructor@pageoff - write32le(ptr + 8, 0xd2800001); // mov x1, #0 - put_elf_reloc(s1->symtab, text_section, - text_section->data_offset - 12, - R_AARCH64_ADR_PREL_PG_HI21, mh_execute_header); - write32le(ptr + 12, 0x90000002); // adrp x2, mh_execute_header@page - put_elf_reloc(s1->symtab, text_section, - text_section->data_offset - 8, - R_AARCH64_LDST8_ABS_LO12_NC, mh_execute_header); - write32le(ptr + 16, 0x91000042); // add x2,x2,mh_execute_header@pageoff - put_elf_reloc(s1->symtab, text_section, - text_section->data_offset - 4, - R_AARCH64_CALL26, at_exit_sym); - write32le(ptr + 20, 0x94000000); // bl __cxa_atexit - } - ptr = section_ptr_add(text_section, 8); - write32le(ptr, 0xa8c17bfd); // ldp x29, x30, [sp], #16 - write32le(ptr + 4, 0xd65f03c0); // ret -#endif - s->reloc->data_offset = s->data_offset = 0; - s->sh_flags &= ~SHF_ALLOC; - add_array (s1, ".init_array", init_sym); -} - -#ifdef CONFIG_NEW_MACHO -static void bind_rebase_add(struct macho *mo, int bind, int sh_info, - ElfW_Rel *rel, struct sym_attr *attr) -{ - mo->bind_rebase = tcc_realloc(mo->bind_rebase, (mo->n_bind_rebase + 1) * - sizeof(struct bind_rebase)); - mo->bind_rebase[mo->n_bind_rebase].section = sh_info; - mo->bind_rebase[mo->n_bind_rebase].bind = bind; - mo->bind_rebase[mo->n_bind_rebase].rel = *rel; - if (attr) - mo->bind_rebase[mo->n_bind_rebase].rel.r_offset = attr->got_offset; - mo->n_bind_rebase++; - mo->n_bind += bind; -} - -static void check_relocs(TCCState *s1, struct macho *mo) -{ - Section *s; - ElfW_Rel *rel, save_rel; - ElfW(Sym) *sym; - int i, j, type, gotplt_entry, sym_index, for_code; - uint32_t *pi, *goti; - struct sym_attr *attr; - - goti = NULL; - mo->nr_plt = mo->n_got = 0; - for (i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (s->sh_type != SHT_RELX || - !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) - continue; - for_each_elem(s, 0, rel, ElfW_Rel) { - save_rel = *rel; - type = ELFW(R_TYPE)(rel->r_info); - gotplt_entry = gotplt_entry_type(type); - for_code = code_reloc(type); - /* We generate a non-lazy pointer for used undefined symbols - and for defined symbols that must have a place for their - address due to codegen (i.e. a reloc requiring a got slot). */ - sym_index = ELFW(R_SYM)(rel->r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - if (sym->st_shndx == SHN_UNDEF - || gotplt_entry == ALWAYS_GOTPLT_ENTRY) { - attr = get_sym_attr(s1, sym_index, 1); - if (!attr->dyn_index) { - attr->got_offset = s1->got->data_offset; - attr->plt_offset = -1; - attr->dyn_index = 1; /* used as flag */ - section_ptr_add(s1->got, PTR_SIZE); - put_elf_reloc(s1->symtab, s1->got, attr->got_offset, - R_JMP_SLOT, sym_index); - goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); - if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { - if (sym->st_shndx == SHN_UNDEF) - tcc_error("undefined local symbo: '%s'", - (char *) symtab_section->link->data + sym->st_name); - goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL; - } else { - goti[mo->n_got++] = mo->e2msym[sym_index]; - if (sym->st_shndx == SHN_UNDEF -#ifdef TCC_TARGET_X86_64 - && type == R_X86_64_GOTPCREL -#elif defined TCC_TARGET_ARM64 - && type == R_AARCH64_ADR_GOT_PAGE -#endif - ) { - attr->plt_offset = -mo->n_bind_rebase - 2; - bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr); - s1->got->reloc->data_offset -= sizeof (ElfW_Rel); - } - if (for_code && sym->st_shndx == SHN_UNDEF) - s1->got->reloc->data_offset -= sizeof (ElfW_Rel); - } - } - if (for_code && sym->st_shndx == SHN_UNDEF) { - if ((int)attr->plt_offset < -1) { - /* remove above bind and replace with plt */ - mo->bind_rebase[-attr->plt_offset - 2].bind = 2; - attr->plt_offset = -1; - } - if (attr->plt_offset == -1) { - uint8_t *jmp; - - attr->plt_offset = mo->stubs->data_offset; -#ifdef TCC_TARGET_X86_64 - if (type != R_X86_64_PLT32) - continue; - jmp = section_ptr_add(mo->stubs, 6); - jmp[0] = 0xff; /* jmpq *ofs(%rip) */ - jmp[1] = 0x25; - put_elf_reloc(s1->symtab, mo->stubs, - attr->plt_offset + 2, - R_X86_64_GOTPCREL, sym_index); -#elif defined TCC_TARGET_ARM64 - if (type != R_AARCH64_CALL26) - continue; - jmp = section_ptr_add(mo->stubs, 12); - put_elf_reloc(s1->symtab, mo->stubs, - attr->plt_offset, - R_AARCH64_ADR_GOT_PAGE, sym_index); - write32le(jmp, // adrp x16, #sym - 0x90000010); - put_elf_reloc(s1->symtab, mo->stubs, - attr->plt_offset + 4, - R_AARCH64_LD64_GOT_LO12_NC, sym_index); - write32le(jmp + 4, // ld x16,[x16, #sym] - 0xf9400210); - write32le(jmp + 8, // br x16 - 0xd61f0200); -#endif - bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr); - pi = section_ptr_add(mo->indirsyms, sizeof(*pi)); - *pi = mo->e2msym[sym_index]; - mo->nr_plt++; - } - rel->r_info = ELFW(R_INFO)(mo->stubsym, type); - rel->r_addend += attr->plt_offset; - } - } - if (type == R_DATA_PTR || type == R_JMP_SLOT) - bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0, - s->sh_info, &save_rel, NULL); - } - } - /* remove deleted binds */ - for (i = 0, j = 0; i < mo->n_bind_rebase; i++) - if (mo->bind_rebase[i].bind == 2) - mo->n_bind--; - else - mo->bind_rebase[j++] = mo->bind_rebase[i]; - mo->n_bind_rebase = j; - pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi)); - memcpy(pi, goti, mo->n_got * sizeof(*pi)); - tcc_free(goti); -} - -#else - -static void check_relocs(TCCState *s1, struct macho *mo) -{ - uint8_t *jmp; - Section *s; - ElfW_Rel *rel, save_rel; - ElfW(Sym) *sym; - int i, type, gotplt_entry, sym_index, for_code; - int bind_offset, la_symbol_offset; - uint32_t *pi, *goti; - struct sym_attr *attr; - -#ifdef TCC_TARGET_X86_64 - jmp = section_ptr_add(mo->stub_helper, 16); - jmp[0] = 0x4c; /* leaq _dyld_private(%rip), %r11 */ - jmp[1] = 0x8d; - jmp[2] = 0x1d; - put_elf_reloca(s1->symtab, mo->stub_helper, 3, - R_X86_64_PC32, mo->dyld_private, -4); - jmp[7] = 0x41; /* pushq %r11 */ - jmp[8] = 0x53; - jmp[9] = 0xff; /* jmpq *dyld_stub_binder@GOT(%rip) */ - jmp[10] = 0x25; - put_elf_reloca(s1->symtab, mo->stub_helper, 11, - R_X86_64_GOTPCREL, mo->dyld_stub_binder, -4); - jmp[15] = 0x90; /* nop */ -#elif defined TCC_TARGET_ARM64 - jmp = section_ptr_add(mo->stub_helper, 24); - put_elf_reloc(s1->symtab, mo->stub_helper, 0, - R_AARCH64_ADR_PREL_PG_HI21, mo->dyld_private); - write32le(jmp, 0x90000011); // adrp x17, _dyld_private@page - put_elf_reloc(s1->symtab, mo->stub_helper, 4, - R_AARCH64_LDST64_ABS_LO12_NC, mo->dyld_private); - write32le(jmp + 4, 0x91000231); // add x17,x17,_dyld_private@pageoff - write32le(jmp + 8, 0xa9bf47f0); // stp x16/x17, [sp, #-16]! - put_elf_reloc(s1->symtab, mo->stub_helper, 12, - R_AARCH64_ADR_GOT_PAGE, mo->dyld_stub_binder); - write32le(jmp + 12, 0x90000010); // adrp x16, dyld_stub_binder@page - put_elf_reloc(s1->symtab, mo->stub_helper, 16, - R_AARCH64_LD64_GOT_LO12_NC, mo->dyld_stub_binder); - write32le(jmp + 16, 0xf9400210); // ldr x16,[x16,dyld_stub_binder@pageoff] - write32le(jmp + 20, 0xd61f0200); // br x16 -#endif - - goti = NULL; - mo->nr_plt = mo->n_got = 0; - for (i = 1; i < s1->nb_sections; i++) { - s = s1->sections[i]; - if (s->sh_type != SHT_RELX || - !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) - continue; - for_each_elem(s, 0, rel, ElfW_Rel) { - save_rel = *rel; - type = ELFW(R_TYPE)(rel->r_info); - gotplt_entry = gotplt_entry_type(type); - for_code = code_reloc(type); - /* We generate a non-lazy pointer for used undefined symbols - and for defined symbols that must have a place for their - address due to codegen (i.e. a reloc requiring a got slot). */ - sym_index = ELFW(R_SYM)(rel->r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - if (sym->st_shndx == SHN_UNDEF - || gotplt_entry == ALWAYS_GOTPLT_ENTRY) { - attr = get_sym_attr(s1, sym_index, 1); - if (!attr->dyn_index) { - attr->got_offset = s1->got->data_offset; - attr->plt_offset = -1; - attr->dyn_index = 1; /* used as flag */ - section_ptr_add(s1->got, PTR_SIZE); - put_elf_reloc(s1->symtab, s1->got, attr->got_offset, - R_JMP_SLOT, sym_index); - goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); - if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { - if (sym->st_shndx == SHN_UNDEF) - tcc_error("undefined local symbo: '%s'", - (char *) symtab_section->link->data + sym->st_name); - goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL; - } else { - goti[mo->n_got++] = mo->e2msym[sym_index]; - if (sym->st_shndx == SHN_UNDEF -#ifdef TCC_TARGET_X86_64 - && type == R_X86_64_GOTPCREL -#elif defined TCC_TARGET_ARM64 - && type == R_AARCH64_ADR_GOT_PAGE -#endif - ) { - mo->bind = - tcc_realloc(mo->bind, - (mo->n_bind + 1) * - sizeof(struct bind)); - mo->bind[mo->n_bind].section = s1->got->reloc->sh_info; - mo->bind[mo->n_bind].rel = save_rel; - mo->bind[mo->n_bind].rel.r_offset = attr->got_offset; - mo->n_bind++; - s1->got->reloc->data_offset -= sizeof (ElfW_Rel); - } - } - } - if (for_code && sym->st_shndx == SHN_UNDEF) { - if (attr->plt_offset == -1) { - attr->plt_offset = mo->stubs->data_offset; -#ifdef TCC_TARGET_X86_64 - if (type != R_X86_64_PLT32) - continue; - /* __stubs */ - jmp = section_ptr_add(mo->stubs, 6); - jmp[0] = 0xff; /* jmpq *__la_symbol_ptr(%rip) */ - jmp[1] = 0x25; - put_elf_reloca(s1->symtab, mo->stubs, - mo->stubs->data_offset - 4, - R_X86_64_PC32, mo->lasym, - mo->la_symbol_ptr->data_offset - 4); - - /* __stub_helper */ - bind_offset = mo->stub_helper->data_offset + 1; - jmp = section_ptr_add(mo->stub_helper, 10); - jmp[0] = 0x68; /* pushq $bind_offset */ - jmp[5] = 0xe9; /* jmpq __stub_helper */ - write32le(jmp + 6, -mo->stub_helper->data_offset); - - /* __la_symbol_ptr */ - la_symbol_offset = mo->la_symbol_ptr->data_offset; - put_elf_reloca(s1->symtab, mo->la_symbol_ptr, - mo->la_symbol_ptr->data_offset, - R_DATA_PTR, mo->helpsym, - mo->stub_helper->data_offset - 10); - section_ptr_add(mo->la_symbol_ptr, PTR_SIZE); -#elif defined TCC_TARGET_ARM64 - if (type != R_AARCH64_CALL26) - continue; - /* __stubs */ - jmp = section_ptr_add(mo->stubs, 12); - put_elf_reloca(s1->symtab, mo->stubs, - mo->stubs->data_offset - 12, - R_AARCH64_ADR_PREL_PG_HI21, mo->lasym, - mo->la_symbol_ptr->data_offset); - write32le(jmp, // adrp x16, __la_symbol_ptr@page - 0x90000010); - put_elf_reloca(s1->symtab, mo->stubs, - mo->stubs->data_offset - 8, - R_AARCH64_LDST64_ABS_LO12_NC, mo->lasym, - mo->la_symbol_ptr->data_offset); - write32le(jmp + 4, // ldr x16,[x16, __la_symbol_ptr@pageoff] - 0xf9400210); - write32le(jmp + 8, // br x16 - 0xd61f0200); - - /* __stub_helper */ - bind_offset = mo->stub_helper->data_offset + 8; - jmp = section_ptr_add(mo->stub_helper, 12); - write32le(jmp + 0, // ldr w16, l0 - 0x18000050); - write32le(jmp + 4, // b stubHelperHeader - 0x14000000 + - ((-(mo->stub_helper->data_offset - 8) / 4) & - 0x3ffffff)); - write32le(jmp + 8, 0); // l0: .long bind_offset - - /* __la_symbol_ptr */ - la_symbol_offset = mo->la_symbol_ptr->data_offset; - put_elf_reloca(s1->symtab, mo->la_symbol_ptr, - mo->la_symbol_ptr->data_offset, - R_DATA_PTR, mo->helpsym, - mo->stub_helper->data_offset - 12); - section_ptr_add(mo->la_symbol_ptr, PTR_SIZE); -#endif - mo->s_lazy_bind = - tcc_realloc(mo->s_lazy_bind, (mo->n_lazy_bind + 1) * - sizeof(struct s_lazy_bind)); - mo->s_lazy_bind[mo->n_lazy_bind].section = - mo->stub_helper->reloc->sh_info; - mo->s_lazy_bind[mo->n_lazy_bind].bind_offset = - bind_offset; - mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset = - la_symbol_offset; - mo->s_lazy_bind[mo->n_lazy_bind].rel = save_rel; - mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset = - attr->plt_offset; - mo->n_lazy_bind++; - pi = section_ptr_add(mo->indirsyms, sizeof(*pi)); - *pi = mo->e2msym[sym_index]; - mo->nr_plt++; - } - rel->r_info = ELFW(R_INFO)(mo->stubsym, type); - rel->r_addend += attr->plt_offset; - } - } - if (type == R_DATA_PTR || type == R_JMP_SLOT) { - if (sym->st_shndx == SHN_UNDEF) { - mo->bind = tcc_realloc(mo->bind, - (mo->n_bind + 1) * - sizeof(struct bind)); - mo->bind[mo->n_bind].section = s->sh_info; - mo->bind[mo->n_bind].rel = save_rel; - mo->n_bind++; - } - else { - mo->s_rebase = - tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * - sizeof(struct s_rebase)); - mo->s_rebase[mo->n_rebase].section = s->sh_info; - mo->s_rebase[mo->n_rebase].rel = save_rel; - mo->n_rebase++; - } - } - } - } - pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi)); - memcpy(pi, goti, mo->n_got * sizeof(*pi)); - pi = section_ptr_add(mo->indirsyms, mo->nr_plt * sizeof(*pi)); - memcpy(pi, mo->indirsyms->data, mo->nr_plt * sizeof(*pi)); - tcc_free(goti); -} -#endif - -static int check_symbols(TCCState *s1, struct macho *mo) -{ - int sym_index, sym_end; - int ret = 0; - - mo->ilocal = mo->iextdef = mo->iundef = -1; - sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); - for (sym_index = 1; sym_index < sym_end; ++sym_index) { - int elf_index = ((struct nlist_64 *)mo->symtab->data + sym_index - 1)->n_value; - ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + elf_index; - const char *name = (char*)symtab_section->link->data + sym->st_name; - unsigned type = ELFW(ST_TYPE)(sym->st_info); - unsigned bind = ELFW(ST_BIND)(sym->st_info); - unsigned vis = ELFW(ST_VISIBILITY)(sym->st_other); - - dprintf("%4d (%4d): %09lx %4d %4d %4d %3d %s\n", - sym_index, elf_index, (long)sym->st_value, - type, bind, vis, sym->st_shndx, name); - if (bind == STB_LOCAL) { - if (mo->ilocal == -1) - mo->ilocal = sym_index - 1; - if (mo->iextdef != -1 || mo->iundef != -1) - tcc_error("local syms after global ones"); - } else if (sym->st_shndx != SHN_UNDEF) { - if (mo->iextdef == -1) - mo->iextdef = sym_index - 1; - if (mo->iundef != -1) - tcc_error("external defined symbol after undefined"); - } else if (sym->st_shndx == SHN_UNDEF) { - if (mo->iundef == -1) - mo->iundef = sym_index - 1; - if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK - || s1->output_type != TCC_OUTPUT_EXE - || find_elf_sym(s1->dynsymtab_section, name)) { - /* Mark the symbol as coming from a dylib so that - relocate_syms doesn't complain. Normally bind_exe_dynsyms - would do this check, and place the symbol into dynsym - which is checked by relocate_syms. But Mach-O doesn't use - bind_exe_dynsyms. */ - sym->st_shndx = SHN_FROMDLL; - continue; - } - tcc_error_noabort("undefined symbol '%s'", name); - ret = -1; - } - } - return ret; -} - -static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn) -{ - struct nlist_64 n = *pn; - ElfSym *sym = (ElfW(Sym) *)symtab_section->data + pn->n_value; - const char *name = (char*)symtab_section->link->data + sym->st_name; - switch(ELFW(ST_TYPE)(sym->st_info)) { - case STT_NOTYPE: - case STT_OBJECT: - case STT_FUNC: - case STT_SECTION: - n.n_type = N_SECT; - break; - case STT_FILE: - n.n_type = N_ABS; - break; - default: - tcc_error("unhandled ELF symbol type %d %s", - ELFW(ST_TYPE)(sym->st_info), name); - } - if (sym->st_shndx == SHN_UNDEF) - tcc_error("should have been rewritten to SHN_FROMDLL: %s", name); - else if (sym->st_shndx == SHN_FROMDLL) - n.n_type = N_UNDF, n.n_sect = 0; - else if (sym->st_shndx == SHN_ABS) - n.n_type = N_ABS, n.n_sect = 0; - else if (sym->st_shndx >= SHN_LORESERVE) - tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name); - else if (!mo->elfsectomacho[sym->st_shndx]) { - if (strncmp(s1->sections[sym->st_shndx]->name, ".debug_", 7)) - tcc_error("ELF section %d(%s) not mapped into Mach-O for symbol %s", - sym->st_shndx, s1->sections[sym->st_shndx]->name, name); - } - else - n.n_sect = mo->elfsectomacho[sym->st_shndx]; - if (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL) - n.n_type |= N_EXT; - else if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) - n.n_desc |= N_WEAK_REF | (n.n_type != N_UNDF ? N_WEAK_DEF : 0); - n.n_strx = pn->n_strx; - n.n_value = sym->st_value; - *pn = n; -} - -static void convert_symbols(TCCState *s1, struct macho *mo) -{ - struct nlist_64 *pn; - for_each_elem(mo->symtab, 0, pn, struct nlist_64) - convert_symbol(s1, mo, pn); -} - -static int machosymcmp(const void *_a, const void *_b, void *arg) -{ - TCCState *s1 = arg; - int ea = ((struct nlist_64 *)_a)->n_value; - int eb = ((struct nlist_64 *)_b)->n_value; - ElfSym *sa = (ElfSym *)symtab_section->data + ea; - ElfSym *sb = (ElfSym *)symtab_section->data + eb; - int r; - /* locals, then defined externals, then undefined externals, the - last two sections also by name, otherwise stable sort */ - r = (ELFW(ST_BIND)(sb->st_info) == STB_LOCAL) - - (ELFW(ST_BIND)(sa->st_info) == STB_LOCAL); - if (r) - return r; - r = (sa->st_shndx == SHN_UNDEF) - (sb->st_shndx == SHN_UNDEF); - if (r) - return r; - if (ELFW(ST_BIND)(sa->st_info) != STB_LOCAL) { - const char * na = (char*)symtab_section->link->data + sa->st_name; - const char * nb = (char*)symtab_section->link->data + sb->st_name; - r = strcmp(na, nb); - if (r) - return r; - } - return ea - eb; -} - -/* cannot use qsort because code has to be reentrant */ -static void tcc_qsort (void *base, size_t nel, size_t width, - int (*comp)(const void *, const void *, void *), void *arg) -{ - size_t wnel, gap, wgap, i, j, k; - char *a, *b, tmp; - - wnel = width * nel; - for (gap = 0; ++gap < nel;) - gap *= 3; - while ( gap /= 3 ) { - wgap = width * gap; - for (i = wgap; i < wnel; i += width) { - for (j = i - wgap; ;j -= wgap) { - a = j + (char *)base; - b = a + wgap; - if ( (*comp)(a, b, arg) <= 0 ) - break; - k = width; - do { - tmp = *a; - *a++ = *b; - *b++ = tmp; - } while ( --k ); - if (j < wgap) - break; - } - } - } -} - -static void create_symtab(TCCState *s1, struct macho *mo) -{ - int sym_index, sym_end; - struct nlist_64 *pn; - - /* Stub creation belongs to check_relocs, but we need to create - the symbol now, so its included in the sorting. */ - mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); - s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); - mo->stubsym = put_elf_sym(s1->symtab, 0, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, - mo->stubs->sh_num, ".__stubs"); -#ifdef CONFIG_NEW_MACHO - mo->chained_fixups = new_section(s1, "CHAINED_FIXUPS", - SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); -#else - mo->stub_helper = new_section(s1, "__stub_helper", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); - mo->la_symbol_ptr = new_section(s1, "__la_symbol_ptr", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); - mo->helpsym = put_elf_sym(s1->symtab, 0, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, - mo->stub_helper->sh_num, ".__stub_helper"); - mo->lasym = put_elf_sym(s1->symtab, 0, 0, - ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, - mo->la_symbol_ptr->sh_num, ".__la_symbol_ptr"); - section_ptr_add(data_section, -data_section->data_offset & (PTR_SIZE - 1)); - mo->dyld_private = put_elf_sym(s1->symtab, data_section->data_offset, PTR_SIZE, - ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT), 0, - data_section->sh_num, ".__dyld_private"); - section_ptr_add(data_section, PTR_SIZE); - mo->dyld_stub_binder = put_elf_sym(s1->symtab, 0, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 0, - SHN_UNDEF, "dyld_stub_binder"); - mo->rebase = new_section(s1, "REBASE", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - mo->binding = new_section(s1, "BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - mo->weak_binding = new_section(s1, "WEAK_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); -#endif - mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - - mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); - put_elf_str(mo->strtab, " "); /* Mach-O starts strtab with a space */ - sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); - pn = section_ptr_add(mo->symtab, sizeof(*pn) * (sym_end - 1)); - for (sym_index = 1; sym_index < sym_end; ++sym_index) { - ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; - const char *name = (char*)symtab_section->link->data + sym->st_name; - pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name); - pn[sym_index - 1].n_value = sym_index; - } - section_ptr_add(mo->strtab, -mo->strtab->data_offset & (PTR_SIZE - 1)); - tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1); - mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym)); - mo->e2msym[0] = -1; - for (sym_index = 1; sym_index < sym_end; ++sym_index) { - mo->e2msym[pn[sym_index - 1].n_value] = sym_index - 1; - } -} - -const struct { - int seg_initial; - uint32_t flags; - const char *name; -} skinfo[sk_last] = { - /*[sk_unknown] =*/ { 0 }, - /*[sk_discard] =*/ { 0 }, - /*[sk_text] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS - | S_ATTR_SOME_INSTRUCTIONS, "__text" }, - /*[sk_stubs] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_SYMBOL_STUBS - | S_ATTR_SOME_INSTRUCTIONS , "__stubs" }, - /*[sk_stub_helper] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS - | S_ATTR_SOME_INSTRUCTIONS , "__stub_helper" }, - /*[sk_ro_data] =*/ { 2, S_REGULAR, "__rodata" }, - /*[sk_uw_info] =*/ { 0 }, - /*[sk_nl_ptr] =*/ { 2, S_NON_LAZY_SYMBOL_POINTERS, "__got" }, - /*[sk_debug_info] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_info" }, - /*[sk_debug_abbrev] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_abbrev" }, - /*[sk_debug_line] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_line" }, - /*[sk_debug_aranges] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_aranges" }, - /*[sk_debug_str] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_str" }, - /*[sk_debug_line_str] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_line_str" }, - /*[sk_stab] =*/ { 4, S_REGULAR, "__stab" }, - /*[sk_stab_str] =*/ { 4, S_REGULAR, "__stab_str" }, - /*[sk_la_ptr] =*/ { 4, S_LAZY_SYMBOL_POINTERS, "__la_symbol_ptr" }, - /*[sk_init] =*/ { 4, S_MOD_INIT_FUNC_POINTERS, "__mod_init_func" }, - /*[sk_fini] =*/ { 4, S_MOD_TERM_FUNC_POINTERS, "__mod_term_func" }, - /*[sk_rw_data] =*/ { 4, S_REGULAR, "__data" }, - /*[sk_bss] =*/ { 4, S_ZEROFILL, "__bss" }, - /*[sk_linkedit] =*/ { 5, S_REGULAR, NULL }, -}; - -#define START ((uint64_t)1 << 32) - -const struct { - int used; - const char *name; - uint64_t vmaddr; - uint64_t vmsize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t flags; -} all_segment[] = { - { 1, "__PAGEZERO", 0, START, 0, 0, 0 }, - { 0, "__TEXT", START, 0, 5, 5, 0 }, - { 0, "__DATA_CONST", -1, 0, 3, 3, SG_READ_ONLY }, - { 0, "__DWARF", -1, 0, 7, 3, 0 }, - { 0, "__DATA", -1, 0, 3, 3, 0 }, - { 1, "__LINKEDIT", -1, 0, 1, 1, 0 }, -}; - -#define N_SEGMENT (sizeof(all_segment)/sizeof(all_segment[0])) - -#ifdef CONFIG_NEW_MACHO -static void calc_fixup_size(TCCState *s1, struct macho *mo) -{ - int i, size; - - size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8; - size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8; - for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) { - int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE; - size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8; - } - size += mo->n_bind * sizeof (struct dyld_chained_import) + 1; - for (i = 0; i < mo->n_bind_rebase; i++) { - if (mo->bind_rebase[i].bind) { - int sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info); - ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - const char *name = (char *) symtab_section->link->data + sym->st_name; - size += strlen(name) + 1; - } - } - size = (size + 7) & -8; - section_ptr_add(mo->chained_fixups, size); -} - -#else - -static void set_segment_and_offset(TCCState *s1, struct macho *mo, addr_t addr, - uint8_t *ptr, int opcode, - Section *sec, addr_t offset) -{ - int i; - struct segment_command_64 *seg = NULL; - - for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) { - seg = get_segment(mo, i); - if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize)) - break; - } - *ptr = opcode | i; - write_uleb128(sec, offset - seg->vmaddr); -} - -static void bind_rebase(TCCState *s1, struct macho *mo) -{ - int i; - uint8_t *ptr; - ElfW(Sym) *sym; - const char *name; - - for (i = 0; i < mo->n_lazy_bind; i++) { - int sym_index = ELFW(R_SYM)(mo->s_lazy_bind[i].rel.r_info); - - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - name = (char *) symtab_section->link->data + sym->st_name; - write32le(mo->stub_helper->data + - mo->s_lazy_bind[i].bind_offset, - mo->lazy_binding->data_offset); - ptr = section_ptr_add(mo->lazy_binding, 1); - set_segment_and_offset(s1, mo, mo->la_symbol_ptr->sh_addr, ptr, - BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, - mo->lazy_binding, - mo->s_lazy_bind[i].la_symbol_offset + - mo->la_symbol_ptr->sh_addr); - ptr = section_ptr_add(mo->lazy_binding, 5 + strlen(name)); - *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | - (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf); - *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0; - strcpy((char *)ptr, name); - ptr += strlen(name) + 1; - *ptr++ = BIND_OPCODE_DO_BIND; - *ptr = BIND_OPCODE_DONE; - } - for (i = 0; i < mo->n_rebase; i++) { - Section *s = s1->sections[mo->s_rebase[i].section]; - - ptr = section_ptr_add(mo->rebase, 2); - *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER; - set_segment_and_offset(s1, mo, s->sh_addr, ptr, - REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, - mo->rebase, - mo->s_rebase[i].rel.r_offset + - s->sh_addr); - ptr = section_ptr_add(mo->rebase, 1); - *ptr = REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1; - } - for (i = 0; i < mo->n_bind; i++) { - int sym_index = ELFW(R_SYM)(mo->bind[i].rel.r_info); - Section *s = s1->sections[mo->bind[i].section]; - Section *binding; - - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - name = (char *) symtab_section->link->data + sym->st_name; - binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK - ? mo->weak_binding : mo->binding; - ptr = section_ptr_add(binding, 4 + (binding == mo->binding) + - strlen(name)); - if (binding == mo->binding) - *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | - (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf); - *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | - (binding == mo->weak_binding - ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0); - strcpy((char *)ptr, name); - ptr += strlen(name) + 1; - *ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER; - set_segment_and_offset(s1, mo, s->sh_addr, ptr, - BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, - binding, - mo->bind[i].rel.r_offset + s->sh_addr); - ptr = section_ptr_add(binding, 1); - *ptr++ = BIND_OPCODE_DO_BIND; - } - if (mo->rebase->data_offset) { - ptr = section_ptr_add(mo->rebase, 1); - *ptr = REBASE_OPCODE_DONE; - } - if (mo->binding->data_offset) { - ptr = section_ptr_add(mo->binding, 1); - *ptr = BIND_OPCODE_DONE; - } - if (mo->weak_binding->data_offset) { - ptr = section_ptr_add(mo->weak_binding, 1); - *ptr = BIND_OPCODE_DONE; - } - tcc_free(mo->s_lazy_bind); - tcc_free(mo->s_rebase); - tcc_free(mo->bind); -} -#endif - -struct trie_info { - const char *name; - int flag; - addr_t addr; - int str_size; - int term_size; -}; - -struct trie_node { - int start; - int end; - int index_start; - int index_end; - int n_child; - struct trie_node *child; -}; - -struct trie_seq { - int n_child; - struct trie_node *node; - int offset; - int nest_offset; -}; - -static void create_trie(struct trie_node *node, - int from, int to, int index_start, - int n_trie, struct trie_info *trie) -{ - int i; - int start, end, index_end; - char cur; - struct trie_node *child; - - for (i = from; i < to; i = end) { - cur = trie[i].name[index_start]; - start = i++; - for (; i < to; i++) - if (cur != trie[i].name[index_start]) - break; - end = i; - if (start == end - 1 || - (trie[start].name[index_start] && - trie[start].name[index_start + 1] == 0)) - index_end = trie[start].str_size - 1; - else { - index_end = index_start + 1; - for (;;) { - cur = trie[start].name[index_end]; - for (i = start + 1; i < end; i++) - if (cur != trie[i].name[index_end]) - break; - if (trie[start].name[index_end] && - trie[start].name[index_end + 1] == 0) { - end = start + 1; - index_end = trie[start].str_size - 1; - break; - } - if (i != end) - break; - index_end++; - } - } - node->child = tcc_realloc(node->child, - (node->n_child + 1) * - sizeof(struct trie_node)); - child = &node->child[node->n_child]; - child->start = start; - child->end = end; - child->index_start = index_start; - child->index_end = index_end; - child->n_child = 0; - child->child = NULL; - node->n_child++; - if (start != end - 1) - create_trie(child, start, end, index_end, n_trie, trie); - } -} - -static int create_seq(int *offset, int *n_seq, struct trie_seq **seq, - struct trie_node *node, - int n_trie, struct trie_info *trie) -{ - int i, nest_offset, last_seq = *n_seq, retval = *offset; - struct trie_seq *p_seq; - struct trie_node *p_nest; - - for (i = 0; i < node->n_child; i++) { - p_nest = &node->child[i]; - *seq = tcc_realloc(*seq, (*n_seq + 1) * sizeof(struct trie_seq)); - p_seq = &(*seq)[(*n_seq)++]; - p_seq->n_child = i == 0 ? node->n_child : -1; - p_seq->node = p_nest; - p_seq->offset = *offset; - p_seq->nest_offset = 0; - *offset += (i == 0 ? 1 + 1 : 0) + - p_nest->index_end - p_nest->index_start + 1 + 3; - } - for (i = 0; i < node->n_child; i++) { - nest_offset = - create_seq(offset, n_seq, seq, &node->child[i], n_trie, trie); - p_seq = &(*seq)[last_seq + i]; - p_seq->nest_offset = nest_offset; - } - return retval; -} - -static void node_free(struct trie_node *node) -{ - int i; - - for (i = 0; i < node->n_child; i++) - node_free(&node->child[i]); - tcc_free(node->child); -} - -static int triecmp(const void *_a, const void *_b, void *arg) -{ - struct trie_info *a = (struct trie_info *) _a; - struct trie_info *b = (struct trie_info *) _b; - int len_a = strlen(a->name); - int len_b = strlen(b->name); - - /* strange sorting needed. Name 'xx' should be after 'xx1' */ - if (!strncmp(a->name, b->name, len_a < len_b ? len_a : len_b)) - return len_a < len_b ? 1 : (len_a > len_b ? -1 : 0); - return strcmp(a->name, b->name); -} - -static void export_trie(TCCState *s1, struct macho *mo) -{ - int i, size, offset = 0, save_offset; - uint8_t *ptr; - int sym_index; - int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); - int n_trie = 0, n_seq = 0; - struct trie_info *trie = NULL, *p_trie; - struct trie_node node, *p_node; - struct trie_seq *seq = NULL; - addr_t vm_addr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr; - - for (sym_index = 1; sym_index < sym_end; ++sym_index) { - ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; - const char *name = (char*)symtab_section->link->data + sym->st_name; - - if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE && - (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL || - ELFW(ST_BIND)(sym->st_info) == STB_WEAK)) { - int flag = EXPORT_SYMBOL_FLAGS_KIND_REGULAR; - addr_t addr = - sym->st_value + s1->sections[sym->st_shndx]->sh_addr - vm_addr; - - if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) - flag |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; - dprintf ("%s %d %llx\n", name, flag, (long long)addr + vm_addr); - trie = tcc_realloc(trie, (n_trie + 1) * sizeof(struct trie_info)); - trie[n_trie].name = name; - trie[n_trie].flag = flag; - trie[n_trie].addr = addr; - trie[n_trie].str_size = strlen(name) + 1; - trie[n_trie].term_size = uleb128_size(flag) + uleb128_size(addr); - n_trie++; - } - } - if (n_trie) { - tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL); - memset(&node, 0, sizeof(node)); - create_trie(&node, 0, n_trie, 0, n_trie, trie); - create_seq(&offset, &n_seq, &seq, &node, n_trie, trie); - save_offset = offset; - for (i = 0; i < n_seq; i++) { - p_node = seq[i].node; - if (p_node->n_child == 0) { - p_trie = &trie[p_node->start]; - seq[i].nest_offset = offset; - offset += 1 + p_trie->term_size + 1; - } - } - for (i = 0; i < n_seq; i++) { - p_node = seq[i].node; - p_trie = &trie[p_node->start]; - if (seq[i].n_child >= 0) { - section_ptr_add(mo->exports, - seq[i].offset - mo->exports->data_offset); - ptr = section_ptr_add(mo->exports, 2); - *ptr++ = 0; - *ptr = seq[i].n_child; - } - size = p_node->index_end - p_node->index_start; - ptr = section_ptr_add(mo->exports, size + 1); - memcpy(ptr, &p_trie->name[p_node->index_start], size); - ptr[size] = 0; - write_uleb128(mo->exports, seq[i].nest_offset); - } - section_ptr_add(mo->exports, save_offset - mo->exports->data_offset); - for (i = 0; i < n_seq; i++) { - p_node = seq[i].node; - if (p_node->n_child == 0) { - p_trie = &trie[p_node->start]; - write_uleb128(mo->exports, p_trie->term_size); - write_uleb128(mo->exports, p_trie->flag); - write_uleb128(mo->exports, p_trie->addr); - ptr = section_ptr_add(mo->exports, 1); - *ptr = 0; - } - } - section_ptr_add(mo->exports, -mo->exports->data_offset & 7); - node_free(&node); - tcc_free(seq); - } - tcc_free(trie); -} - -static void collect_sections(TCCState *s1, struct macho *mo, const char *filename) -{ - int i, sk, numsec; - int used_segment[N_SEGMENT]; - uint64_t curaddr, fileofs; - Section *s; - struct segment_command_64 *seg; - struct dylib_command *dylib; -#ifdef CONFIG_NEW_MACHO - struct linkedit_data_command *chained_fixups_lc; - struct linkedit_data_command *export_trie_lc; -#endif - struct build_version_command *dyldbv; - struct source_version_command *dyldsv; - struct rpath_command *rpath; - struct dylinker_command *dyldlc; - struct symtab_command *symlc; - struct dysymtab_command *dysymlc; - char *str; - - for (i = 0; i < N_SEGMENT; i++) - used_segment[i] = all_segment[i].used; - - memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect)); - for (i = s1->nb_sections; i-- > 1;) { - int type, flags; - s = s1->sections[i]; - type = s->sh_type; - flags = s->sh_flags; - sk = sk_unknown; - /* debug sections have sometimes no SHF_ALLOC */ - if ((flags & SHF_ALLOC) || !strncmp(s->name, ".debug_", 7)) { - switch (type) { - default: sk = sk_unknown; break; - case SHT_INIT_ARRAY: sk = sk_init; break; - case SHT_FINI_ARRAY: sk = sk_fini; break; - case SHT_NOBITS: sk = sk_bss; break; - case SHT_SYMTAB: sk = sk_discard; break; - case SHT_STRTAB: - if (s == stabstr_section) - sk = sk_stab_str; - else - sk = sk_discard; - break; - case SHT_RELX: sk = sk_discard; break; - case SHT_LINKEDIT: sk = sk_linkedit; break; - case SHT_PROGBITS: - if (s == mo->stubs) - sk = sk_stubs; -#ifndef CONFIG_NEW_MACHO - else if (s == mo->stub_helper) - sk = sk_stub_helper; - else if (s == mo->la_symbol_ptr) - sk = sk_la_ptr; -#endif - else if (s == rodata_section) - sk = sk_ro_data; - else if (s == s1->got) - sk = sk_nl_ptr; - else if (s == stab_section) - sk = sk_stab; - else if (s == dwarf_info_section) - sk = sk_debug_info; - else if (s == dwarf_abbrev_section) - sk = sk_debug_abbrev; - else if (s == dwarf_line_section) - sk = sk_debug_line; - else if (s == dwarf_aranges_section) - sk = sk_debug_aranges; - else if (s == dwarf_str_section) - sk = sk_debug_str; - else if (s == dwarf_line_str_section) - sk = sk_debug_line_str; - else if (flags & SHF_EXECINSTR) - sk = sk_text; - else if (flags & SHF_WRITE) - sk = sk_rw_data; - else - sk = sk_ro_data; - break; - } - } else - sk = sk_discard; - s->prev = mo->sk_to_sect[sk].s; - mo->sk_to_sect[sk].s = s; - used_segment[skinfo[sk].seg_initial] = 1; - } - - if (s1->output_type != TCC_OUTPUT_EXE) - used_segment[0] = 0; - - for (i = 0; i < N_SEGMENT; i++) - if (used_segment[i]) { - seg = add_segment(mo, all_segment[i].name); - if (i == 1 && s1->output_type != TCC_OUTPUT_EXE) - seg->vmaddr = 0; - else - seg->vmaddr = all_segment[i].vmaddr; - seg->vmsize = all_segment[i].vmsize; - seg->maxprot = all_segment[i].maxprot; - seg->initprot = all_segment[i].initprot; - seg->flags = all_segment[i].flags; - for (sk = sk_unknown; sk < sk_last; sk++) - if (skinfo[sk].seg_initial == i) - mo->segment[sk] = mo->nseg - 1; - } - - if (s1->output_type != TCC_OUTPUT_EXE) { - const char *name = s1->install_name ? s1->install_name : filename; - i = (sizeof(*dylib) + strlen(name) + 1 + 7) &-8; - dylib = add_lc(mo, LC_ID_DYLIB, i); - dylib->name = sizeof(*dylib); - dylib->timestamp = 1; - dylib->current_version = - s1->current_version ? s1->current_version : 1 << 16; - dylib->compatibility_version = - s1->compatibility_version ? s1->compatibility_version : 1 << 16; - str = (char*)dylib + dylib->name; - strcpy(str, name); - } - -#ifdef CONFIG_NEW_MACHO - chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, - sizeof(struct linkedit_data_command)); - export_trie_lc = add_lc(mo, LC_DYLD_EXPORTS_TRIE, - sizeof(struct linkedit_data_command)); -#else - mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo)); -#endif - - symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); - dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); - - if (s1->output_type == TCC_OUTPUT_EXE) { - i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; - dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); - dyldlc->name = sizeof(*dyldlc); - str = (char*)dyldlc + dyldlc->name; - strcpy(str, "/usr/lib/dyld"); - } - - dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); - dyldbv->platform = PLATFORM_MACOS; - dyldbv->minos = (10 << 16) + (6 << 8); - dyldbv->sdk = (10 << 16) + (6 << 8); - dyldbv->ntools = 0; - - dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); - dyldsv->version = 0; - - if (s1->output_type == TCC_OUTPUT_EXE) { - mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); - mo->ep->entryoff = 4096; - } - - for(i = 0; i < s1->nb_loaded_dlls; i++) { - DLLReference *dllref = s1->loaded_dlls[i]; - if (dllref->level == 0) - add_dylib(mo, dllref->name); - } - - if (s1->rpath) { - char *path = s1->rpath, *end; - do { - end = strchr(path, ':'); - if (!end) - end = strchr(path, 0); - i = (sizeof(*rpath) + (end - path) + 1 + 7) &-8; - rpath = add_lc(mo, LC_RPATH, i); - rpath->path = sizeof(*rpath); - str = (char*)rpath + rpath->path; - memcpy(str, path, end - path); - str[end - path] = 0; - path = end + 1; - } while (*end); - } - - fileofs = 4096; /* leave space for mach-o headers */ - curaddr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr; - curaddr += 4096; - seg = NULL; - numsec = 0; - mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections); - for (sk = sk_unknown; sk < sk_last; sk++) { - struct section_64 *sec = NULL; - if (seg) { - seg->vmsize = curaddr - seg->vmaddr; - seg->filesize = fileofs - seg->fileoff; - } -#ifdef CONFIG_NEW_MACHO - if (sk == sk_linkedit) { - calc_fixup_size(s1, mo); - export_trie(s1, mo); - } -#else - if (sk == sk_linkedit) { - bind_rebase(s1, mo); - export_trie(s1, mo); - } -#endif - if (skinfo[sk].seg_initial && - (s1->output_type != TCC_OUTPUT_EXE || mo->segment[sk]) && - mo->sk_to_sect[sk].s) { - uint64_t al = 0; - int si; - seg = get_segment(mo, mo->segment[sk]); - if (skinfo[sk].name) { - si = add_section(mo, &seg, skinfo[sk].name); - numsec++; - mo->lc[mo->seg2lc[mo->segment[sk]]] = (struct load_command*)seg; - mo->sk_to_sect[sk].machosect = si; - sec = get_section(seg, si); - sec->flags = skinfo[sk].flags; - if (sk == sk_stubs) -#ifdef TCC_TARGET_X86_64 - sec->reserved2 = 6; -#elif defined TCC_TARGET_ARM64 - sec->reserved2 = 12; -#endif - if (sk == sk_nl_ptr) - sec->reserved1 = mo->nr_plt; -#ifndef CONFIG_NEW_MACHO - if (sk == sk_la_ptr) - sec->reserved1 = mo->nr_plt + mo->n_got; -#endif - } - if (seg->vmaddr == -1) { - curaddr = (curaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE; - seg->vmaddr = curaddr; - fileofs = (fileofs + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE; - seg->fileoff = fileofs; - } - - for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { - int a = exact_log2p1(s->sh_addralign); - if (a && al < (a - 1)) - al = a - 1; - s->sh_size = s->data_offset; - } - if (sec) - sec->align = al; - al = 1ULL << al; - if (al > 4096) - tcc_warning("alignment > 4096"), sec->align = 12, al = 4096; - curaddr = (curaddr + al - 1) & -al; - fileofs = (fileofs + al - 1) & -al; - if (sec) { - sec->addr = curaddr; - sec->offset = fileofs; - } - for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { - al = s->sh_addralign; - curaddr = (curaddr + al - 1) & -al; - dprintf("%s: curaddr now 0x%lx\n", s->name, (long)curaddr); - s->sh_addr = curaddr; - curaddr += s->sh_size; - if (s->sh_type != SHT_NOBITS) { - fileofs = (fileofs + al - 1) & -al; - s->sh_offset = fileofs; - fileofs += s->sh_size; - dprintf("%s: fileofs now %ld\n", s->name, (long)fileofs); - } - if (sec) - mo->elfsectomacho[s->sh_num] = numsec; - } - if (sec) - sec->size = curaddr - sec->addr; - } - if (DEBUG_MACHO) - for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { - int type = s->sh_type; - int flags = s->sh_flags; - printf("%d section %-16s %-10s %09lx %04x %02d %s,%s,%s\n", - sk, - s->name, - type == SHT_PROGBITS ? "progbits" : - type == SHT_NOBITS ? "nobits" : - type == SHT_SYMTAB ? "symtab" : - type == SHT_STRTAB ? "strtab" : - type == SHT_INIT_ARRAY ? "init" : - type == SHT_FINI_ARRAY ? "fini" : - type == SHT_RELX ? "rel" : "???", - (long)s->sh_addr, - (unsigned)s->data_offset, - s->sh_addralign, - flags & SHF_ALLOC ? "alloc" : "", - flags & SHF_WRITE ? "write" : "", - flags & SHF_EXECINSTR ? "exec" : "" - ); - } - } - if (seg) { - seg->vmsize = curaddr - seg->vmaddr; - seg->filesize = fileofs - seg->fileoff; - } - - /* Fill symtab info */ - symlc->symoff = mo->symtab->sh_offset; - symlc->nsyms = mo->symtab->data_offset / sizeof(struct nlist_64); - symlc->stroff = mo->strtab->sh_offset; - symlc->strsize = mo->strtab->data_offset; - - dysymlc->iundefsym = mo->iundef == -1 ? symlc->nsyms : mo->iundef; - dysymlc->iextdefsym = mo->iextdef == -1 ? dysymlc->iundefsym : mo->iextdef; - dysymlc->ilocalsym = mo->ilocal == -1 ? dysymlc->iextdefsym : mo->ilocal; - dysymlc->nlocalsym = dysymlc->iextdefsym - dysymlc->ilocalsym; - dysymlc->nextdefsym = dysymlc->iundefsym - dysymlc->iextdefsym; - dysymlc->nundefsym = symlc->nsyms - dysymlc->iundefsym; - dysymlc->indirectsymoff = mo->indirsyms->sh_offset; - dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t); - -#ifdef CONFIG_NEW_MACHO - if (mo->chained_fixups->data_offset) { - chained_fixups_lc->dataoff = mo->chained_fixups->sh_offset; - chained_fixups_lc->datasize = mo->chained_fixups->data_offset; - } - if (mo->exports->data_offset) { - export_trie_lc->dataoff = mo->exports->sh_offset; - export_trie_lc->datasize = mo->exports->data_offset; - } -#else - if (mo->rebase->data_offset) { - mo->dyldinfo->rebase_off = mo->rebase->sh_offset; - mo->dyldinfo->rebase_size = mo->rebase->data_offset; - } - if (mo->binding->data_offset) { - mo->dyldinfo->bind_off = mo->binding->sh_offset; - mo->dyldinfo->bind_size = mo->binding->data_offset; - } - if (mo->weak_binding->data_offset) { - mo->dyldinfo->weak_bind_off = mo->weak_binding->sh_offset; - mo->dyldinfo->weak_bind_size = mo->weak_binding->data_offset; - } - if (mo->lazy_binding->data_offset) { - mo->dyldinfo->lazy_bind_off = mo->lazy_binding->sh_offset; - mo->dyldinfo->lazy_bind_size = mo->lazy_binding->data_offset; - } - if (mo->exports->data_offset) { - mo->dyldinfo->export_off = mo->exports->sh_offset; - mo->dyldinfo->export_size = mo->exports->data_offset; - } -#endif -} - -static void macho_write(TCCState *s1, struct macho *mo, FILE *fp) -{ - int i, sk; - uint64_t fileofs = 0; - Section *s; - mo->mh.mh.magic = MH_MAGIC_64; -#ifdef TCC_TARGET_X86_64 - mo->mh.mh.cputype = CPU_TYPE_X86_64; - mo->mh.mh.cpusubtype = CPU_SUBTYPE_LIB64 | CPU_SUBTYPE_X86_ALL; -#elif defined TCC_TARGET_ARM64 - mo->mh.mh.cputype = CPU_TYPE_ARM64; - mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL; -#endif - if (s1->output_type == TCC_OUTPUT_EXE) { - mo->mh.mh.filetype = MH_EXECUTE; - mo->mh.mh.flags = MH_DYLDLINK | MH_PIE; - } - else { - mo->mh.mh.filetype = MH_DYLIB; - mo->mh.mh.flags = MH_DYLDLINK; - } - mo->mh.mh.ncmds = mo->nlc; - mo->mh.mh.sizeofcmds = 0; - for (i = 0; i < mo->nlc; i++) - mo->mh.mh.sizeofcmds += mo->lc[i]->cmdsize; - - fwrite(&mo->mh, 1, sizeof(mo->mh), fp); - fileofs += sizeof(mo->mh); - for (i = 0; i < mo->nlc; i++) { - fwrite(mo->lc[i], 1, mo->lc[i]->cmdsize, fp); - fileofs += mo->lc[i]->cmdsize; - } - - for (sk = sk_unknown; sk < sk_last; sk++) { - //struct segment_command_64 *seg; - if (skinfo[sk].seg_initial == 0 || - (s1->output_type == TCC_OUTPUT_EXE && !mo->segment[sk]) || - !mo->sk_to_sect[sk].s) - continue; - /*seg =*/ get_segment(mo, mo->segment[sk]); - for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { - if (s->sh_type != SHT_NOBITS) { - while (fileofs < s->sh_offset) - fputc(0, fp), fileofs++; - if (s->sh_size) { - fwrite(s->data, 1, s->sh_size, fp); - fileofs += s->sh_size; - } - } - } - } -} - -#ifdef CONFIG_NEW_MACHO -static int bind_rebase_cmp(const void *_a, const void *_b, void *arg) -{ - TCCState *s1 = arg; - struct bind_rebase *a = (struct bind_rebase *) _a; - struct bind_rebase *b = (struct bind_rebase *) _b; - addr_t aa = s1->sections[a->section]->sh_addr + a->rel.r_offset; - addr_t ab = s1->sections[b->section]->sh_addr + b->rel.r_offset; - - return aa > ab ? 1 : aa < ab ? -1 : 0; -} - -ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) -{ - int i, j, k, bind_index, size, page_count, sym_index; - const char *name; - ElfW(Sym) *sym; - unsigned char *data = mo->chained_fixups->data; - struct segment_command_64 *seg; - struct dyld_chained_fixups_header *header; - struct dyld_chained_starts_in_image *image; - struct dyld_chained_starts_in_segment *segment; - struct dyld_chained_import *import; - - tcc_qsort(mo->bind_rebase, mo->n_bind_rebase, sizeof(struct bind_rebase), - bind_rebase_cmp, s1); - for (i = 0; i < mo->n_bind_rebase - 1; i++) - if (mo->bind_rebase[i].section == mo->bind_rebase[i + 1].section && - mo->bind_rebase[i].rel.r_offset == mo->bind_rebase[i + 1].rel.r_offset) { - sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - name = (char *) symtab_section->link->data + sym->st_name; - tcc_error("Overlap %s/%s %s:%s", - mo->bind_rebase[i].bind ? "bind" : "rebase", - mo->bind_rebase[i + 1].bind ? "bind" : "rebase", - s1->sections[mo->bind_rebase[i].section]->name, name); - } - header = (struct dyld_chained_fixups_header *) data; - data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8; - header->starts_offset = data - mo->chained_fixups->data; - header->imports_count = mo->n_bind; - header->imports_format = DYLD_CHAINED_IMPORT; - header->symbols_format = 0; - size = sizeof(struct dyld_chained_starts_in_image) + - (mo->nseg - 1) * sizeof(uint32_t); - image = (struct dyld_chained_starts_in_image *) data; - data += (size + 7) & -8; - image->seg_count = mo->nseg; - for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) { - image->seg_info_offset[i] = (data - mo->chained_fixups->data) - - header->starts_offset; - seg = get_segment(mo, i); - page_count = (seg->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE; - size = sizeof(struct dyld_chained_starts_in_segment) + - (page_count - 1) * sizeof(uint16_t); - segment = (struct dyld_chained_starts_in_segment *) data; - data += (size + 7) & -8; - segment->size = size; - segment->page_size = SEG_PAGE_SIZE; -#if 1 -#define PTR_64_OFFSET 0 -#define PTR_64_MASK 0x7FFFFFFFFFFULL - segment->pointer_format = DYLD_CHAINED_PTR_64; -#else -#define PTR_64_OFFSET 0x100000000ULL -#define PTR_64_MASK 0xFFFFFFFFFFFFFFULL - segment->pointer_format = DYLD_CHAINED_PTR_64_OFFSET; -#endif - segment->segment_offset = seg->fileoff; - segment->max_valid_pointer = 0; - segment->page_count = page_count; - // add bind/rebase - bind_index = 0; - k = 0; - for (j = 0; j < page_count; j++) { - addr_t start = seg->vmaddr + j * SEG_PAGE_SIZE; - addr_t end = start + SEG_PAGE_SIZE; - void *last = NULL; - addr_t last_o = 0; - addr_t cur_o, cur; - struct dyld_chained_ptr_64_rebase *rebase; - struct dyld_chained_ptr_64_bind *bind; - - segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE; - for (; k < mo->n_bind_rebase; k++) { - Section *s = s1->sections[mo->bind_rebase[k].section]; - addr_t r_offset = mo->bind_rebase[k].rel.r_offset; - addr_t addr = s->sh_addr + r_offset; - - if ((addr & 3) || - (addr & (SEG_PAGE_SIZE - 1)) > SEG_PAGE_SIZE - PTR_SIZE) - tcc_error("Illegal rel_offset %s %lld", - s->name, (long long)r_offset); - if (addr >= end) - break; - if (addr >= start) { - cur_o = addr - start; - if (mo->bind_rebase[k].bind) { - if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE) - segment->page_start[j] = cur_o; - else { - bind = (struct dyld_chained_ptr_64_bind *) last; - bind->next = (cur_o - last_o) / 4; - } - bind = (struct dyld_chained_ptr_64_bind *) - (s->data + r_offset); - last = bind; - last_o = cur_o; - bind->ordinal = bind_index; - bind->addend = 0; - bind->reserved = 0; - bind->next = 0; - bind->bind = 1; - } - else { - if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE) - segment->page_start[j] = cur_o; - else { - rebase = (struct dyld_chained_ptr_64_rebase *) last; - rebase->next = (cur_o - last_o) / 4; - } - rebase = (struct dyld_chained_ptr_64_rebase *) - (s->data + r_offset); - last = rebase; - last_o = cur_o; - cur = (*(uint64_t *) (s->data + r_offset)) - - PTR_64_OFFSET; - rebase->target = cur & PTR_64_MASK; - rebase->high8 = cur >> (64 - 8); - if (cur != ((uint64_t)rebase->high8 << (64 - 8)) + rebase->target) - tcc_error("rebase error"); - rebase->reserved = 0; - rebase->next = 0; - rebase->bind = 0; - } - } - bind_index += mo->bind_rebase[k].bind; - } - } - } - // add imports - header->imports_offset = data - mo->chained_fixups->data; - import = (struct dyld_chained_import *) data; - data += mo->n_bind * sizeof (struct dyld_chained_import); - header->symbols_offset = data - mo->chained_fixups->data; - data++; - for (i = 0, bind_index = 0; i < mo->n_bind_rebase; i++) { - if (mo->bind_rebase[i].bind) { - import[bind_index].lib_ordinal = - BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xffu; - import[bind_index].name_offset = - (data - mo->chained_fixups->data) - header->symbols_offset; - sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - import[bind_index].weak_import = - ELFW(ST_BIND)(sym->st_info) == STB_WEAK; - name = (char *) symtab_section->link->data + sym->st_name; - strcpy((char *) data, name); - data += strlen(name) + 1; - bind_index++; - } - } - tcc_free(mo->bind_rebase); -} -#endif - -ST_FUNC int macho_output_file(TCCState *s1, const char *filename) -{ - int fd, mode, file_type; - FILE *fp; - int i, ret = -1; - struct macho mo; - - (void)memset(&mo, 0, sizeof(mo)); - - file_type = s1->output_type; - if (file_type == TCC_OUTPUT_OBJ) - mode = 0666; - else - mode = 0777; - unlink(filename); - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); - if (fd < 0 || (fp = fdopen(fd, "wb")) == NULL) { - tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno)); - return -1; - } - if (s1->verbose) - printf("<- %s\n", filename); - - tcc_add_runtime(s1); - tcc_macho_add_destructor(s1); - resolve_common_syms(s1); - create_symtab(s1, &mo); - check_relocs(s1, &mo); - ret = check_symbols(s1, &mo); - if (!ret) { - int save_output = s1->output_type; - - collect_sections(s1, &mo, filename); - relocate_syms(s1, s1->symtab, 0); - if (s1->output_type == TCC_OUTPUT_EXE) - mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1) - - get_segment(&mo, 1)->vmaddr; - if (s1->nb_errors) - goto do_ret; - // Macho uses bind/rebase instead of dynsym - s1->output_type = TCC_OUTPUT_EXE; - relocate_sections(s1); - s1->output_type = save_output; -#ifdef CONFIG_NEW_MACHO - bind_rebase_import(s1, &mo); -#endif - convert_symbols(s1, &mo); - macho_write(s1, &mo, fp); - } - - do_ret: - for (i = 0; i < mo.nlc; i++) - tcc_free(mo.lc[i]); - tcc_free(mo.seg2lc); - tcc_free(mo.lc); - tcc_free(mo.elfsectomacho); - tcc_free(mo.e2msym); - - fclose(fp); -#ifdef CONFIG_CODESIGN - if (!ret) { - char command[1024]; - int retval; - - snprintf(command, sizeof(command), "codesign -f -s - %s", filename); - retval = system (command); - if (retval == -1 || !(WIFEXITED(retval) && WEXITSTATUS(retval) == 0)) - tcc_error ("command failed '%s'", command); - } -#endif - return ret; -} - -static uint32_t macho_swap32(uint32_t x) -{ - return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8); -} -#define SWAP(x) (swap ? macho_swap32(x) : (x)) -#define tbd_parse_movepast(s) \ - (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL) -#define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs)) -#define tbd_parse_skipws while (*pos && (*pos==' '||*pos=='\n')) ++pos -#define tbd_parse_tramplequote if(*pos=='\''||*pos=='"') tbd_parse_trample -#define tbd_parse_tramplespace if(*pos==' ') tbd_parse_trample -#define tbd_parse_trample *pos++=0 - -#ifdef TCC_IS_NATIVE -/* Looks for the active developer SDK set by xcode-select (or the default - one set during installation.) */ -ST_FUNC void tcc_add_macos_sdkpath(TCCState* s) -{ - char *sdkroot = NULL, *pos = NULL; - void* xcs = dlopen("libxcselect.dylib", RTLD_GLOBAL | RTLD_LAZY); - CString path; - int (*f)(unsigned int, char**) = dlsym(xcs, "xcselect_host_sdk_path"); - cstr_new(&path); - if (f) f(1, &sdkroot); - if (sdkroot) - pos = strstr(sdkroot,"SDKs/MacOSX"); - if (pos) - cstr_printf(&path, "%.*s.sdk/usr/lib", (int)(pos - sdkroot + 11), sdkroot); - /* must use free from libc directly */ -#pragma push_macro("free") -#undef free - free(sdkroot); -#pragma pop_macro("free") - if (path.size) - tcc_add_library_path(s, (char*)path.data); - else - tcc_add_library_path(s, - "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" - ":" "/Applications/Xcode.app/Developer/SDKs/MacOSX.sdk/usr/lib" - ); - cstr_free(&path); -} - -ST_FUNC const char* macho_tbd_soname(const char* filename) { - char *soname, *data, *pos; - const char *ret = filename; - - int fd = open(filename,O_RDONLY); - if (fd<0) return ret; - pos = data = tcc_load_text(fd); - if (!tbd_parse_movepast("install-name: ")) goto the_end; - tbd_parse_skipws; - tbd_parse_tramplequote; - soname = pos; - if (!tbd_parse_movetoany("\n \"'")) goto the_end; - tbd_parse_trample; - ret = tcc_strdup(soname); -the_end: - tcc_free(data); - return ret; -} -#endif /* TCC_IS_NATIVE */ - -ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev) -{ - char *soname, *data, *pos; - int ret = -1; - - pos = data = tcc_load_text(fd); - if (!tbd_parse_movepast("install-name: ")) goto the_end; - tbd_parse_skipws; - tbd_parse_tramplequote; - soname = pos; - if (!tbd_parse_movetoany("\n \"'")) goto the_end; - tbd_parse_trample; - ret = 0; - if (tcc_add_dllref(s1, soname, lev)->found) - goto the_end; - while(pos) { - char* sym = NULL; - int cont = 1; - if (!tbd_parse_movepast("symbols: ")) break; - if (!tbd_parse_movepast("[")) break; - while (cont) { - tbd_parse_skipws; - tbd_parse_tramplequote; - sym = pos; - if (!tbd_parse_movetoany(",] \"'")) break; - tbd_parse_tramplequote; - tbd_parse_tramplespace; - tbd_parse_skipws; - if (*pos==0||*pos==']') cont=0; - tbd_parse_trample; - set_elf_sym(s1->dynsymtab_section, 0, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym); - } - } - -the_end: - tcc_free(data); - return ret; -} - -ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev) -{ - unsigned char buf[sizeof(struct mach_header_64)]; - void *buf2; - uint32_t machofs = 0; - struct fat_header fh; - struct mach_header mh; - struct load_command *lc; - int i, swap = 0; - const char *soname = filename; - struct nlist_64 *symtab = 0; - uint32_t nsyms = 0; - char *strtab = 0; - uint32_t strsize = 0; - uint32_t iextdef = 0; - uint32_t nextdef = 0; - - again: - if (full_read(fd, buf, sizeof(buf)) != sizeof(buf)) - return -1; - memcpy(&fh, buf, sizeof(fh)); - if (fh.magic == FAT_MAGIC || fh.magic == FAT_CIGAM) { - struct fat_arch *fa = load_data(fd, sizeof(fh), - fh.nfat_arch * sizeof(*fa)); - swap = fh.magic == FAT_CIGAM; - for (i = 0; i < SWAP(fh.nfat_arch); i++) -#ifdef TCC_TARGET_X86_64 - if (SWAP(fa[i].cputype) == CPU_TYPE_X86_64 - && SWAP(fa[i].cpusubtype) == CPU_SUBTYPE_X86_ALL) -#elif defined TCC_TARGET_ARM64 - if (SWAP(fa[i].cputype) == CPU_TYPE_ARM64 - && SWAP(fa[i].cpusubtype) == CPU_SUBTYPE_ARM64_ALL) -#endif - break; - if (i == SWAP(fh.nfat_arch)) { - tcc_free(fa); - return -1; - } - machofs = SWAP(fa[i].offset); - tcc_free(fa); - lseek(fd, machofs, SEEK_SET); - goto again; - } else if (fh.magic == FAT_MAGIC_64 || fh.magic == FAT_CIGAM_64) { - tcc_warning("%s: Mach-O fat 64bit files of type 0x%x not handled", - filename, fh.magic); - return -1; - } - - memcpy(&mh, buf, sizeof(mh)); - if (mh.magic != MH_MAGIC_64) - return -1; - dprintf("found Mach-O at %d\n", machofs); - buf2 = load_data(fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds); - for (i = 0, lc = buf2; i < mh.ncmds; i++) { - dprintf("lc %2d: 0x%08x\n", i, lc->cmd); - switch (lc->cmd) { - case LC_SYMTAB: - { - struct symtab_command *sc = (struct symtab_command*)lc; - nsyms = sc->nsyms; - symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab)); - strsize = sc->strsize; - strtab = load_data(fd, machofs + sc->stroff, strsize); - break; - } - case LC_ID_DYLIB: - { - struct dylib_command *dc = (struct dylib_command*)lc; - soname = (char*)lc + dc->name; - dprintf(" ID_DYLIB %d 0x%x 0x%x %s\n", - dc->timestamp, dc->current_version, - dc->compatibility_version, soname); - break; - } - case LC_REEXPORT_DYLIB: - { - struct dylib_command *dc = (struct dylib_command*)lc; - char *name = (char*)lc + dc->name; - int subfd = open(name, O_RDONLY | O_BINARY); - dprintf(" REEXPORT %s\n", name); - if (subfd < 0) - tcc_warning("can't open %s (reexported from %s)", name, filename); - else { - /* Hopefully the REEXPORTs never form a cycle, we don't check - for that! */ - macho_load_dll(s1, subfd, name, lev + 1); - close(subfd); - } - break; - } - case LC_DYSYMTAB: - { - struct dysymtab_command *dc = (struct dysymtab_command*)lc; - iextdef = dc->iextdefsym; - nextdef = dc->nextdefsym; - break; - } - } - lc = (struct load_command*) ((char*)lc + lc->cmdsize); - } - - if (tcc_add_dllref(s1, soname, lev)->found) - goto the_end; - - if (!nsyms || !nextdef) - tcc_warning("%s doesn't export any symbols?", filename); - - //dprintf("symbols (all):\n"); - dprintf("symbols (exported):\n"); - dprintf(" n: typ sec desc value name\n"); - //for (i = 0; i < nsyms; i++) { - for (i = iextdef; i < iextdef + nextdef; i++) { - struct nlist_64 *sym = symtab + i; - dprintf("%5d: %3d %3d 0x%04x 0x%016lx %s\n", - i, sym->n_type, sym->n_sect, sym->n_desc, (long)sym->n_value, - strtab + sym->n_strx); - set_elf_sym(s1->dynsymtab_section, 0, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), - 0, SHN_UNDEF, strtab + sym->n_strx); - } - - the_end: - tcc_free(strtab); - tcc_free(symtab); - tcc_free(buf2); - return 0; -}