diff --git a/reactos/tools/raddr2line.c b/reactos/tools/raddr2line.c index ffe7f34682e..63ebcf29915 100644 --- a/reactos/tools/raddr2line.c +++ b/reactos/tools/raddr2line.c @@ -18,8 +18,8 @@ size_t fixup_offset ( size_t ImageBase, size_t offset ) { - if ( offset >= ImageBase ) - offset -= ImageBase; +// if ( offset >= ImageBase ) +// offset -= ImageBase; return offset; } diff --git a/reactos/tools/rsym/dwarf2.h b/reactos/tools/rsym/dwarf2.h new file mode 100644 index 00000000000..04b6237d2a2 --- /dev/null +++ b/reactos/tools/rsym/dwarf2.h @@ -0,0 +1,844 @@ +/* Declarations and definitions of codes relating to the DWARF2 symbolic + debugging information format. + Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002, + 2003, 2004 Free Software Foundation, Inc. + + Written by Gary Funck (gary@intrepid.com) The Ada Joint Program + Office (AJPO), Florida State University and Silicon Graphics Inc. + provided support for this effort -- June 21, 1995. + + Derived from the DWARF 1 implementation written by Ron Guilmette + (rfg@netcom.com), November 1990. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + GCC 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 a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file is derived from the DWARF specification (a public document) + Revision 2.0.0 (July 27, 1993) developed by the UNIX International + Programming Languages Special Interest Group (UI/PLSIG) and distributed + by UNIX International. Copies of this specification are available from + UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. + + This file also now contains definitions from the DWARF 3 specification. */ + +/* This file is shared between GCC and GDB, and should not contain + prototypes. */ + +#ifndef GCC_DWARF2_H +#define GCC_DWARF2_H + +//#include "list.h" + +#include +/* Structure found in the .debug_line section. */ +typedef struct +{ + unsigned char li_length [4]; + unsigned char li_version [2]; + unsigned char li_prologue_length [4]; + unsigned char li_min_insn_length [1]; + unsigned char li_default_is_stmt [1]; + unsigned char li_line_base [1]; + unsigned char li_line_range [1]; + unsigned char li_opcode_base [1]; +} +DWARF2_External_LineInfo; + +typedef struct +{ + unsigned long li_length; + unsigned short li_version; + unsigned int li_prologue_length; + unsigned char li_min_insn_length; + unsigned char li_default_is_stmt; + int li_line_base; + unsigned char li_line_range; + unsigned char li_opcode_base; +} +DWARF2_Internal_LineInfo; + +/* Structure found in .debug_pubnames section. */ +typedef struct +{ + unsigned char pn_length [4]; + unsigned char pn_version [2]; + unsigned char pn_offset [4]; + unsigned char pn_size [4]; +} +DWARF2_External_PubNames; + +typedef struct +{ + unsigned long pn_length; + unsigned short pn_version; + unsigned long pn_offset; + unsigned long pn_size; +} +DWARF2_Internal_PubNames; + +/* Structure found in .debug_info section. */ +typedef struct +{ + unsigned char cu_length [4]; + unsigned char cu_version [2]; + unsigned char cu_abbrev_offset [4]; + unsigned char cu_pointer_size [1]; +} +DWARF2_External_CompUnit; + +typedef struct +{ + unsigned long cu_length; + unsigned short cu_version; + unsigned long cu_abbrev_offset; + unsigned char cu_pointer_size; +} +DWARF2_Internal_CompUnit; + +typedef struct +{ + unsigned char ar_length [4]; + unsigned char ar_version [2]; + unsigned char ar_info_offset [4]; + unsigned char ar_pointer_size [1]; + unsigned char ar_segment_size [1]; +} +DWARF2_External_ARange; + +typedef struct +{ + unsigned long ar_length; + unsigned short ar_version; + unsigned long ar_info_offset; + unsigned char ar_pointer_size; + unsigned char ar_segment_size; +} +DWARF2_Internal_ARange; +#include + +/* Tag names and codes. */ +enum dwarf_tag + { + DW_TAG_padding = 0x00, + 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, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + 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, + 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_param = 0x2f, + DW_TAG_template_value_param = 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, + /* DWARF 3. */ + 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, + /* SGI/MIPS Extensions. */ + DW_TAG_MIPS_loop = 0x4081, + /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */ + DW_TAG_HP_array_descriptor = 0x4090, + /* GNU extensions. */ + DW_TAG_format_label = 0x4101, /* For FORTRAN 77 and Fortran 90. */ + DW_TAG_function_template = 0x4102, /* For C++. */ + DW_TAG_class_template = 0x4103, /* For C++. */ + DW_TAG_GNU_BINCL = 0x4104, + DW_TAG_GNU_EINCL = 0x4105, + /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */ + DW_TAG_upc_shared_type = 0x8765, + DW_TAG_upc_strict_type = 0x8766, + DW_TAG_upc_relaxed_type = 0x8767, + /* PGI (STMicroelectronics) extensions. No documentation available. */ + DW_TAG_PGI_kanji_type = 0xA000, + DW_TAG_PGI_interface_block = 0xA020 + }; + +#define DW_TAG_lo_user 0x4080 +#define DW_TAG_hi_user 0xffff + +/* Flag that tells whether entry has a child or not. */ +#define DW_children_no 0 +#define DW_children_yes 1 + +/* Form names and codes. */ +enum dwarf_form + { + 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 + }; + +/* Attribute names and codes. */ +enum dwarf_attribute + { + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_subscr_data = 0x0a, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_element_list = 0x0f, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_member = 0x14, + 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, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_stride_size = 0x2e, + DW_AT_upper_bound = 0x2f, + 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, + DW_AT_namelist_items = 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, + /* DWARF 3 values. */ + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_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, + /* SGI/MIPS extensions. */ + 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, + /* HP extensions. */ + DW_AT_HP_block_index = 0x2000, + DW_AT_HP_unmodifiable = 0x2001, /* Same as DW_AT_MIPS_fde. */ + DW_AT_HP_actuals_stmt_list = 0x2010, + DW_AT_HP_proc_per_section = 0x2011, + DW_AT_HP_raw_data_ptr = 0x2012, + DW_AT_HP_pass_by_reference = 0x2013, + DW_AT_HP_opt_level = 0x2014, + DW_AT_HP_prof_version_id = 0x2015, + DW_AT_HP_opt_flags = 0x2016, + DW_AT_HP_cold_region_low_pc = 0x2017, + DW_AT_HP_cold_region_high_pc = 0x2018, + DW_AT_HP_all_variables_modifiable = 0x2019, + DW_AT_HP_linkage_name = 0x201a, + DW_AT_HP_prof_flags = 0x201b, /* In comp unit of procs_info for -g. */ + /* 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, + /* VMS extensions. */ + DW_AT_VMS_rtnbeg_pd_address = 0x2201, + /* UPC extension. */ + DW_AT_upc_threads_scaled = 0x3210, + /* PGI (STMicroelectronics) extensions. */ + DW_AT_PGI_lbase = 0x3a00, + DW_AT_PGI_soffset = 0x3a01, + DW_AT_PGI_lstride = 0x3a02 + }; + +#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */ +#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */ + +/* Location atom names and codes. */ +enum dwarf_location_atom + { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + 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, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_bra = 0x28, + 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, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit2 = 0x32, + DW_OP_lit3 = 0x33, + DW_OP_lit4 = 0x34, + DW_OP_lit5 = 0x35, + DW_OP_lit6 = 0x36, + DW_OP_lit7 = 0x37, + DW_OP_lit8 = 0x38, + DW_OP_lit9 = 0x39, + DW_OP_lit10 = 0x3a, + DW_OP_lit11 = 0x3b, + DW_OP_lit12 = 0x3c, + DW_OP_lit13 = 0x3d, + DW_OP_lit14 = 0x3e, + DW_OP_lit15 = 0x3f, + DW_OP_lit16 = 0x40, + DW_OP_lit17 = 0x41, + DW_OP_lit18 = 0x42, + DW_OP_lit19 = 0x43, + DW_OP_lit20 = 0x44, + DW_OP_lit21 = 0x45, + DW_OP_lit22 = 0x46, + DW_OP_lit23 = 0x47, + DW_OP_lit24 = 0x48, + DW_OP_lit25 = 0x49, + DW_OP_lit26 = 0x4a, + DW_OP_lit27 = 0x4b, + DW_OP_lit28 = 0x4c, + DW_OP_lit29 = 0x4d, + DW_OP_lit30 = 0x4e, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg2 = 0x52, + DW_OP_reg3 = 0x53, + DW_OP_reg4 = 0x54, + DW_OP_reg5 = 0x55, + DW_OP_reg6 = 0x56, + DW_OP_reg7 = 0x57, + DW_OP_reg8 = 0x58, + DW_OP_reg9 = 0x59, + DW_OP_reg10 = 0x5a, + DW_OP_reg11 = 0x5b, + DW_OP_reg12 = 0x5c, + DW_OP_reg13 = 0x5d, + DW_OP_reg14 = 0x5e, + DW_OP_reg15 = 0x5f, + DW_OP_reg16 = 0x60, + DW_OP_reg17 = 0x61, + DW_OP_reg18 = 0x62, + DW_OP_reg19 = 0x63, + DW_OP_reg20 = 0x64, + DW_OP_reg21 = 0x65, + DW_OP_reg22 = 0x66, + DW_OP_reg23 = 0x67, + DW_OP_reg24 = 0x68, + DW_OP_reg25 = 0x69, + DW_OP_reg26 = 0x6a, + DW_OP_reg27 = 0x6b, + DW_OP_reg28 = 0x6c, + DW_OP_reg29 = 0x6d, + DW_OP_reg30 = 0x6e, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg2 = 0x72, + DW_OP_breg3 = 0x73, + DW_OP_breg4 = 0x74, + DW_OP_breg5 = 0x75, + DW_OP_breg6 = 0x76, + DW_OP_breg7 = 0x77, + DW_OP_breg8 = 0x78, + DW_OP_breg9 = 0x79, + DW_OP_breg10 = 0x7a, + DW_OP_breg11 = 0x7b, + DW_OP_breg12 = 0x7c, + DW_OP_breg13 = 0x7d, + DW_OP_breg14 = 0x7e, + DW_OP_breg15 = 0x7f, + DW_OP_breg16 = 0x80, + DW_OP_breg17 = 0x81, + DW_OP_breg18 = 0x82, + DW_OP_breg19 = 0x83, + DW_OP_breg20 = 0x84, + DW_OP_breg21 = 0x85, + DW_OP_breg22 = 0x86, + DW_OP_breg23 = 0x87, + DW_OP_breg24 = 0x88, + DW_OP_breg25 = 0x89, + DW_OP_breg26 = 0x8a, + DW_OP_breg27 = 0x8b, + DW_OP_breg28 = 0x8c, + DW_OP_breg29 = 0x8d, + DW_OP_breg30 = 0x8e, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + /* DWARF 3 extensions. */ + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + /* GNU extensions. */ + DW_OP_GNU_push_tls_address = 0xe0, + /* HP extensions. */ + DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ + DW_OP_HP_is_value = 0xe1, + DW_OP_HP_fltconst4 = 0xe2, + DW_OP_HP_fltconst8 = 0xe3, + DW_OP_HP_mod_range = 0xe4, + DW_OP_HP_unmod_range = 0xe5, + DW_OP_HP_tls = 0xe6 + }; + +#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */ +#define DW_OP_hi_user 0xff /* Implementation-defined range end. */ + +/* Type encodings. */ +enum dwarf_type + { + 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, + /* DWARF 3. */ + DW_ATE_imaginary_float = 0x9, + /* HP extensions. */ + DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */ + DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */ + DW_ATE_HP_float128 = 0x82, /* Floating-point (128 bit). */ + DW_ATE_HP_complex_float128 = 0x83, /* Complex floating-point (128 bit). */ + DW_ATE_HP_floathpintel = 0x84, /* Floating-point (82 bit IA64). */ + DW_ATE_HP_imaginary_float80 = 0x85, + DW_ATE_HP_imaginary_float128 = 0x86 + }; + +#define DW_ATE_lo_user 0x80 +#define DW_ATE_hi_user 0xff + +/* Array ordering names and codes. */ +enum dwarf_array_dim_ordering + { + DW_ORD_row_major = 0, + DW_ORD_col_major = 1 + }; + +/* Access attribute. */ +enum dwarf_access_attribute + { + DW_ACCESS_public = 1, + DW_ACCESS_protected = 2, + DW_ACCESS_private = 3 + }; + +/* Visibility. */ +enum dwarf_visibility_attribute + { + DW_VIS_local = 1, + DW_VIS_exported = 2, + DW_VIS_qualified = 3 + }; + +/* Virtuality. */ +enum dwarf_virtuality_attribute + { + DW_VIRTUALITY_none = 0, + DW_VIRTUALITY_virtual = 1, + DW_VIRTUALITY_pure_virtual = 2 + }; + +/* Case sensitivity. */ +enum dwarf_id_case + { + DW_ID_case_sensitive = 0, + DW_ID_up_case = 1, + DW_ID_down_case = 2, + DW_ID_case_insensitive = 3 + }; + +/* Calling convention. */ +enum dwarf_calling_convention + { + DW_CC_normal = 0x1, + DW_CC_program = 0x2, + DW_CC_nocall = 0x3, + DW_CC_GNU_renesas_sh = 0x40 + }; + +#define DW_CC_lo_user 0x40 +#define DW_CC_hi_user 0xff + +/* Inline attribute. */ +enum dwarf_inline_attribute + { + DW_INL_not_inlined = 0, + DW_INL_inlined = 1, + DW_INL_declared_not_inlined = 2, + DW_INL_declared_inlined = 3 + }; + +/* Discriminant lists. */ +enum dwarf_discrim_list + { + DW_DSC_label = 0, + DW_DSC_range = 1 + }; + +/* Line number opcodes. */ +enum dwarf_line_number_ops + { + DW_LNS_extended_op = 0, + 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, + /* DWARF 3. */ + DW_LNS_set_prologue_end = 10, + DW_LNS_set_epilogue_begin = 11, + DW_LNS_set_isa = 12 + }; + +/* Line number extended opcodes. */ +enum dwarf_line_number_x_ops + { + DW_LNE_end_sequence = 1, + DW_LNE_set_address = 2, + DW_LNE_define_file = 3, + /* HP extensions. */ + DW_LNE_HP_negate_is_UV_update = 0x11, + DW_LNE_HP_push_context = 0x12, + DW_LNE_HP_pop_context = 0x13, + DW_LNE_HP_set_file_line_column = 0x14, + DW_LNE_HP_set_routine_name = 0x15, + DW_LNE_HP_set_sequence = 0x16, + DW_LNE_HP_negate_post_semantics = 0x17, + DW_LNE_HP_negate_function_exit = 0x18, + DW_LNE_HP_negate_front_end_logical = 0x19, + DW_LNE_HP_define_proc = 0x20 + }; + +/* Call frame information. */ +enum dwarf_call_frame_info + { + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + 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, + /* DWARF 3. */ + 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, + /* SGI/MIPS specific. */ + DW_CFA_MIPS_advance_loc8 = 0x1d, + /* GNU extensions. */ + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_GNU_negative_offset_extended = 0x2f + }; + +#define DW_CIE_ID 0xffffffff +#define DW_CIE_VERSION 1 + +#define DW_CFA_extended 0 +#define DW_CFA_lo_user 0x1c +#define DW_CFA_hi_user 0x3f + +#define DW_CHILDREN_no 0x00 +#define DW_CHILDREN_yes 0x01 + +#define DW_ADDR_none 0 + +/* Source language names and codes. */ +enum dwarf_source_language + { + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + /* DWARF 3. */ + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + /* MIPS. */ + DW_LANG_Mips_Assembler = 0x8001, + /* UPC. */ + DW_LANG_Upc = 0x8765 + }; + +#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */ +#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */ + +/* Names and codes for macro information. */ +enum dwarf_macinfo_record_type + { + DW_MACINFO_define = 1, + DW_MACINFO_undef = 2, + DW_MACINFO_start_file = 3, + DW_MACINFO_end_file = 4, + DW_MACINFO_vendor_ext = 255 + }; + +/* @@@ For use with GNU frame unwind information. */ + +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_omit 0xff + +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0A +#define DW_EH_PE_sdata4 0x0B +#define DW_EH_PE_sdata8 0x0C +#define DW_EH_PE_signed 0x08 + +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 + +#define DW_EH_PE_indirect 0x80 + +/** Private definitions ***/ + +typedef struct +{ + ULONG Length; + ULONG CiePointer; +} DW2CIEFDE; + +typedef struct +{ + ULONG Length; + char *Next; + ULONG CieId; + char Version; + ULONG ReturnAddressRegister; + ULONG AugStringLength; + char *AugString; + ULONG AugLength; + char *AugData; + ULONG CodeAlign; + LONG DataAlign; + char *Instructions; +} DW2CIE, *PDW2CIE; + +typedef struct +{ + unsigned long Length; + char *Next; + char *CiePointer; + unsigned long PcBegin; + unsigned long PcRange; + unsigned long AugLength; + char *AugData; + char *Instructions; +} DW2FDE, *PDW2FDE; + +typedef struct _SEHBLOCK +{ + unsigned long BeginTry; + unsigned long EndTry; + unsigned long Target; + unsigned long Handler; + unsigned long End; +} SEHBLOCK, *PSEHBLOCK; + +typedef struct _CFSTATE +{ + unsigned long Location; + unsigned long Code; + unsigned long Reg; + unsigned long Reg2; + long FramePtr; + long FramePtrDiff; + long Offset; + unsigned long IsUwop; + unsigned long Scope; + unsigned long cScopes; + unsigned long TryLevel; + SEHBLOCK SehBlock[20]; +} DW2CFSTATE, *PDW2CFSTATE; + +#define NextCIE(p) ((void*)((char*)p + p->Length + 4)) + + + +#endif /* dwarf2.h */ diff --git a/reactos/tools/rsym/rsym.h b/reactos/tools/rsym/rsym.h index 8f23daaf5a8..91b6c6d42b0 100644 --- a/reactos/tools/rsym/rsym.h +++ b/reactos/tools/rsym/rsym.h @@ -14,9 +14,26 @@ #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 #define IMAGE_SCN_TYPE_NOLOAD 0x00000002 +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 +#define IMAGE_SCN_LNK_OTHER 0x00000100 +#define IMAGE_SCN_LNK_INFO 0x00000200 #define IMAGE_SCN_LNK_REMOVE 0x00000800 -#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 +#define IMAGE_SCN_GPREL 0x00008000 +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 diff --git a/reactos/tools/rsym/rsym.mak b/reactos/tools/rsym/rsym.mak index 5cd46b93e0b..0adacedcae2 100644 --- a/reactos/tools/rsym/rsym.mak +++ b/reactos/tools/rsym/rsym.mak @@ -18,9 +18,15 @@ endif RSYM_TARGET = \ $(RSYM_OUT_)rsym$(EXEPOSTFIX) +ifeq ($(ARCH),amd64) +RSYM_SOURCES = \ + $(RSYM_BASE_)rsym64.c \ + $(RSYM_BASE_)rsym_common.c +else RSYM_SOURCES = \ $(RSYM_BASE_)rsym.c \ $(RSYM_BASE_)rsym_common.c +endif RSYM_OBJECTS = \ $(addprefix $(INTERMEDIATE_), $(RSYM_SOURCES:.c=.o)) @@ -44,6 +50,10 @@ $(RSYM_INT_)rsym.o: $(RSYM_BASE_)rsym.c | $(RSYM_INT) $(ECHO_CC) ${host_gcc} $(RSYM_HOST_CFLAGS) -c $< -o $@ +$(RSYM_INT_)rsym64.o: $(RSYM_BASE_)rsym64.c | $(RSYM_INT) + $(ECHO_CC) + ${host_gcc} $(RSYM_HOST_CFLAGS) -c $< -o $@ + $(RSYM_INT_)rsym_common.o: $(RSYM_BASE_)rsym_common.c | $(RSYM_INT) $(ECHO_CC) ${host_gcc} $(RSYM_HOST_CFLAGS) -c $< -o $@ diff --git a/reactos/tools/rsym/rsym64.c b/reactos/tools/rsym/rsym64.c new file mode 100644 index 00000000000..e078e651bf6 --- /dev/null +++ b/reactos/tools/rsym/rsym64.c @@ -0,0 +1,910 @@ +#include +#include +#include + +#include "rsym.h" +#include "rsym64.h" +#include "dwarf2.h" + +char DoPrint = 0; +ULONG g_ehframep; + +#define DPRINT if(DoPrint) printf + +struct {char *name; char regnt;} regs[] = +{ {"rax", REG_RAX}, {"rdx", REG_RDX}, {"rcx", REG_RCX}, {"rbx", REG_RBX}, + {"rsi", REG_RSI}, {"rdi", REG_RDI}, {"rbp", REG_RBP}, {"rsp", REG_RSP}, + {"r8", REG_R8}, {"r9", REG_R9}, {"r10", REG_R10}, {"r11", REG_R11}, + {"r12", REG_R12}, {"r13", REG_R13}, {"r14", REG_R14}, {"r15", REG_R15}, + {"xmm0", REG_XMM0}, {"xmm1", REG_XMM1}, {"xmm2", REG_XMM2}, {"xmm3", REG_XMM3}, + {"xmm4", REG_XMM4}, {"xmm5", REG_XMM5}, {"xmm6", REG_XMM6}, {"xmm7", REG_XMM7}, + {"xmm8", REG_XMM8}, {"xmm9", REG_XMM9}, {"xmm10",REG_XMM10},{"xmm11",REG_XMM11}, + {"xmm12",REG_XMM12},{"xmm13",REG_XMM13},{"xmm14",REG_XMM14},{"xmm15",REG_XMM15}, +// "st0", "st1", "st2", "st3", +// "st4", "st5", "st6", "st7", +// "mm0", "mm1", "mm2", "mm3", +// "mm4", "mm5", "mm6", "mm7" +}; + +/** Functions for DWARF2 ******************************************************/ + +unsigned long +DwDecodeUleb128(unsigned long *pResult, char *pc) +{ + unsigned long ulResult = 0; + unsigned long ulShift = 0; + unsigned char current; + unsigned long ulSize = 0; + + do + { + current = pc[ulSize]; + ulSize++; + ulResult |= (current & 0x7f) << ulShift; + ulShift += 7; + } + while (current & 0x80); + + *pResult = ulResult; + return ulSize; +} + +unsigned long +DwDecodeSleb128(long *pResult, char *pc) +{ + long lResult = 0; + unsigned long ulShift = 0; + unsigned char current; + unsigned long ulSize = 0; + + do + { + current = pc[ulSize]; + ulSize++; + lResult |= (current & 0x7f) << ulShift; + ulShift += 7; + } + while (current & 0x80); + + if (current & 0x40) + lResult |= - (1 << (ulShift)); + + *pResult = lResult; + + return ulSize; +} + +unsigned long +DwDecodeCie(PDW2CIE Cie, char *pc) +{ + Cie->Length = *(ULONG*)pc; + Cie->Next = pc + 4 + Cie->Length; + Cie->CieId = *(ULONG*)(pc + 4); + Cie->Version = pc[8]; + Cie->AugString = pc + 9; + Cie->AugStringLength = strlen(Cie->AugString); + pc = Cie->AugString + Cie->AugStringLength + 1; + pc += DwDecodeUleb128(&Cie->CodeAlign, pc); + pc += DwDecodeSleb128(&Cie->DataAlign, pc); + pc += DwDecodeUleb128(&Cie->ReturnAddressRegister, pc); + pc += DwDecodeUleb128(&Cie->AugLength, pc); + Cie->AugData = pc; + pc += Cie->AugLength; + Cie->Instructions = pc; + + return Cie->Length + 4; +} + +unsigned long +DwDecodeFde(PDW2FDE Fde, char *pc) +{ + Fde->Length = *(ULONG*)pc; + Fde->Next = pc + 4 + Fde->Length; + Fde->CiePointer = pc + 4 - *(ULONG*)(pc + 4); + Fde->PcBegin = *(ULONG*)(pc + 8); + Fde->PcRange = *(ULONG*)(pc + 12); + pc += 16; + pc += DwDecodeUleb128(&Fde->AugLength, pc); + Fde->AugData = pc; + Fde->Instructions = Fde->AugData + Fde->AugLength; + + return Fde->Length + 4; +} + +unsigned long +DwExecIntruction(PDW2CFSTATE State, char *pc) +{ + unsigned char Code; + unsigned long Length; + unsigned long PrevFramePtr = State->FramePtr; + + State->Scope = 0; + State->IsUwop = 0; + State->Code = Code = *pc; + Length = 1; + if ((Code & 0xc0) == DW_CFA_advance_loc) + { + State->Code = DW_CFA_advance_loc; + State->Location += Code & 0x3f; + } + else if ((Code & 0xc0) == DW_CFA_offset) + { + State->Code = DW_CFA_offset; + State->Reg = Code & 0x3f; + Length += DwDecodeUleb128((unsigned long*)&State->Offset, pc + 1); + State->Offset *= 8; // fixme data alignment + State->IsUwop = 1; + } + else if ((Code & 0xc0) == DW_CFA_restore) + { + State->Code = DW_CFA_restore; + State->Reg = Code & 0x3f; + } + else switch (Code) + { + case DW_CFA_nop: + break; + case DW_CFA_set_loc: + Length = 9; // address + State->Location = *(DWORD*)(pc + 1); + break; + case DW_CFA_advance_loc1: + Length = 2; + State->Location += pc[1]; + break; + case DW_CFA_advance_loc2: + Length = 3; +// printf("Found a DW_CFA_advance_loc2 : 0x%lx ->", *(WORD*)(pc + 1)); + State->Location += *(WORD*)(pc + 1); +// printf(" 0x%lx\n", State->Location); + break; + case DW_CFA_advance_loc4: + Length = 5; +// printf("Found a DW_CFA_advance_loc4 : 0x%lx ->", *(DWORD*)(pc + 1)); + State->Location += *(DWORD*)(pc + 1); +// printf(" 0x%lx\n", State->Location); + break; + case DW_CFA_offset_extended: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + Length += DwDecodeUleb128((unsigned long*)&State->Offset, pc + Length); + State->IsUwop = 1; + break; + case DW_CFA_offset_extended_sf: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + Length += DwDecodeSleb128(&State->Offset, pc + Length); + State->IsUwop = 1; + break; + case DW_CFA_restore_extended: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + break; + case DW_CFA_undefined: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + break; + case DW_CFA_same_value: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + break; + case DW_CFA_register: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + Length += DwDecodeUleb128(&State->Reg2, pc + Length); + break; + case DW_CFA_remember_state: + break; + case DW_CFA_restore_state: + break; + case DW_CFA_def_cfa: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + Length += DwDecodeUleb128((unsigned long*)&State->FramePtr, pc + Length); + State->IsUwop = 1; + break; + case DW_CFA_def_cfa_register: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + break; + case DW_CFA_def_cfa_offset: + Length += DwDecodeUleb128((unsigned long*)&State->FramePtr, pc + Length); + State->IsUwop = 1; + break; + case DW_CFA_def_cfa_sf: + Length += DwDecodeUleb128(&State->Reg, pc + Length); + Length += DwDecodeSleb128(&State->FramePtr, pc + Length); + State->FramePtr *= 8; // data alignment + State->IsUwop = 1; + break; + case DW_CFA_GNU_args_size: + { + unsigned long argsize; + printf("Warning, DW_CFA_GNU_args_size is unimplemented\n"); + Length += DwDecodeUleb128(&argsize, pc + Length); + break; + } + /* PSEH */ + case 0x21: + { + unsigned long SehType; + +// printf("found 0x21 at %lx\n", State->Location); + Length += DwDecodeUleb128(&SehType, pc + Length); + switch (SehType) + { + case 1: /* Begin Try */ + State->TryLevel++; + if (State->TryLevel >= 20) + { + printf("WTF? Trylevel of 20 exceeded...\n"); + exit(1); + } + State->SehBlock[State->TryLevel-1].BeginTry = State->Location; +// printf("Found begintry at 0x%lx\n", State->Location); + State->Scope = 1; + break; + + case 2: /* End Try */ + State->SehBlock[State->TryLevel-1].EndTry = State->Location; + State->Scope = 2; + break; + + case 3: /* Jump target */ + State->SehBlock[State->TryLevel-1].Target = State->Location; + State->Scope = 3; + break; + + case 4: /* SEH End */ + if (State->TryLevel == 20) + { + printf("Ooops, end of SEH with trylevel at 0!\n"); + exit(1); + } + State->SehBlock[State->TryLevel-1].End = State->Location; + State->TryLevel--; + State->cScopes++; + State->Scope = 0; + break; + + case 5: /* Constant filter */ + { + unsigned long value; + Length += DwDecodeUleb128(&value, pc + Length); + State->SehBlock[State->TryLevel-1].Handler = value; +// printf("Found a constant filter at 0x%lx\n", State->Location); + break; + } + + /* These work differently. We are in a new function. + * We have to parse a lea opcode to find the adress of + * the jump target. This is the reference to find the + * appropriate C_SCOPE_TABLE. */ + case 6: /* Filter func */ +// printf("Found a filter func at 0x%lx\n", State->Location); + break; + + case 7: /* Finally func */ + { +// printf("Found a finally func at 0x%lx\n", State->Location); + break; + } + + default: + printf("Found unknow PSEH code 0x%lx\n", SehType); + exit(1); + } + break; + } + default: + fprintf(stderr, "unknown instruction 0x%x at 0x%p\n", Code, pc); + exit(1); + } + + State->FramePtrDiff = State->FramePtr - PrevFramePtr; + DPRINT("@%p: code=%x, Loc=%lx, offset=%lx, reg=0x%lx:%s\n", + (void*)((ULONG)pc - g_ehframep), Code, State->Location, State->Offset, State->Reg, regs[State->Reg].name); + return Length; +} + +/** Windows unwind data functions *********************************************/ + +ULONG +StoreUnwindCodes(PUNWIND_INFO Info, PDW2CFSTATE State, ULONG FunctionStart) +{ + ULONG cCodes = 0; + ULONG AllocSize; + UNWIND_CODE Code[3]; + int i; + + Code[0].CodeOffset = State->Location - FunctionStart; + + switch (State->Code) + { + case DW_CFA_offset: + case DW_CFA_offset_extended: + // save register at offset + Code[0].OpInfo = regs[State->Reg].regnt; + if (State->Offset <= 0x7FFF8) + { + Code[0].UnwindOp = UWOP_SAVE_NONVOL; + Code[1].FrameOffset = State->Offset / 8; + cCodes = 2; + } + else + { + Code[0].UnwindOp = UWOP_SAVE_NONVOL_FAR; + Code[1].FrameOffset = (State->Offset / 8); + Code[2].FrameOffset = (State->Offset / 8) >> 16; + cCodes = 3; + } + break; + + case DW_CFA_def_cfa: + //case DW_CFA_def_cfa_register: + case DW_CFA_def_cfa_offset: + case DW_CFA_def_cfa_sf: + AllocSize = State->FramePtrDiff; + if (AllocSize <= 128) + { + Code[0].UnwindOp = UWOP_ALLOC_SMALL; + Code[0].OpInfo = (AllocSize / 8) - 1; + cCodes = 1; + } + else if (AllocSize <= 0x7FFF8) + { + Code[0].UnwindOp = UWOP_ALLOC_LARGE; + Code[0].OpInfo = 0; + Code[1].FrameOffset = AllocSize / 8; + cCodes = 2; + } + else // if (AllocSize > 0x7FFF8) + { + Code[0].UnwindOp = UWOP_ALLOC_LARGE; + Code[0].OpInfo = 1; + Code[1].FrameOffset = (USHORT)AllocSize; + Code[2].FrameOffset = (USHORT)(AllocSize >> 16); + cCodes = 3; + } + break; + } + + if (Info) + { + /* Move old codes */ + for (i = Info->CountOfCodes - 1; i >= 0; i--) + { + Info->UnwindCode[i + cCodes] = Info->UnwindCode[i]; + } + + /* Copy new codes */ + for (i = 0; i < cCodes; i++) + { + Info->UnwindCode[i] = Code[i]; + } + + Info->CountOfCodes += cCodes; + } + + return cCodes; +} + +#define GetxdataSize(cFuncs, cUWOP, cScopes) \ + ( cFuncs * (sizeof(UNWIND_INFO) + 2 + 4 + 4) \ + + cUWOP * sizeof(UNWIND_CODE) \ + + cScopes * sizeof(C_SCOPE_TABLE_ENTRY) ) + +ULONG +StoreUnwindInfo(PUNWIND_INFO Info, PDW2FDE pFde, ULONG FunctionStart) +{ + ULONG cbSize; + DW2CFSTATE State; + char *pInst; + ULONG c; + DW2CIE Cie; + + cbSize = 4; // sizeof(UNWIND_INFO); + Info->Version = 1; + Info->Flags = 0; + Info->SizeOfProlog = 0; + Info->CountOfCodes = 0; + Info->FrameRegister = 0; + Info->FrameOffset = 0; + + /* Decode the CIE */ + DwDecodeCie(&Cie, pFde->CiePointer); + + /* Initialize state */ + State.Location = FunctionStart; + State.FramePtr = 0; + State.TryLevel = 0; + State.cScopes = 0; + + /* Parse the CIE's initial instructions */ + pInst = Cie.Instructions; + while (pInst < Cie.Next) + { + pInst += DwExecIntruction(&State, pInst); + } + + /* Parse the FDE instructions */ + pInst = pFde->Instructions; + while (pInst < pFde->Next) + { + pInst += DwExecIntruction(&State, pInst); + + if (State.IsUwop) + { + c = StoreUnwindCodes(Info, &State, FunctionStart); + cbSize += c * sizeof(UNWIND_CODE); + Info->SizeOfProlog = State.Location - FunctionStart; + } + } + cbSize = ROUND_UP(cbSize, 4); + + /* Do we have scope table to write? */ + if (State.cScopes > 0) + { + unsigned long i; + ULONG *pExceptionHandler; + PC_SCOPE_TABLE pScopeTable; + + /* Set flag for exception handler */ + Info->Flags |= UNW_FLAG_EHANDLER; + + /* Store address of handler and number of scope tables */ + pExceptionHandler = (ULONG*)((char*)Info + cbSize); + // HACK for testing purpose + *pExceptionHandler = FunctionStart; // _C_specific_handler + + pScopeTable = (PC_SCOPE_TABLE)(pExceptionHandler + 1); + pScopeTable->NumEntries = State.cScopes; + + /* Store the scope table entries */ + for (i = 0; i < State.cScopes; i++) + { + pScopeTable->Entry[i].Begin = State.SehBlock[i].BeginTry; + pScopeTable->Entry[i].End = State.SehBlock[i].EndTry; + pScopeTable->Entry[i].Handler = 1;//State.SehBlock[i].Handler; + pScopeTable->Entry[i].Target = State.SehBlock[i].Target; + } + + /* Update size */ + cbSize += 8 + State.cScopes * sizeof(C_SCOPE_TABLE_ENTRY); + } + + return cbSize; +} + +void +CountUnwindData(PFILE_INFO File) +{ + DW2CIEFDE *p; + DW2FDE Fde; + char *pInst, *pmax; + DW2CFSTATE State; + + File->cFuncs = 0; + File->cScopes = 0; + File->cUWOP = 0; + State.FramePtr = 0; + State.TryLevel = 0; + + p = File->eh_frame.p; + pmax = (char*)p + File->eh_frame.psh->Misc.VirtualSize; + for (; p->Length && (char*)p < pmax; p = NextCIE(p)) + { + /* Is this an FDE? */ + if (p->CiePointer != 0) + { + File->cFuncs++; + DwDecodeFde(&Fde, (char*)p); + + pInst = Fde.Instructions; + while (pInst < Fde.Next) + { + pInst += DwExecIntruction(&State, pInst); + File->cUWOP += StoreUnwindCodes(NULL, &State, 0); + File->cScopes += State.Scope ? 1 : 0; + } + } + } + + return; +} + +int CompFunc(const void *p1, const void *p2) +{ + PRUNTIME_FUNCTION prf1 = (void*)p1, prf2 = (void*)p2; + return (prf1->FunctionStart > prf2->FunctionStart ? 1 : -1); +} + +void +GeneratePData(PFILE_INFO File) +{ + DW2CIEFDE *p; + DW2FDE Fde; + PIMAGE_DATA_DIRECTORY Dir; + ULONG i, Offset; + void * eh_frame; + PRUNTIME_FUNCTION pdata; + ULONG xdata_va; + char *xdata_p; + ULONG cbSize; + PIMAGE_SECTION_HEADER pshp, pshx; + ULONG FileAlignment; + char *pmax; + + FileAlignment = File->OptionalHeader->FileAlignment; + + /* Get pointer to eh_frame section */ + eh_frame = File->eh_frame.p; + g_ehframep = (ULONG)eh_frame; + + /* Get sizes */ + CountUnwindData(File); +// printf("cFuncs = %ld, cUWOPS = %ld, cScopes = %ld\n", +// File->cFuncs, File->cUWOP, File->cScopes); + + /* Initialize section header for .pdata */ + i = File->pdata.idx = File->UsedSections; + pshp = File->pdata.psh = &File->NewSectionHeaders[i]; + memcpy(pshp->Name, ".pdata", 7); + pshp->Misc.VirtualSize = (File->cFuncs + 1) * sizeof(RUNTIME_FUNCTION); + pshp->VirtualAddress = File->NewSectionHeaders[i - 1].VirtualAddress + + File->NewSectionHeaders[i - 1].SizeOfRawData; + pshp->SizeOfRawData = ROUND_UP(pshp->Misc.VirtualSize, FileAlignment); + pshp->PointerToRawData = File->NewSectionHeaders[i - 1].PointerToRawData + + File->NewSectionHeaders[i - 1].SizeOfRawData; + pshp->PointerToRelocations = 0; + pshp->PointerToLinenumbers = 0; + pshp->NumberOfRelocations = 0; + pshp->NumberOfLinenumbers = 0; + pshp->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_NOT_PAGED | + IMAGE_SCN_CNT_INITIALIZED_DATA; + + /* Allocate .pdata buffer */ + pdata = File->pdata.p = malloc(pshp->SizeOfRawData); + memset(File->pdata.p, pshp->SizeOfRawData, 0); + + /* Init exception data dir */ + Dir = &File->OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; + Dir->VirtualAddress = pshp->VirtualAddress; + Dir->Size = pshp->Misc.VirtualSize; + + /* Initialize section header for .xdata */ + File->xdata.idx = File->pdata.idx + 1; + pshx = File->xdata.psh = &File->NewSectionHeaders[File->xdata.idx]; + memcpy(pshx->Name, ".xdata", 7); + pshx->Misc.VirtualSize = GetxdataSize(File->cFuncs, File->cUWOP, File->cScopes); + pshx->VirtualAddress = pshp->VirtualAddress + pshp->SizeOfRawData; + pshx->SizeOfRawData = ROUND_UP(pshx->Misc.VirtualSize, FileAlignment); + pshx->PointerToRawData = pshp->PointerToRawData + pshp->SizeOfRawData; + pshx->PointerToRelocations = 0; + pshx->PointerToLinenumbers = 0; + pshx->NumberOfRelocations = 0; + pshx->NumberOfLinenumbers = 0; + pshx->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_NOT_PAGED | + IMAGE_SCN_CNT_INITIALIZED_DATA; + + /* Allocate .xdata buffer */ + File->xdata.p = malloc(pshx->SizeOfRawData); + memset(File->xdata.p, pshx->SizeOfRawData, 0); + + i = 0; + Offset = File->eh_frame.psh->VirtualAddress; + xdata_va = pshx->VirtualAddress; + xdata_p = File->xdata.p; + pmax = (char*)eh_frame + File->eh_frame.psh->Misc.VirtualSize - 100; + + for (p = eh_frame; p->Length && (char*)p < pmax; p = NextCIE(p)) + { + /* Is this an FDE? */ + if (p->CiePointer != 0) + { + DwDecodeFde(&Fde, (char*)p); + pdata[i].FunctionStart = Offset + 8 + Fde.PcBegin; + pdata[i].FunctionEnd = pdata[i].FunctionStart + Fde.PcRange; + pdata[i].UnwindInfo = xdata_va; + +// printf("%ld: RUNTIME_FUNCTION: {0x%lx, 0x%lx, 0x%lx}\n", i, pdata[i].FunctionStart, pdata[i].FunctionEnd, pdata[i].UnwindInfo); + + cbSize = StoreUnwindInfo((void*)xdata_p, &Fde, pdata[i].FunctionStart); + xdata_va += cbSize; + xdata_p += cbSize; + i++; + } + Offset += 4 + p->Length; + } + + /* Sort the RUNTIME_FUNCTIONS */ + qsort(pdata, i, sizeof(RUNTIME_FUNCTION), CompFunc); + +} + +/** Functions for COFF ********************************************************/ + + +WORD +CalculateChecksum(DWORD Start, void *pFile, ULONG cbSize) +{ + WORD *Ptr = pFile; + DWORD i; + DWORD checksum = Start; + + for (i = 0; i < (cbSize + 1) / sizeof(WORD); i++) + { + checksum += Ptr[i]; + checksum = (checksum + (checksum >> 16)) & 0xffff; + } + + return checksum ; +} + +void +WriteOutFile(FILE *handle, PFILE_INFO File) +{ + int ret, Size, Pos = 0; + DWORD CheckSum; + ULONG i, Alignment; + + Alignment = File->OptionalHeader->FileAlignment; + + /* Update section count */ + File->FileHeader->NumberOfSections = File->UsedSections + 2; // FIXME!!! + + /* Update SizeOfImage */ + Size = File->xdata.psh->VirtualAddress + + File->xdata.psh->SizeOfRawData; + File->OptionalHeader->SizeOfImage = Size; + + /* Recalculate checksum */ + CheckSum = CalculateChecksum(0, File->FilePtr, File->HeaderSize); + for (i = 0; i < File->AllSections; i++) + { + if (File->UseSection[i]) + { + Size = File->SectionHeaders[i].SizeOfRawData; + if (Size) + { + void *p; + p = File->FilePtr + File->SectionHeaders[i].PointerToRawData; + CheckSum = CalculateChecksum(CheckSum, p, Size); + } + } + } + Size = File->pdata.psh->Misc.VirtualSize; + CheckSum = CalculateChecksum(CheckSum, File->pdata.p, Size); + Size = File->xdata.psh->Misc.VirtualSize; + CheckSum = CalculateChecksum(CheckSum, File->xdata.p, Size); + CheckSum += File->HeaderSize; + CheckSum += File->pdata.psh->Misc.VirtualSize; + CheckSum += File->xdata.psh->Misc.VirtualSize; + File->OptionalHeader->CheckSum = CheckSum; + + /* Write file header */ + Size = File->HeaderSize; + ret = fwrite(File->DosHeader, 1, Size, handle); + Pos = Size; + + /* Write Section headers */ + Size = File->NewSectionHeaderSize; + ret = fwrite(File->NewSectionHeaders, 1, Size, handle); + Pos += Size; + + /* Fill up to next alignement */ + Size = ROUND_UP(Pos, Alignment) - Pos; + ret = fwrite(File->AlignBuf, 1, Size, handle); + Pos += Size; + + /* Write sections */ + for (i = 0; i < File->AllSections; i++) + { + if (File->UseSection[i]) + { + void *p; + Size = File->SectionHeaders[i].SizeOfRawData; + if (Size) + { + p = File->FilePtr + File->SectionHeaders[i].PointerToRawData; + ret = fwrite(p, 1, Size, handle); + Pos += Size; + } + } + } + + /* Write .pdata section */ + Size = File->pdata.psh->SizeOfRawData; + ret = fwrite(File->pdata.p, 1, Size, handle); + Pos += Size; + + /* Write .xdata section */ + Size = File->xdata.psh->SizeOfRawData; + ret = fwrite(File->xdata.p, 1, Size, handle); + Pos += Size; + +} + + +int +ParsePEHeaders(PFILE_INFO File) +{ + DWORD OldChecksum, Checksum; + ULONG Alignment, CurrentPos; + int i, j; + + /* Check if MZ header exists */ + File->DosHeader = (PIMAGE_DOS_HEADER)File->FilePtr; + if ((File->DosHeader->e_magic != IMAGE_DOS_MAGIC) || + (File->DosHeader->e_lfanew == 0L)) + { + perror("Input file is not a PE image.\n"); + return -1; + } + + /* Locate PE file header */ + File->FileHeader = (PIMAGE_FILE_HEADER)(File->FilePtr + + File->DosHeader->e_lfanew + sizeof(ULONG)); + + /* Check for x64 image */ + if (File->FileHeader->Machine != IMAGE_FILE_MACHINE_AMD64) + { + perror("Input file is not an x64 image.\n"); + return -1; + } + + /* Locate optional header */ + File->OptionalHeader = (PIMAGE_OPTIONAL_HEADER64)(File->FileHeader + 1); + + /* Check if checksum is correct */ + OldChecksum = File->OptionalHeader->CheckSum; + File->OptionalHeader->CheckSum = 0; + Checksum = CalculateChecksum(0, File->FilePtr, File->cbInFileSize); + Checksum += File->cbInFileSize; + if ((Checksum & 0xffff) != (OldChecksum & 0xffff)) + { + fprintf(stderr, "Input file has incorrect PE checksum: 0x%lx (calculated: 0x%lx)\n", + OldChecksum, Checksum); +// return 0; + } + + /* Locate PE section headers */ + File->SectionHeaders = (PIMAGE_SECTION_HEADER)((char*)File->OptionalHeader + + File->FileHeader->SizeOfOptionalHeader); + + File->HeaderSize = File->DosHeader->e_lfanew + + sizeof(ULONG) + + sizeof(IMAGE_FILE_HEADER) + + File->FileHeader->SizeOfOptionalHeader; + + if (!File->FileHeader->PointerToSymbolTable) + { + fprintf(stderr, "No symbol table.\n"); + return -1; + } + + /* Create some shortcuts */ + File->ImageBase = File->OptionalHeader->ImageBase; + File->Symbols = File->FilePtr + File->FileHeader->PointerToSymbolTable; + File->Strings = (char*)File->Symbols + File->FileHeader->NumberOfSymbols * 18; + + /* Check section names */ + File->AllSections = File->FileHeader->NumberOfSections; + Alignment = File->OptionalHeader->FileAlignment; + File->NewSectionHeaders = malloc((File->AllSections+2) * sizeof(IMAGE_SECTION_HEADER)); + File->UsedSections = 0; + File->eh_frame.idx = -1; + + /* Allocate array of chars, specifiying wheter to copy the section */ + File->UseSection = malloc(File->AllSections); + + for (i = 0; i < File->AllSections; i++) + { + char *pName = (char*)File->SectionHeaders[i].Name; + File->UseSection[i] = 1; + + /* Check for long name */ + if (pName[0] == '/') + { + unsigned long index = strtoul(pName+1, 0, 10); + pName = File->Strings + index; + + // Hack, simply remove all sections with long names + File->UseSection[i] = 0; + } + + /* Chek if we have the eh_frame section */ + if (strcmp(pName, ".eh_frame") == 0) + { + File->eh_frame.psh = &File->SectionHeaders[i]; + File->eh_frame.idx = i; + File->eh_frame.p = File->FilePtr + File->eh_frame.psh->PointerToRawData; + } + + /* Increase number of used sections */ + if (File->UseSection[i]) + File->UsedSections = i+1; + + } + + /* This is the actual size of the new section headers */ + File->NewSectionHeaderSize = + (File->UsedSections+2) * sizeof(IMAGE_SECTION_HEADER); + + /* Calculate the position to start writing the sections to */ + CurrentPos = File->HeaderSize + File->NewSectionHeaderSize; + CurrentPos = ROUND_UP(CurrentPos, Alignment); + + /* Create new section headers */ + for (i = 0, j = 0; i < File->UsedSections; i++) + { + /* Copy section header */ + File->NewSectionHeaders[j] = File->SectionHeaders[i]; + + /* Shall we strip the section? */ + if (File->UseSection[i] == 0) + { + /* Make it a bss section */ + File->NewSectionHeaders[j].PointerToRawData = 0; + File->NewSectionHeaders[j].SizeOfRawData = 0; + File->NewSectionHeaders[j].Characteristics = 0xC0500080; + } + + /* Fix Offset into File */ + File->NewSectionHeaders[j].PointerToRawData = + File->NewSectionHeaders[j].PointerToRawData ? CurrentPos : 0; + CurrentPos += File->NewSectionHeaders[j].SizeOfRawData; + j++; + } + + if (File->eh_frame.idx == -1) + { + fprintf(stderr, "No .eh_frame section found\n"); + return 0; + } + + return 1; +} + +int main(int argc, char* argv[]) +{ + char* pszInFile; + char* pszOutFile; + FILE_INFO File; + FILE* outfile; + int ret; + + if (argc != 3) + { + fprintf(stderr, "Usage: rsym \n"); + exit(1); + } + + pszInFile = convert_path(argv[1]); + pszOutFile = convert_path(argv[2]); + + File.FilePtr = load_file(pszInFile, &File.cbInFileSize); + if (!File.FilePtr) + { + fprintf(stderr, "An error occured loading '%s'\n", pszInFile); + exit(1); + } + + ret = ParsePEHeaders(&File); + if (ret != 1) + { + free(File.FilePtr); + exit(ret == -1 ? 1 : 0); + } + + File.AlignBuf = malloc(File.OptionalHeader->FileAlignment); + memset(File.AlignBuf, File.OptionalHeader->FileAlignment, 0); + + GeneratePData(&File); + + outfile = fopen(pszOutFile, "wb"); + if (outfile == NULL) + { + perror("Cannot open output file"); + free(File.FilePtr); + exit(1); + } + + WriteOutFile(outfile, &File); + + fclose(outfile); + + return 0; +} diff --git a/reactos/tools/rsym/rsym64.h b/reactos/tools/rsym/rsym64.h new file mode 100644 index 00000000000..521b55cbad9 --- /dev/null +++ b/reactos/tools/rsym/rsym64.h @@ -0,0 +1,185 @@ + +#ifndef _RSYM64_H +#define _RSYM64_H + +//C_ASSERT(sizeof(ULONG) == 4); +typedef unsigned char UBYTE; +typedef unsigned __int64 ULONG64; + +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 + +#define UWOP_PUSH_NONVOL 0 +#define UWOP_ALLOC_LARGE 1 +#define UWOP_ALLOC_SMALL 2 +#define UWOP_SET_FPREG 3 +#define UWOP_SAVE_NONVOL 4 +#define UWOP_SAVE_NONVOL_FAR 5 +#define UWOP_SAVE_XMM 6 +#define UWOP_SAVE_XMM_FAR 7 +#define UWOP_SAVE_XMM128 8 +#define UWOP_SAVE_XMM128_FAR 9 +#define UWOP_PUSH_MACHFRAME 10 + +#define REG_RAX 0 +#define REG_RCX 1 +#define REG_RDX 2 +#define REG_RBX 3 +#define REG_RSP 4 +#define REG_RBP 5 +#define REG_RSI 6 +#define REG_RDI 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_R13 13 +#define REG_R14 14 +#define REG_R15 15 + +#define REG_XMM0 0 +#define REG_XMM1 1 +#define REG_XMM2 2 +#define REG_XMM3 3 +#define REG_XMM4 4 +#define REG_XMM5 5 +#define REG_XMM6 6 +#define REG_XMM7 7 +#define REG_XMM8 8 +#define REG_XMM9 9 +#define REG_XMM10 10 +#define REG_XMM11 11 +#define REG_XMM12 12 +#define REG_XMM13 13 +#define REG_XMM14 14 +#define REG_XMM15 15 + + +typedef struct _IMAGE_IMPORT_DESCRIPTOR +{ + union { + DWORD Characteristics; + DWORD OriginalFirstThunk; + }; + DWORD TimeDateStamp; + DWORD ForwarderChain; + DWORD Name; + DWORD FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +typedef struct _IMAGE_THUNK_DATA64 +{ + union { + ULONGLONG ForwarderString; + ULONGLONG Function; + ULONGLONG Ordinal; + ULONGLONG AddressOfData; + } u1; +} IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64; + +typedef struct _RUNTIME_FUNCTION +{ + ULONG FunctionStart; + ULONG FunctionEnd; + ULONG UnwindInfo; +} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; + +typedef union _UNWIND_CODE +{ + struct + { + UBYTE CodeOffset; + UBYTE UnwindOp:4; + UBYTE OpInfo:4; + }; + USHORT FrameOffset; +} UNWIND_CODE, *PUNWIND_CODE; + +enum +{ + UNW_FLAG_EHANDLER = 0x01, + UNW_FLAG_UHANDLER = 0x02, + UNW_FLAG_CHAININFO = 0x03, +}; + +typedef struct _UNWIND_INFO +{ + UBYTE Version:3; + UBYTE Flags:5; + UBYTE SizeOfProlog; + UBYTE CountOfCodes; + UBYTE FrameRegister:4; + UBYTE FrameOffset:4; + UNWIND_CODE UnwindCode[1]; +/* union { + OPTIONAL ULONG ExceptionHandler; + OPTIONAL ULONG FunctionEntry; + }; + OPTIONAL ULONG ExceptionData[]; +*/ +} UNWIND_INFO, *PUNWIND_INFO; + +typedef struct _C_SCOPE_TABLE_ENTRY +{ + ULONG Begin; + ULONG End; + ULONG Handler; + ULONG Target; +} C_SCOPE_TABLE_ENTRY, *PC_SCOPE_TABLE_ENTRY; + +typedef struct _C_SCOPE_TABLE +{ + ULONG NumEntries; + C_SCOPE_TABLE_ENTRY Entry[1]; +} C_SCOPE_TABLE, *PC_SCOPE_TABLE; + + +typedef struct +{ + IMAGE_SECTION_HEADER *psh; + char *pName; + void *p; + ULONG idx; +} SECTION; + +typedef struct +{ + char* FilePtr; + size_t cbInFileSize; + size_t cbNewFileSize; + + /* PE data pointers */ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_FILE_HEADER FileHeader; + PIMAGE_OPTIONAL_HEADER64 OptionalHeader; + PIMAGE_SECTION_HEADER SectionHeaders; + PIMAGE_SECTION_HEADER NewSectionHeaders; + ULONG NewSectionHeaderSize; + PIMAGE_BASE_RELOCATION Relocations; + void *Symbols; + char *Strings; + ULONG64 ImageBase; + ULONG HeaderSize; + char *UseSection; + + /* Sections */ + ULONG AllSections; + ULONG UsedSections; + + SECTION eh_frame; + SECTION pdata; + SECTION xdata; + + char *AlignBuf; + + ULONG cFuncs; + ULONG cUWOP; + ULONG cScopes; + +} FILE_INFO, *PFILE_INFO; + + + +#endif // !_RSYM64_H