sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
| 3 | /*--- Basic definitions and helper functions for DWARF3. ---*/ |
| 4 | /*--- d3basics.c ---*/ |
| 5 | /*--------------------------------------------------------------------*/ |
| 6 | |
| 7 | /* |
| 8 | This file is part of Valgrind, a dynamic binary instrumentation |
| 9 | framework. |
| 10 | |
sewardj | 0f157dd | 2013-10-18 14:27:36 +0000 | [diff] [blame] | 11 | Copyright (C) 2008-2013 OpenWorks LLP |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 12 | info@open-works.co.uk |
| 13 | |
| 14 | This program is free software; you can redistribute it and/or |
| 15 | modify it under the terms of the GNU General Public License as |
| 16 | published by the Free Software Foundation; either version 2 of the |
| 17 | License, or (at your option) any later version. |
| 18 | |
| 19 | This program is distributed in the hope that it will be useful, but |
| 20 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 22 | General Public License for more details. |
| 23 | |
| 24 | You should have received a copy of the GNU General Public License |
| 25 | along with this program; if not, write to the Free Software |
| 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 27 | 02111-1307, USA. |
| 28 | |
| 29 | The GNU General Public License is contained in the file COPYING. |
| 30 | |
| 31 | Neither the names of the U.S. Department of Energy nor the |
| 32 | University of California nor the names of its contributors may be |
| 33 | used to endorse or promote products derived from this software |
| 34 | without prior written permission. |
| 35 | */ |
| 36 | |
| 37 | #include "pub_core_basics.h" |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 38 | #include "pub_core_debuginfo.h" |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 39 | #include "pub_core_libcassert.h" |
| 40 | #include "pub_core_libcprint.h" |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 41 | #include "pub_core_libcbase.h" |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 42 | #include "pub_core_options.h" |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 43 | #include "pub_core_xarray.h" |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 44 | |
sewardj | aa3c28a | 2008-03-08 10:44:39 +0000 | [diff] [blame] | 45 | #include "pub_core_vki.h" /* VKI_PROT_READ */ |
| 46 | #include "pub_core_aspacemgr.h" /* VG_(is_valid_for_client) */ |
| 47 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 48 | #include "priv_misc.h" |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 49 | #include "priv_image.h" |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 50 | #include "priv_d3basics.h" /* self */ |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 51 | #include "priv_storage.h" |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 52 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 53 | const HChar* ML_(pp_DW_children) ( DW_children hashch ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 54 | { |
| 55 | switch (hashch) { |
| 56 | case DW_children_no: return "no children"; |
| 57 | case DW_children_yes: return "has children"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 58 | } |
bart | dac4779 | 2012-01-16 09:22:25 +0000 | [diff] [blame] | 59 | return "DW_children_???"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 60 | } |
| 61 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 62 | const HChar* ML_(pp_DW_TAG) ( DW_TAG tag ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 63 | { |
| 64 | switch (tag) { |
| 65 | case DW_TAG_padding: return "DW_TAG_padding"; |
| 66 | case DW_TAG_array_type: return "DW_TAG_array_type"; |
| 67 | case DW_TAG_class_type: return "DW_TAG_class_type"; |
| 68 | case DW_TAG_entry_point: return "DW_TAG_entry_point"; |
| 69 | case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; |
| 70 | case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; |
| 71 | case DW_TAG_imported_declaration: |
| 72 | return "DW_TAG_imported_declaration"; |
| 73 | case DW_TAG_label: return "DW_TAG_label"; |
| 74 | case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; |
| 75 | case DW_TAG_member: return "DW_TAG_member"; |
| 76 | case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; |
| 77 | case DW_TAG_reference_type: return "DW_TAG_reference_type"; |
| 78 | case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; |
| 79 | case DW_TAG_string_type: return "DW_TAG_string_type"; |
| 80 | case DW_TAG_structure_type: return "DW_TAG_structure_type"; |
| 81 | case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; |
| 82 | case DW_TAG_typedef: return "DW_TAG_typedef"; |
| 83 | case DW_TAG_union_type: return "DW_TAG_union_type"; |
| 84 | case DW_TAG_unspecified_parameters: |
| 85 | return "DW_TAG_unspecified_parameters"; |
| 86 | case DW_TAG_variant: return "DW_TAG_variant"; |
| 87 | case DW_TAG_common_block: return "DW_TAG_common_block"; |
| 88 | case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; |
| 89 | case DW_TAG_inheritance: return "DW_TAG_inheritance"; |
| 90 | case DW_TAG_inlined_subroutine: |
| 91 | return "DW_TAG_inlined_subroutine"; |
| 92 | case DW_TAG_module: return "DW_TAG_module"; |
| 93 | case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; |
| 94 | case DW_TAG_set_type: return "DW_TAG_set_type"; |
| 95 | case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; |
| 96 | case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; |
| 97 | case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; |
| 98 | case DW_TAG_base_type: return "DW_TAG_base_type"; |
| 99 | case DW_TAG_catch_block: return "DW_TAG_catch_block"; |
| 100 | case DW_TAG_const_type: return "DW_TAG_const_type"; |
| 101 | case DW_TAG_constant: return "DW_TAG_constant"; |
| 102 | case DW_TAG_enumerator: return "DW_TAG_enumerator"; |
| 103 | case DW_TAG_file_type: return "DW_TAG_file_type"; |
| 104 | case DW_TAG_friend: return "DW_TAG_friend"; |
| 105 | case DW_TAG_namelist: return "DW_TAG_namelist"; |
| 106 | case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; |
| 107 | case DW_TAG_packed_type: return "DW_TAG_packed_type"; |
| 108 | case DW_TAG_subprogram: return "DW_TAG_subprogram"; |
| 109 | case DW_TAG_template_type_param: |
| 110 | return "DW_TAG_template_type_param"; |
| 111 | case DW_TAG_template_value_param: |
| 112 | return "DW_TAG_template_value_param"; |
| 113 | case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; |
| 114 | case DW_TAG_try_block: return "DW_TAG_try_block"; |
| 115 | case DW_TAG_variant_part: return "DW_TAG_variant_part"; |
| 116 | case DW_TAG_variable: return "DW_TAG_variable"; |
| 117 | case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; |
| 118 | /* DWARF 3. */ |
| 119 | case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; |
| 120 | case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; |
| 121 | case DW_TAG_interface_type: return "DW_TAG_interface_type"; |
| 122 | case DW_TAG_namespace: return "DW_TAG_namespace"; |
| 123 | case DW_TAG_imported_module: return "DW_TAG_imported_module"; |
| 124 | case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; |
| 125 | case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; |
| 126 | case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; |
| 127 | case DW_TAG_condition: return "DW_TAG_condition"; |
| 128 | case DW_TAG_shared_type: return "DW_TAG_shared_type"; |
tom | fba428c | 2010-04-28 08:09:30 +0000 | [diff] [blame] | 129 | /* DWARF 4. */ |
| 130 | case DW_TAG_type_unit: return "DW_TAG_type_unit"; |
| 131 | case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type"; |
| 132 | case DW_TAG_template_alias: return "DW_TAG_template_alias"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 133 | /* SGI/MIPS Extensions. */ |
| 134 | case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; |
| 135 | /* HP extensions. See: |
| 136 | ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */ |
| 137 | case DW_TAG_HP_array_descriptor: |
| 138 | return "DW_TAG_HP_array_descriptor"; |
| 139 | /* GNU extensions. */ |
| 140 | case DW_TAG_format_label: return "DW_TAG_format_label"; |
| 141 | case DW_TAG_function_template: return "DW_TAG_function_template"; |
| 142 | case DW_TAG_class_template: return "DW_TAG_class_template"; |
| 143 | case DW_TAG_GNU_BINCL: return "DW_TAG_GNU_BINCL"; |
| 144 | case DW_TAG_GNU_EINCL: return "DW_TAG_GNU_EINCL"; |
| 145 | /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */ |
| 146 | case DW_TAG_upc_shared_type: return "DW_TAG_upc_shared_type"; |
| 147 | case DW_TAG_upc_strict_type: return "DW_TAG_upc_strict_type"; |
| 148 | case DW_TAG_upc_relaxed_type: return "DW_TAG_upc_relaxed_type"; |
| 149 | /* PGI (STMicroelectronics) extensions. No documentation available. */ |
| 150 | case DW_TAG_PGI_kanji_type: return "DW_TAG_PGI_kanji_type"; |
| 151 | case DW_TAG_PGI_interface_block: |
| 152 | return "DW_TAG_PGI_interface_block"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 153 | } |
bart | dac4779 | 2012-01-16 09:22:25 +0000 | [diff] [blame] | 154 | return "DW_TAG_???"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 155 | } |
| 156 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 157 | const HChar* ML_(pp_DW_FORM) ( DW_FORM form ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 158 | { |
| 159 | switch (form) { |
| 160 | case DW_FORM_addr: return "DW_FORM_addr"; |
| 161 | case DW_FORM_block2: return "DW_FORM_block2"; |
| 162 | case DW_FORM_block4: return "DW_FORM_block4"; |
| 163 | case DW_FORM_data2: return "DW_FORM_data2"; |
| 164 | case DW_FORM_data4: return "DW_FORM_data4"; |
| 165 | case DW_FORM_data8: return "DW_FORM_data8"; |
| 166 | case DW_FORM_string: return "DW_FORM_string"; |
| 167 | case DW_FORM_block: return "DW_FORM_block"; |
| 168 | case DW_FORM_block1: return "DW_FORM_block1"; |
| 169 | case DW_FORM_data1: return "DW_FORM_data1"; |
| 170 | case DW_FORM_flag: return "DW_FORM_flag"; |
| 171 | case DW_FORM_sdata: return "DW_FORM_sdata"; |
| 172 | case DW_FORM_strp: return "DW_FORM_strp"; |
| 173 | case DW_FORM_udata: return "DW_FORM_udata"; |
| 174 | case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; |
| 175 | case DW_FORM_ref1: return "DW_FORM_ref1"; |
| 176 | case DW_FORM_ref2: return "DW_FORM_ref2"; |
| 177 | case DW_FORM_ref4: return "DW_FORM_ref4"; |
| 178 | case DW_FORM_ref8: return "DW_FORM_ref8"; |
| 179 | case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; |
| 180 | case DW_FORM_indirect: return "DW_FORM_indirect"; |
tom | fba428c | 2010-04-28 08:09:30 +0000 | [diff] [blame] | 181 | case DW_FORM_sec_offset:return "DW_FORM_sec_offset"; |
| 182 | case DW_FORM_exprloc: return "DW_FORM_exprloc"; |
| 183 | case DW_FORM_flag_present:return "DW_FORM_flag_present"; |
| 184 | case DW_FORM_ref_sig8: return "DW_FORM_ref_sig8"; |
sewardj | f7c9714 | 2012-07-14 09:59:01 +0000 | [diff] [blame] | 185 | case DW_FORM_GNU_ref_alt:return "DW_FORM_GNU_ref_alt"; |
| 186 | case DW_FORM_GNU_strp_alt:return "DW_FORM_GNU_strp_alt"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 187 | } |
bart | dac4779 | 2012-01-16 09:22:25 +0000 | [diff] [blame] | 188 | return "DW_FORM_???"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 189 | } |
| 190 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 191 | const HChar* ML_(pp_DW_AT) ( DW_AT attr ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 192 | { |
| 193 | switch (attr) { |
| 194 | case DW_AT_sibling: return "DW_AT_sibling"; |
| 195 | case DW_AT_location: return "DW_AT_location"; |
| 196 | case DW_AT_name: return "DW_AT_name"; |
| 197 | case DW_AT_ordering: return "DW_AT_ordering"; |
| 198 | case DW_AT_subscr_data: return "DW_AT_subscr_data"; |
| 199 | case DW_AT_byte_size: return "DW_AT_byte_size"; |
| 200 | case DW_AT_bit_offset: return "DW_AT_bit_offset"; |
| 201 | case DW_AT_bit_size: return "DW_AT_bit_size"; |
| 202 | case DW_AT_element_list: return "DW_AT_element_list"; |
| 203 | case DW_AT_stmt_list: return "DW_AT_stmt_list"; |
| 204 | case DW_AT_low_pc: return "DW_AT_low_pc"; |
| 205 | case DW_AT_high_pc: return "DW_AT_high_pc"; |
| 206 | case DW_AT_language: return "DW_AT_language"; |
| 207 | case DW_AT_member: return "DW_AT_member"; |
| 208 | case DW_AT_discr: return "DW_AT_discr"; |
| 209 | case DW_AT_discr_value: return "DW_AT_discr_value"; |
| 210 | case DW_AT_visibility: return "DW_AT_visibility"; |
| 211 | case DW_AT_import: return "DW_AT_import"; |
| 212 | case DW_AT_string_length: return "DW_AT_string_length"; |
| 213 | case DW_AT_common_reference: return "DW_AT_common_reference"; |
| 214 | case DW_AT_comp_dir: return "DW_AT_comp_dir"; |
| 215 | case DW_AT_const_value: return "DW_AT_const_value"; |
| 216 | case DW_AT_containing_type: return "DW_AT_containing_type"; |
| 217 | case DW_AT_default_value: return "DW_AT_default_value"; |
| 218 | case DW_AT_inline: return "DW_AT_inline"; |
| 219 | case DW_AT_is_optional: return "DW_AT_is_optional"; |
| 220 | case DW_AT_lower_bound: return "DW_AT_lower_bound"; |
| 221 | case DW_AT_producer: return "DW_AT_producer"; |
| 222 | case DW_AT_prototyped: return "DW_AT_prototyped"; |
| 223 | case DW_AT_return_addr: return "DW_AT_return_addr"; |
| 224 | case DW_AT_start_scope: return "DW_AT_start_scope"; |
| 225 | case DW_AT_stride_size: return "DW_AT_stride_size"; |
| 226 | case DW_AT_upper_bound: return "DW_AT_upper_bound"; |
| 227 | case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; |
| 228 | case DW_AT_accessibility: return "DW_AT_accessibility"; |
| 229 | case DW_AT_address_class: return "DW_AT_address_class"; |
| 230 | case DW_AT_artificial: return "DW_AT_artificial"; |
| 231 | case DW_AT_base_types: return "DW_AT_base_types"; |
| 232 | case DW_AT_calling_convention: return "DW_AT_calling_convention"; |
| 233 | case DW_AT_count: return "DW_AT_count"; |
| 234 | case DW_AT_data_member_location: return "DW_AT_data_member_location"; |
| 235 | case DW_AT_decl_column: return "DW_AT_decl_column"; |
| 236 | case DW_AT_decl_file: return "DW_AT_decl_file"; |
| 237 | case DW_AT_decl_line: return "DW_AT_decl_line"; |
| 238 | case DW_AT_declaration: return "DW_AT_declaration"; |
| 239 | case DW_AT_discr_list: return "DW_AT_discr_list"; |
| 240 | case DW_AT_encoding: return "DW_AT_encoding"; |
| 241 | case DW_AT_external: return "DW_AT_external"; |
| 242 | case DW_AT_frame_base: return "DW_AT_frame_base"; |
| 243 | case DW_AT_friend: return "DW_AT_friend"; |
| 244 | case DW_AT_identifier_case: return "DW_AT_identifier_case"; |
| 245 | case DW_AT_macro_info: return "DW_AT_macro_info"; |
| 246 | case DW_AT_namelist_items: return "DW_AT_namelist_items"; |
| 247 | case DW_AT_priority: return "DW_AT_priority"; |
| 248 | case DW_AT_segment: return "DW_AT_segment"; |
| 249 | case DW_AT_specification: return "DW_AT_specification"; |
| 250 | case DW_AT_static_link: return "DW_AT_static_link"; |
| 251 | case DW_AT_type: return "DW_AT_type"; |
| 252 | case DW_AT_use_location: return "DW_AT_use_location"; |
| 253 | case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; |
| 254 | case DW_AT_virtuality: return "DW_AT_virtuality"; |
| 255 | case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; |
| 256 | /* DWARF 3 values. */ |
| 257 | case DW_AT_allocated: return "DW_AT_allocated"; |
| 258 | case DW_AT_associated: return "DW_AT_associated"; |
| 259 | case DW_AT_data_location: return "DW_AT_data_location"; |
| 260 | case DW_AT_stride: return "DW_AT_stride"; |
| 261 | case DW_AT_entry_pc: return "DW_AT_entry_pc"; |
| 262 | case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; |
| 263 | case DW_AT_extension: return "DW_AT_extension"; |
| 264 | case DW_AT_ranges: return "DW_AT_ranges"; |
| 265 | case DW_AT_trampoline: return "DW_AT_trampoline"; |
| 266 | case DW_AT_call_column: return "DW_AT_call_column"; |
| 267 | case DW_AT_call_file: return "DW_AT_call_file"; |
| 268 | case DW_AT_call_line: return "DW_AT_call_line"; |
| 269 | case DW_AT_description: return "DW_AT_description"; |
| 270 | case DW_AT_binary_scale: return "DW_AT_binary_scale"; |
| 271 | case DW_AT_decimal_scale: return "DW_AT_decimal_scale"; |
| 272 | case DW_AT_small: return "DW_AT_small"; |
| 273 | case DW_AT_decimal_sign: return "DW_AT_decimal_sign"; |
| 274 | case DW_AT_digit_count: return "DW_AT_digit_count"; |
| 275 | case DW_AT_picture_string: return "DW_AT_picture_string"; |
| 276 | case DW_AT_mutable: return "DW_AT_mutable"; |
| 277 | case DW_AT_threads_scaled: return "DW_AT_threads_scaled"; |
| 278 | case DW_AT_explicit: return "DW_AT_explicit"; |
| 279 | case DW_AT_object_pointer: return "DW_AT_object_pointer"; |
| 280 | case DW_AT_endianity: return "DW_AT_endianity"; |
| 281 | case DW_AT_elemental: return "DW_AT_elemental"; |
| 282 | case DW_AT_pure: return "DW_AT_pure"; |
| 283 | case DW_AT_recursive: return "DW_AT_recursive"; |
tom | fba428c | 2010-04-28 08:09:30 +0000 | [diff] [blame] | 284 | /* DWARF 4 values. */ |
| 285 | case DW_AT_signature: return "DW_AT_signature"; |
| 286 | case DW_AT_main_subprogram: return "DW_AT_main_subprogram"; |
| 287 | case DW_AT_data_bit_offset: return "DW_AT_data_bit_offset"; |
| 288 | case DW_AT_const_expr: return "DW_AT_const_expr"; |
| 289 | case DW_AT_enum_class: return "DW_AT_enum_class"; |
| 290 | case DW_AT_linkage_name: return "DW_AT_linkage_name"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 291 | /* SGI/MIPS extensions. */ |
| 292 | /* case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; */ |
| 293 | /* DW_AT_MIPS_fde == DW_AT_HP_unmodifiable */ |
| 294 | case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; |
| 295 | case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; |
| 296 | case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; |
| 297 | case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; |
| 298 | case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth"; |
| 299 | case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; |
| 300 | case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; |
| 301 | case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; |
| 302 | case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; |
| 303 | case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; |
| 304 | /* HP extensions. */ |
| 305 | case DW_AT_HP_block_index: return "DW_AT_HP_block_index"; |
| 306 | case DW_AT_HP_unmodifiable: return "DW_AT_HP_unmodifiable"; |
| 307 | case DW_AT_HP_actuals_stmt_list: return "DW_AT_HP_actuals_stmt_list"; |
| 308 | case DW_AT_HP_proc_per_section: return "DW_AT_HP_proc_per_section"; |
| 309 | case DW_AT_HP_raw_data_ptr: return "DW_AT_HP_raw_data_ptr"; |
| 310 | case DW_AT_HP_pass_by_reference: return "DW_AT_HP_pass_by_reference"; |
| 311 | case DW_AT_HP_opt_level: return "DW_AT_HP_opt_level"; |
| 312 | case DW_AT_HP_prof_version_id: return "DW_AT_HP_prof_version_id"; |
| 313 | case DW_AT_HP_opt_flags: return "DW_AT_HP_opt_flags"; |
| 314 | case DW_AT_HP_cold_region_low_pc: return "DW_AT_HP_cold_region_low_pc"; |
| 315 | case DW_AT_HP_cold_region_high_pc: return "DW_AT_HP_cold_region_high_pc"; |
| 316 | case DW_AT_HP_all_variables_modifiable: return "DW_AT_HP_all_variables_modifiable"; |
| 317 | case DW_AT_HP_linkage_name: return "DW_AT_HP_linkage_name"; |
| 318 | case DW_AT_HP_prof_flags: return "DW_AT_HP_prof_flags"; |
| 319 | /* GNU extensions. */ |
| 320 | case DW_AT_sf_names: return "DW_AT_sf_names"; |
| 321 | case DW_AT_src_info: return "DW_AT_src_info"; |
| 322 | case DW_AT_mac_info: return "DW_AT_mac_info"; |
| 323 | case DW_AT_src_coords: return "DW_AT_src_coords"; |
| 324 | case DW_AT_body_begin: return "DW_AT_body_begin"; |
| 325 | case DW_AT_body_end: return "DW_AT_body_end"; |
| 326 | case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; |
| 327 | /* VMS extensions. */ |
| 328 | case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; |
| 329 | /* UPC extension. */ |
| 330 | case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled"; |
| 331 | /* PGI (STMicroelectronics) extensions. */ |
| 332 | case DW_AT_PGI_lbase: return "DW_AT_PGI_lbase"; |
| 333 | case DW_AT_PGI_soffset: return "DW_AT_PGI_soffset"; |
| 334 | case DW_AT_PGI_lstride: return "DW_AT_PGI_lstride"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 335 | } |
bart | dac4779 | 2012-01-16 09:22:25 +0000 | [diff] [blame] | 336 | return "DW_AT_???"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | |
| 340 | /* ------ To do with evaluation of Dwarf expressions ------ */ |
| 341 | |
| 342 | /* FIXME: duplicated in readdwarf.c */ |
| 343 | static |
| 344 | ULong read_leb128 ( UChar* data, Int* length_return, Int sign ) |
| 345 | { |
| 346 | ULong result = 0; |
| 347 | UInt num_read = 0; |
| 348 | Int shift = 0; |
| 349 | UChar byte; |
| 350 | |
| 351 | vg_assert(sign == 0 || sign == 1); |
| 352 | |
| 353 | do |
| 354 | { |
| 355 | byte = * data ++; |
| 356 | num_read ++; |
| 357 | |
| 358 | result |= ((ULong)(byte & 0x7f)) << shift; |
| 359 | |
| 360 | shift += 7; |
| 361 | |
| 362 | } |
| 363 | while (byte & 0x80); |
| 364 | |
| 365 | if (length_return != NULL) |
| 366 | * length_return = num_read; |
| 367 | |
| 368 | if (sign && (shift < 64) && (byte & 0x40)) |
| 369 | result |= -(1ULL << shift); |
| 370 | |
| 371 | return result; |
| 372 | } |
| 373 | |
| 374 | /* Small helper functions easier to use |
| 375 | * value is returned and the given pointer is |
| 376 | * moved past end of leb128 data */ |
| 377 | /* FIXME: duplicated in readdwarf.c */ |
| 378 | static ULong read_leb128U( UChar **data ) |
| 379 | { |
| 380 | Int len; |
| 381 | ULong val = read_leb128( *data, &len, 0 ); |
| 382 | *data += len; |
| 383 | return val; |
| 384 | } |
| 385 | |
| 386 | /* Same for signed data */ |
| 387 | /* FIXME: duplicated in readdwarf.c */ |
| 388 | static Long read_leb128S( UChar **data ) |
| 389 | { |
| 390 | Int len; |
| 391 | ULong val = read_leb128( *data, &len, 1 ); |
| 392 | *data += len; |
| 393 | return (Long)val; |
| 394 | } |
| 395 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 396 | /* FIXME: duplicates logic in readdwarf.c: copy_convert_CfiExpr_tree |
| 397 | and {FP,SP}_REG decls */ |
| 398 | static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs ) |
| 399 | { |
| 400 | vg_assert(regs); |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 401 | # if defined(VGP_x86_linux) || defined(VGP_x86_darwin) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 402 | if (regno == 5/*EBP*/) { *a = regs->fp; return True; } |
| 403 | if (regno == 4/*ESP*/) { *a = regs->sp; return True; } |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 404 | # elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) |
njn | de706e3 | 2009-05-20 02:27:00 +0000 | [diff] [blame] | 405 | if (regno == 6/*RBP*/) { *a = regs->fp; return True; } |
| 406 | if (regno == 7/*RSP*/) { *a = regs->sp; return True; } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 407 | # elif defined(VGP_ppc32_linux) |
| 408 | if (regno == 1/*SP*/) { *a = regs->sp; return True; } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 409 | # elif defined(VGP_ppc64_linux) |
| 410 | if (regno == 1/*SP*/) { *a = regs->sp; return True; } |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 411 | # elif defined(VGP_arm_linux) |
| 412 | if (regno == 13) { *a = regs->sp; return True; } |
| 413 | if (regno == 11) { *a = regs->fp; return True; } |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 414 | # elif defined(VGP_s390x_linux) |
| 415 | if (regno == 15) { *a = regs->sp; return True; } |
| 416 | if (regno == 11) { *a = regs->fp; return True; } |
sewardj | 5db1540 | 2012-06-07 09:13:21 +0000 | [diff] [blame] | 417 | # elif defined(VGP_mips32_linux) |
| 418 | if (regno == 29) { *a = regs->sp; return True; } |
| 419 | if (regno == 30) { *a = regs->fp; return True; } |
petarj | 4df0bfc | 2013-02-27 23:17:33 +0000 | [diff] [blame] | 420 | # elif defined(VGP_mips64_linux) |
| 421 | if (regno == 29) { *a = regs->sp; return True; } |
| 422 | if (regno == 30) { *a = regs->fp; return True; } |
sewardj | f0c1250 | 2014-01-12 12:54:00 +0000 | [diff] [blame] | 423 | # elif defined(VGP_arm64_linux) |
| 424 | I_die_here; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 425 | # else |
| 426 | # error "Unknown platform" |
| 427 | # endif |
| 428 | return False; |
| 429 | } |
| 430 | |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 431 | /* Convert a stated address to an actual address */ |
| 432 | static Bool bias_address( Addr* a, const DebugInfo* di ) |
| 433 | { |
| 434 | if (di->text_present |
| 435 | && di->text_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 436 | && *a >= di->text_debug_svma && *a < di->text_debug_svma + di->text_size) { |
| 437 | *a += di->text_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 438 | } |
| 439 | else if (di->data_present |
| 440 | && di->data_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 441 | && *a >= di->data_debug_svma && *a < di->data_debug_svma + di->data_size) { |
| 442 | *a += di->data_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 443 | } |
| 444 | else if (di->sdata_present |
| 445 | && di->sdata_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 446 | && *a >= di->sdata_debug_svma && *a < di->sdata_debug_svma + di->sdata_size) { |
| 447 | *a += di->sdata_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 448 | } |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 449 | else if (di->rodata_present |
| 450 | && di->rodata_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 451 | && *a >= di->rodata_debug_svma && *a < di->rodata_debug_svma + di->rodata_size) { |
| 452 | *a += di->rodata_debug_bias; |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 453 | } |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 454 | else if (di->bss_present |
| 455 | && di->bss_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 456 | && *a >= di->bss_debug_svma && *a < di->bss_debug_svma + di->bss_size) { |
| 457 | *a += di->bss_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 458 | } |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 459 | else if (di->sbss_present |
| 460 | && di->sbss_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 461 | && *a >= di->sbss_debug_svma && *a < di->sbss_debug_svma + di->sbss_size) { |
| 462 | *a += di->sbss_debug_bias; |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 463 | } |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 464 | else { |
| 465 | return False; |
| 466 | } |
| 467 | |
| 468 | return True; |
| 469 | } |
| 470 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 471 | |
| 472 | /* Evaluate a standard DWARF3 expression. See detailed description in |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 473 | priv_d3basics.h. Doesn't handle DW_OP_piece/DW_OP_bit_piece yet. */ |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 474 | GXResult ML_(evaluate_Dwarf3_Expr) ( UChar* expr, UWord exprszB, |
| 475 | GExpr* fbGX, RegSummary* regs, |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 476 | const DebugInfo* di, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 477 | Bool push_initial_zero ) |
| 478 | { |
| 479 | # define N_EXPR_STACK 20 |
| 480 | |
| 481 | # define FAIL(_str) \ |
| 482 | do { \ |
| 483 | res.kind = GXR_Failure; \ |
| 484 | res.word = (UWord)(_str); \ |
| 485 | return res; \ |
| 486 | } while (0) |
| 487 | |
| 488 | # define PUSH(_arg) \ |
| 489 | do { \ |
| 490 | vg_assert(sp >= -1 && sp < N_EXPR_STACK); \ |
| 491 | if (sp == N_EXPR_STACK-1) \ |
| 492 | FAIL("evaluate_Dwarf3_Expr: stack overflow(1)"); \ |
| 493 | sp++; \ |
| 494 | stack[sp] = (_arg); \ |
| 495 | } while (0) |
| 496 | |
| 497 | # define POP(_lval) \ |
| 498 | do { \ |
| 499 | vg_assert(sp >= -1 && sp < N_EXPR_STACK); \ |
| 500 | if (sp == -1) \ |
| 501 | FAIL("evaluate_Dwarf3_Expr: stack underflow(1)"); \ |
| 502 | _lval = stack[sp]; \ |
| 503 | sp--; \ |
| 504 | } while (0) |
| 505 | |
| 506 | UChar opcode; |
| 507 | UChar* limit; |
| 508 | Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */ |
| 509 | Addr stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */ |
| 510 | GXResult fbval, res; |
| 511 | Addr a1; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 512 | Word sw1, sw2; |
| 513 | UWord uw1, uw2; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 514 | Bool ok; |
| 515 | |
| 516 | sp = -1; |
| 517 | vg_assert(expr); |
| 518 | vg_assert(exprszB >= 0); |
| 519 | limit = expr + exprszB; |
| 520 | |
| 521 | /* Deal with the case where the entire expression is a single |
| 522 | Register Name Operation (D3 spec sec 2.6.1). Then the |
| 523 | denotation of the expression as a whole is a register name. */ |
| 524 | if (exprszB == 1 |
| 525 | && expr[0] >= DW_OP_reg0 && expr[0] <= DW_OP_reg31) { |
| 526 | res.kind = GXR_RegNo; |
| 527 | res.word = (UWord)(expr[0] - DW_OP_reg0); |
| 528 | return res; |
| 529 | } |
| 530 | if (exprszB > 1 |
| 531 | && expr[0] == DW_OP_regx) { |
| 532 | /* JRS: 2008Feb20: I believe the following is correct, but would |
| 533 | like to see a test case show up before enabling it. */ |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 534 | expr++; |
| 535 | res.kind = GXR_RegNo; |
| 536 | res.word = (UWord)read_leb128U( &expr ); |
| 537 | if (expr != limit) |
| 538 | FAIL("evaluate_Dwarf3_Expr: DW_OP_regx*: invalid expr size"); |
| 539 | else |
| 540 | return res; |
| 541 | /*NOTREACHED*/ |
| 542 | } |
| 543 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 544 | /* Evidently this expression denotes a value, not a register name. |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 545 | So evaluate it accordingly. */ |
| 546 | |
| 547 | if (push_initial_zero) |
| 548 | PUSH(0); |
| 549 | |
| 550 | while (True) { |
| 551 | |
| 552 | vg_assert(sp >= -1 && sp < N_EXPR_STACK); |
| 553 | |
| 554 | if (expr > limit) |
| 555 | /* overrun - something's wrong */ |
| 556 | FAIL("evaluate_Dwarf3_Expr: ran off end of expr"); |
| 557 | |
| 558 | if (expr == limit) { |
| 559 | /* end of expr - return expr on the top of stack. */ |
| 560 | if (sp == -1) |
| 561 | /* stack empty. Bad. */ |
| 562 | FAIL("evaluate_Dwarf3_Expr: stack empty at end of expr"); |
| 563 | else |
| 564 | break; |
| 565 | } |
| 566 | |
| 567 | opcode = *expr++; |
| 568 | switch (opcode) { |
| 569 | case DW_OP_addr: |
| 570 | /* Presumably what is given in the Dwarf3 is a SVMA (how |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 571 | could it be otherwise?) So we add the appropriate bias |
| 572 | on before pushing the result. */ |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 573 | a1 = ML_(read_Addr)(expr); |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 574 | if (bias_address(&a1, di)) { |
| 575 | PUSH( a1 ); |
| 576 | expr += sizeof(Addr); |
| 577 | } |
| 578 | else { |
| 579 | FAIL("evaluate_Dwarf3_Expr: DW_OP_addr with address " |
| 580 | "in unknown section"); |
| 581 | } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 582 | break; |
| 583 | case DW_OP_fbreg: |
| 584 | if (!fbGX) |
| 585 | FAIL("evaluate_Dwarf3_Expr: DW_OP_fbreg with " |
| 586 | "no expr for fbreg present"); |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 587 | fbval = ML_(evaluate_GX)(fbGX, NULL, regs, di); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 588 | /* Convert fbval into something we can use. If we got a |
| 589 | Value, no problem. However, as per D3 spec sec 3.3.5 |
| 590 | (Low Level Information) sec 2, we could also get a |
| 591 | RegNo, and that is taken to mean the value in the |
| 592 | indicated register. So we have to manually |
| 593 | "dereference" it. */ |
| 594 | a1 = 0; |
| 595 | switch (fbval.kind) { |
| 596 | case GXR_Failure: |
| 597 | return fbval; /* propagate failure */ |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 598 | case GXR_Addr: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 599 | a1 = fbval.word; break; /* use as-is */ |
| 600 | case GXR_RegNo: |
| 601 | ok = get_Dwarf_Reg( &a1, fbval.word, regs ); |
| 602 | if (!ok) return fbval; /* propagate failure */ |
| 603 | break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 604 | case GXR_Value: |
| 605 | FAIL("evaluate_Dwarf3_Expr: DW_OP_{implicit,stack}_value " |
| 606 | "in DW_AT_frame_base"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 607 | default: |
| 608 | vg_assert(0); |
| 609 | } |
| 610 | sw1 = (Word)read_leb128S( &expr ); |
| 611 | PUSH( a1 + sw1 ); |
| 612 | break; |
| 613 | /* DW_OP_breg* denotes 'contents of specified register, plus |
| 614 | constant offset'. So provided we know what the register's |
| 615 | value is, we can evaluate this. Contrast DW_OP_reg*, |
| 616 | which indicates that denoted location is in a register |
| 617 | itself. If DW_OP_reg* shows up here the expression is |
| 618 | malformed, since we are evaluating for value now, and |
| 619 | DW_OP_reg* denotes a register location, not a value. See |
| 620 | D3 Spec sec 2.6.1 ("Register Name Operations") for |
| 621 | details. */ |
| 622 | case DW_OP_breg0 ... DW_OP_breg31: |
| 623 | if (!regs) |
| 624 | FAIL("evaluate_Dwarf3_Expr: DW_OP_breg* but no reg info"); |
| 625 | a1 = 0; |
| 626 | if (!get_Dwarf_Reg( &a1, opcode - DW_OP_breg0, regs )) |
| 627 | FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_breg*"); |
| 628 | sw1 = (Word)read_leb128S( &expr ); |
| 629 | a1 += sw1; |
| 630 | PUSH( a1 ); |
| 631 | break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 632 | case DW_OP_bregx: |
| 633 | if (!regs) |
| 634 | FAIL("evaluate_Dwarf3_Expr: DW_OP_bregx but no reg info"); |
| 635 | a1 = 0; |
| 636 | uw1 = (UWord)read_leb128U( &expr ); |
| 637 | if (!get_Dwarf_Reg( &a1, uw1, regs )) |
| 638 | FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_bregx reg value"); |
| 639 | sw1 = (Word)read_leb128S( &expr ); |
| 640 | a1 += sw1; |
| 641 | PUSH( a1 ); |
| 642 | break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 643 | /* As per comment on DW_OP_breg*, the following denote that |
| 644 | the value in question is in a register, not in memory. So |
| 645 | we simply return failure. (iow, the expression is |
| 646 | malformed). */ |
| 647 | case DW_OP_reg0 ... DW_OP_reg31: |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 648 | case DW_OP_regx: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 649 | FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* " |
| 650 | "whilst evaluating for a value"); |
| 651 | break; |
| 652 | case DW_OP_plus_uconst: |
| 653 | POP(uw1); |
| 654 | uw1 += (UWord)read_leb128U( &expr ); |
| 655 | PUSH(uw1); |
| 656 | break; |
| 657 | case DW_OP_GNU_push_tls_address: |
| 658 | /* GDB contains the following cryptic comment: */ |
| 659 | /* Variable is at a constant offset in the thread-local |
| 660 | storage block into the objfile for the current thread and |
| 661 | the dynamic linker module containing this expression. Here |
| 662 | we return returns the offset from that base. The top of the |
| 663 | stack has the offset from the beginning of the thread |
| 664 | control block at which the variable is located. Nothing |
| 665 | should follow this operator, so the top of stack would be |
| 666 | returned. */ |
| 667 | /* But no spec resulting from Googling. Punt for now. */ |
| 668 | FAIL("warning: evaluate_Dwarf3_Expr: unhandled " |
| 669 | "DW_OP_GNU_push_tls_address"); |
| 670 | /*NOTREACHED*/ |
sewardj | aa3c28a | 2008-03-08 10:44:39 +0000 | [diff] [blame] | 671 | case DW_OP_deref: |
| 672 | POP(uw1); |
| 673 | if (VG_(am_is_valid_for_client)( (Addr)uw1, sizeof(Addr), |
| 674 | VKI_PROT_READ )) { |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 675 | uw1 = ML_(read_UWord)((void *)uw1); |
sewardj | aa3c28a | 2008-03-08 10:44:39 +0000 | [diff] [blame] | 676 | PUSH(uw1); |
| 677 | } else { |
| 678 | FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref: " |
| 679 | "address not valid for client"); |
| 680 | } |
| 681 | break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 682 | case DW_OP_deref_size: |
| 683 | POP(uw1); |
| 684 | uw2 = *expr++; |
| 685 | if (VG_(am_is_valid_for_client)( (Addr)uw1, uw2, |
| 686 | VKI_PROT_READ )) { |
| 687 | switch (uw2) { |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 688 | case 1: uw1 = ML_(read_UChar)((void*)uw1); break; |
| 689 | case 2: uw1 = ML_(read_UShort)((void*)uw1); break; |
| 690 | case 4: uw1 = ML_(read_UInt)((void*)uw1); break; |
| 691 | case 8: uw1 = ML_(read_ULong)((void*)uw1); break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 692 | default: |
| 693 | FAIL("warning: evaluate_Dwarf3_Expr: unhandled " |
| 694 | "DW_OP_deref_size size"); |
| 695 | } |
| 696 | PUSH(uw1); |
| 697 | } else { |
| 698 | FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref_size: " |
| 699 | "address not valid for client"); |
| 700 | } |
| 701 | break; |
| 702 | case DW_OP_lit0 ... DW_OP_lit31: |
| 703 | PUSH(opcode - DW_OP_lit0); |
| 704 | break; |
| 705 | case DW_OP_const1u: |
| 706 | uw1 = *expr++; |
| 707 | PUSH(uw1); |
| 708 | break; |
| 709 | case DW_OP_const2u: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 710 | uw1 = ML_(read_UShort)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 711 | expr += 2; |
| 712 | PUSH(uw1); |
| 713 | break; |
| 714 | case DW_OP_const4u: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 715 | uw1 = ML_(read_UInt)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 716 | expr += 4; |
| 717 | PUSH(uw1); |
| 718 | break; |
| 719 | case DW_OP_const8u: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 720 | uw1 = ML_(read_ULong)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 721 | expr += 8; |
| 722 | PUSH(uw1); |
| 723 | break; |
| 724 | case DW_OP_constu: |
| 725 | uw1 = read_leb128U( &expr ); |
| 726 | PUSH(uw1); |
| 727 | break; |
| 728 | case DW_OP_const1s: |
| 729 | uw1 = *(Char *)expr; |
| 730 | expr++; |
| 731 | PUSH(uw1); |
| 732 | break; |
| 733 | case DW_OP_const2s: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 734 | uw1 = ML_(read_Short)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 735 | expr += 2; |
| 736 | PUSH(uw1); |
| 737 | break; |
| 738 | case DW_OP_const4s: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 739 | uw1 = ML_(read_Int)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 740 | expr += 4; |
| 741 | PUSH(uw1); |
| 742 | break; |
| 743 | case DW_OP_const8s: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 744 | uw1 = ML_(read_Long)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 745 | expr += 8; |
| 746 | PUSH(uw1); |
| 747 | break; |
| 748 | case DW_OP_consts: |
| 749 | uw1 = read_leb128S( &expr ); |
| 750 | PUSH(uw1); |
| 751 | break; |
| 752 | case DW_OP_dup: |
| 753 | POP(uw1); |
| 754 | PUSH(uw1); |
| 755 | PUSH(uw1); |
| 756 | break; |
| 757 | case DW_OP_drop: |
| 758 | POP(uw1); |
| 759 | break; |
| 760 | case DW_OP_over: |
| 761 | uw1 = 1; |
| 762 | goto do_pick; |
| 763 | case DW_OP_pick: |
| 764 | uw1 = *expr++; |
| 765 | do_pick: |
| 766 | if (sp < (Int)uw1) |
| 767 | FAIL("evaluate_Dwarf3_Expr: stack underflow"); |
| 768 | uw1 = stack[sp - uw1]; |
| 769 | PUSH(uw1); |
| 770 | break; |
| 771 | case DW_OP_swap: |
| 772 | if (sp < 1) |
| 773 | FAIL("evaluate_Dwarf3_Expr: stack underflow"); |
| 774 | uw1 = stack[sp]; |
| 775 | stack[sp] = stack[sp - 1]; |
| 776 | stack[sp - 1] = uw1; |
| 777 | break; |
| 778 | case DW_OP_rot: |
| 779 | if (sp < 2) |
| 780 | FAIL("evaluate_Dwarf3_Expr: stack underflow"); |
| 781 | uw1 = stack[sp]; |
| 782 | stack[sp] = stack[sp - 1]; |
| 783 | stack[sp - 1] = stack[sp - 2]; |
| 784 | stack[sp - 2] = uw1; |
| 785 | break; |
| 786 | case DW_OP_abs: |
| 787 | POP(sw1); |
| 788 | if (sw1 < 0) |
| 789 | sw1 = -sw1; |
| 790 | PUSH(sw1); |
| 791 | break; |
| 792 | case DW_OP_div: |
| 793 | POP(sw2); |
| 794 | if (sw2 == 0) |
| 795 | FAIL("evaluate_Dwarf3_Expr: division by zero"); |
| 796 | POP(sw1); |
| 797 | sw1 /= sw2; |
| 798 | PUSH(sw1); |
| 799 | break; |
| 800 | case DW_OP_mod: |
tom | b9c17d2 | 2010-01-21 10:19:46 +0000 | [diff] [blame] | 801 | POP(uw2); |
| 802 | if (uw2 == 0) |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 803 | FAIL("evaluate_Dwarf3_Expr: division by zero"); |
tom | b9c17d2 | 2010-01-21 10:19:46 +0000 | [diff] [blame] | 804 | POP(uw1); |
| 805 | uw1 %= uw2; |
| 806 | PUSH(uw1); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 807 | break; |
| 808 | #define BINARY(name, op, s) \ |
| 809 | case DW_OP_##name: \ |
| 810 | POP(s##w2); \ |
| 811 | POP(s##w1); \ |
| 812 | s##w1 = s##w1 op s##w2; \ |
| 813 | PUSH(s##w1); \ |
| 814 | break |
| 815 | #define UNARY(name, op, s) \ |
| 816 | case DW_OP_##name: \ |
| 817 | POP(s##w1); \ |
| 818 | s##w1 = op s##w1; \ |
| 819 | PUSH(s##w1); \ |
| 820 | break |
| 821 | BINARY (and, &, u); |
| 822 | BINARY (minus, -, u); |
| 823 | BINARY (mul, *, u); |
| 824 | UNARY (neg, -, u); |
| 825 | UNARY (not, ~, u); |
| 826 | BINARY (or, |, u); |
| 827 | BINARY (plus, +, u); |
| 828 | BINARY (shl, <<, u); |
| 829 | BINARY (shr, >>, u); |
| 830 | BINARY (shra, >>, s); |
| 831 | BINARY (xor, ^, u); |
| 832 | BINARY (le, <=, s); |
| 833 | BINARY (lt, <, s); |
| 834 | BINARY (ge, >=, s); |
| 835 | BINARY (gt, >, s); |
| 836 | BINARY (ne, !=, u); |
| 837 | BINARY (eq, ==, u); |
| 838 | #undef UNARY |
| 839 | #undef BINARY |
| 840 | case DW_OP_skip: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 841 | sw1 = ML_(read_Short)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 842 | expr += 2; |
| 843 | if (expr + sw1 < limit - exprszB) |
| 844 | FAIL("evaluate_Dwarf3_Expr: DW_OP_skip before start of expr"); |
| 845 | if (expr + sw1 >= limit) |
| 846 | FAIL("evaluate_Dwarf3_Expr: DW_OP_skip after end of expr"); |
| 847 | expr += sw1; |
| 848 | break; |
| 849 | case DW_OP_bra: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 850 | sw1 = ML_(read_Short)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 851 | expr += 2; |
| 852 | if (expr + sw1 < limit - exprszB) |
| 853 | FAIL("evaluate_Dwarf3_Expr: DW_OP_bra before start of expr"); |
| 854 | if (expr + sw1 >= limit) |
| 855 | FAIL("evaluate_Dwarf3_Expr: DW_OP_bra after end of expr"); |
| 856 | POP(uw1); |
| 857 | if (uw1) |
| 858 | expr += sw1; |
| 859 | break; |
| 860 | case DW_OP_nop: |
| 861 | break; |
| 862 | case DW_OP_call_frame_cfa: |
| 863 | if (!regs) |
sewardj | 3026f71 | 2010-01-01 18:46:41 +0000 | [diff] [blame] | 864 | FAIL("evaluate_Dwarf3_Expr: " |
| 865 | "DW_OP_call_frame_cfa but no reg info"); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 866 | #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) |
sewardj | 3026f71 | 2010-01-01 18:46:41 +0000 | [diff] [blame] | 867 | /* Valgrind on ppc32/ppc64 currently doesn't use unwind info. */ |
sewardj | 50f5cea | 2011-10-20 10:41:37 +0000 | [diff] [blame] | 868 | uw1 = ML_(read_Addr)((UChar*)regs->sp); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 869 | #else |
| 870 | uw1 = ML_(get_CFA)(regs->ip, regs->sp, regs->fp, 0, ~(UWord) 0); |
| 871 | #endif |
sewardj | 3026f71 | 2010-01-01 18:46:41 +0000 | [diff] [blame] | 872 | /* we expect this to fail on arm-linux, since ML_(get_CFA) |
| 873 | always returns zero at present. */ |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 874 | if (!uw1) |
| 875 | FAIL("evaluate_Dwarf3_Expr: Could not resolve " |
| 876 | "DW_OP_call_frame_cfa"); |
| 877 | PUSH(uw1); |
| 878 | break; |
| 879 | case DW_OP_implicit_value: |
| 880 | sw1 = (Word)read_leb128S( &expr ); |
| 881 | uw1 = 0; |
| 882 | switch (sw1) { |
| 883 | case 1: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 884 | uw1 = ML_(read_UChar)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 885 | expr += 1; |
| 886 | break; |
| 887 | case 2: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 888 | uw1 = ML_(read_UShort)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 889 | expr += 2; |
| 890 | break; |
| 891 | case 4: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 892 | uw1 = ML_(read_UInt)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 893 | expr += 4; |
| 894 | break; |
| 895 | case 8: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 896 | uw1 = ML_(read_ULong)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 897 | expr += 8; |
| 898 | break; |
| 899 | default: |
| 900 | FAIL("evaluate_Dwarf3_Expr: Unhandled " |
| 901 | "DW_OP_implicit_value size"); |
| 902 | } |
| 903 | if (expr != limit) |
| 904 | FAIL("evaluate_Dwarf3_Expr: DW_OP_implicit_value " |
| 905 | "does not terminate expression"); |
| 906 | res.word = uw1; |
| 907 | res.kind = GXR_Value; |
| 908 | return res; |
| 909 | case DW_OP_stack_value: |
| 910 | POP (uw1); |
| 911 | res.word = uw1; |
| 912 | res.kind = GXR_Value; |
| 913 | if (expr != limit) |
| 914 | FAIL("evaluate_Dwarf3_Expr: DW_OP_stack_value " |
| 915 | "does not terminate expression"); |
| 916 | break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 917 | default: |
| 918 | if (!VG_(clo_xml)) |
| 919 | VG_(message)(Vg_DebugMsg, |
| 920 | "warning: evaluate_Dwarf3_Expr: unhandled " |
sewardj | 738856f | 2009-07-15 14:48:32 +0000 | [diff] [blame] | 921 | "DW_OP_ 0x%x\n", (Int)opcode); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 922 | FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_"); |
| 923 | /*NOTREACHED*/ |
| 924 | } |
| 925 | |
| 926 | } |
| 927 | |
| 928 | vg_assert(sp >= 0 && sp < N_EXPR_STACK); |
| 929 | res.word = stack[sp]; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 930 | res.kind = GXR_Addr; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 931 | return res; |
| 932 | |
| 933 | # undef POP |
| 934 | # undef PUSH |
| 935 | # undef FAIL |
| 936 | # undef N_EXPR_STACK |
| 937 | } |
| 938 | |
| 939 | |
| 940 | /* Evaluate a so-called Guarded (DWARF3) expression. See detailed |
| 941 | description in priv_d3basics.h. */ |
| 942 | GXResult ML_(evaluate_GX)( GExpr* gx, GExpr* fbGX, |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 943 | RegSummary* regs, const DebugInfo* di ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 944 | { |
| 945 | GXResult res; |
| 946 | Addr aMin, aMax; |
| 947 | UChar uc; |
| 948 | UShort nbytes; |
| 949 | UWord nGuards = 0; |
| 950 | UChar* p = &gx->payload[0]; |
| 951 | uc = *p++; /*biasMe*/ |
| 952 | vg_assert(uc == 0 || uc == 1); |
| 953 | /* in fact it's senseless to evaluate if the guards need biasing. |
| 954 | So don't. */ |
| 955 | vg_assert(uc == 0); |
| 956 | while (True) { |
| 957 | uc = *p++; |
| 958 | if (uc == 1) { /*isEnd*/ |
| 959 | /* didn't find any matching range. */ |
| 960 | res.kind = GXR_Failure; |
| 961 | res.word = (UWord)"no matching range"; |
| 962 | return res; |
| 963 | } |
| 964 | vg_assert(uc == 0); |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 965 | aMin = ML_(read_Addr)(p); p += sizeof(Addr); |
| 966 | aMax = ML_(read_Addr)(p); p += sizeof(Addr); |
| 967 | nbytes = ML_(read_UShort)(p); p += sizeof(UShort); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 968 | nGuards++; |
bart | a0b6b2c | 2008-07-07 06:49:24 +0000 | [diff] [blame] | 969 | if (0) VG_(printf)(" guard %d: %#lx %#lx\n", |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 970 | (Int)nGuards, aMin,aMax); |
| 971 | if (regs == NULL) { |
| 972 | vg_assert(aMin == (Addr)0); |
| 973 | vg_assert(aMax == ~(Addr)0); |
| 974 | /* Assert this is the first guard. */ |
| 975 | vg_assert(nGuards == 1); |
| 976 | res = ML_(evaluate_Dwarf3_Expr)( |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 977 | p, (UWord)nbytes, fbGX, regs, di, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 978 | False/*push_initial_zero*/ ); |
| 979 | /* Now check there are no more guards. */ |
| 980 | p += (UWord)nbytes; |
| 981 | vg_assert(*p == 1); /*isEnd*/ |
| 982 | return res; |
| 983 | } else { |
| 984 | if (aMin <= regs->ip && regs->ip <= aMax) { |
| 985 | /* found a matching range. Evaluate the expression. */ |
| 986 | return ML_(evaluate_Dwarf3_Expr)( |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 987 | p, (UWord)nbytes, fbGX, regs, di, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 988 | False/*push_initial_zero*/ ); |
| 989 | } |
| 990 | } |
| 991 | /* else keep searching */ |
| 992 | p += (UWord)nbytes; |
| 993 | } |
| 994 | } |
| 995 | |
| 996 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 997 | /* Evaluate a very simple Guarded (DWARF3) expression. The expression |
| 998 | is expected to denote a constant, with no reference to any |
| 999 | registers nor to any frame base expression. The expression is |
| 1000 | expected to have at least one guard. If there is more than one |
| 1001 | guard, all the sub-expressions are evaluated and compared. The |
| 1002 | address ranges on the guards are ignored. GXR_Failure is returned |
| 1003 | in the following circumstances: |
| 1004 | * no guards |
| 1005 | * any of the subexpressions require a frame base expression |
| 1006 | * any of the subexpressions denote a register location |
| 1007 | * any of the subexpressions do not produce a manifest constant |
| 1008 | * there's more than one subexpression, all of which successfully |
| 1009 | evaluate to a constant, but they don't all produce the same constant. |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1010 | JRS 23Jan09: the special-casing in this function is a nasty kludge. |
| 1011 | Really it ought to be pulled out and turned into a general |
| 1012 | constant- expression evaluator. |
| 1013 | */ |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 1014 | GXResult ML_(evaluate_trivial_GX)( GExpr* gx, const DebugInfo* di ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1015 | { |
| 1016 | GXResult res; |
| 1017 | Addr aMin, aMax; |
| 1018 | UChar uc; |
| 1019 | UShort nbytes; |
| 1020 | Word i, nGuards; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1021 | MaybeULong *mul, *mul2; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1022 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 1023 | const HChar* badness = NULL; |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1024 | UChar* p = &gx->payload[0]; /* must remain unsigned */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1025 | XArray* results = VG_(newXA)( ML_(dinfo_zalloc), "di.d3basics.etG.1", |
| 1026 | ML_(dinfo_free), |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1027 | sizeof(MaybeULong) ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1028 | |
| 1029 | uc = *p++; /*biasMe*/ |
| 1030 | vg_assert(uc == 0 || uc == 1); |
| 1031 | /* in fact it's senseless to evaluate if the guards need biasing. |
| 1032 | So don't. */ |
| 1033 | vg_assert(uc == 0); |
| 1034 | |
| 1035 | nGuards = 0; |
| 1036 | while (True) { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1037 | MaybeULong thisResult; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1038 | uc = *p++; |
| 1039 | if (uc == 1) /*isEnd*/ |
| 1040 | break; |
| 1041 | vg_assert(uc == 0); |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1042 | aMin = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1043 | aMax = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1044 | nbytes = ML_(read_UShort)(p); p += sizeof(UShort); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1045 | nGuards++; |
| 1046 | if (0) VG_(printf)(" guard %ld: %#lx %#lx\n", |
| 1047 | nGuards, aMin,aMax); |
| 1048 | |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1049 | thisResult.b = False; |
| 1050 | thisResult.ul = 0; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1051 | |
| 1052 | /* Peer at this particular subexpression, to see if it's |
| 1053 | obviously a constant. */ |
| 1054 | if (nbytes == 1 + sizeof(Addr) && *p == DW_OP_addr) { |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1055 | /* DW_OP_addr a */ |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1056 | Addr a = ML_(read_Addr)((p+1)); |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 1057 | if (bias_address(&a, di)) { |
| 1058 | thisResult.b = True; |
| 1059 | thisResult.ul = (ULong)a; |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1060 | } else { |
| 1061 | if (!badness) |
| 1062 | badness = "trivial GExpr denotes constant address " |
| 1063 | "in unknown section (1)"; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 1064 | } |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1065 | } |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1066 | else |
| 1067 | if (nbytes == 1 + sizeof(Addr) + 1 + 1 |
| 1068 | /* 11 byte block: 3 c0 b6 2b 0 0 0 0 0 23 4 |
| 1069 | (DW_OP_addr: 2bb6c0; DW_OP_plus_uconst: 4) |
| 1070 | This is really a nasty kludge - only matches if the |
| 1071 | trailing ULEB denotes a number in the range 0 .. 127 |
| 1072 | inclusive. */ |
| 1073 | && p[0] == DW_OP_addr |
| 1074 | && p[1 + sizeof(Addr)] == DW_OP_plus_uconst |
| 1075 | && p[1 + sizeof(Addr) + 1] < 0x80 /*1-byte ULEB*/) { |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1076 | Addr a = ML_(read_Addr)(&p[1]); |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1077 | if (bias_address(&a, di)) { |
| 1078 | thisResult.b = True; |
| 1079 | thisResult.ul = (ULong)a + (ULong)p[1 + sizeof(Addr) + 1]; |
| 1080 | } else { |
| 1081 | if (!badness) |
| 1082 | badness = "trivial GExpr denotes constant address " |
| 1083 | "in unknown section (2)"; |
| 1084 | } |
| 1085 | } |
| 1086 | else |
| 1087 | if (nbytes == 2 + sizeof(Addr) |
| 1088 | && *p == DW_OP_addr |
| 1089 | && *(p + 1 + sizeof(Addr)) == DW_OP_GNU_push_tls_address) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1090 | if (!badness) |
| 1091 | badness = "trivial GExpr is DW_OP_addr plus trailing junk"; |
| 1092 | } |
| 1093 | else if (nbytes >= 1 && *p >= DW_OP_reg0 && *p <= DW_OP_reg31) { |
| 1094 | if (!badness) |
| 1095 | badness = "trivial GExpr denotes register (1)"; |
| 1096 | } |
| 1097 | else if (nbytes >= 1 && *p == DW_OP_fbreg) { |
| 1098 | if (!badness) |
| 1099 | badness = "trivial GExpr requires fbGX"; |
| 1100 | } |
| 1101 | else if (nbytes >= 1 && *p >= DW_OP_breg0 && *p <= DW_OP_breg31) { |
| 1102 | if (!badness) |
| 1103 | badness = "trivial GExpr requires register value"; |
| 1104 | } |
| 1105 | else if (nbytes >= 1 && *p == DW_OP_regx) { |
| 1106 | if (!badness) |
| 1107 | badness = "trivial GExpr denotes register (2)"; |
| 1108 | } |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1109 | else if (0) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1110 | VG_(printf)(" ML_(evaluate_trivial_GX): unhandled:\n "); |
| 1111 | ML_(pp_GX)( gx ); |
| 1112 | VG_(printf)("\n"); |
| 1113 | tl_assert(0); |
| 1114 | } |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1115 | else |
| 1116 | if (!badness) |
| 1117 | badness = "non-trivial GExpr"; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1118 | |
| 1119 | VG_(addToXA)( results, &thisResult ); |
| 1120 | |
| 1121 | p += (UWord)nbytes; |
| 1122 | } |
| 1123 | |
| 1124 | res.kind = GXR_Failure; |
| 1125 | |
| 1126 | tl_assert(nGuards == VG_(sizeXA)( results )); |
| 1127 | tl_assert(nGuards >= 0); |
| 1128 | if (nGuards == 0) { |
| 1129 | tl_assert(!badness); |
| 1130 | res.word = (UWord)"trivial GExpr has no guards (!)"; |
| 1131 | VG_(deleteXA)( results ); |
| 1132 | return res; |
| 1133 | } |
| 1134 | |
| 1135 | for (i = 0; i < nGuards; i++) { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1136 | mul = VG_(indexXA)( results, i ); |
| 1137 | if (mul->b == False) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1138 | break; |
| 1139 | } |
| 1140 | |
| 1141 | vg_assert(i >= 0 && i <= nGuards); |
| 1142 | if (i < nGuards) { |
| 1143 | /* at least one subexpression failed to produce a manifest constant. */ |
| 1144 | vg_assert(badness); |
| 1145 | res.word = (UWord)badness; |
| 1146 | VG_(deleteXA)( results ); |
| 1147 | return res; |
| 1148 | } |
| 1149 | |
| 1150 | /* All the subexpressions produced a constant, but did they all produce |
| 1151 | the same one? */ |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1152 | mul = VG_(indexXA)( results, 0 ); |
| 1153 | tl_assert(mul->b == True); /* we just established that all exprs are ok */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1154 | |
| 1155 | for (i = 1; i < nGuards; i++) { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1156 | mul2 = VG_(indexXA)( results, i ); |
| 1157 | tl_assert(mul2->b == True); |
| 1158 | if (mul2->ul != mul->ul) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1159 | res.word = (UWord)"trivial GExpr: subexpressions disagree"; |
| 1160 | VG_(deleteXA)( results ); |
| 1161 | return res; |
| 1162 | } |
| 1163 | } |
| 1164 | |
| 1165 | /* Well, we have success. All subexpressions evaluated, and |
| 1166 | they all agree. Hurrah. */ |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1167 | res.kind = GXR_Addr; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1168 | res.word = (UWord)mul->ul; /* NB: narrowing from ULong */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1169 | VG_(deleteXA)( results ); |
| 1170 | return res; |
| 1171 | } |
| 1172 | |
| 1173 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1174 | void ML_(pp_GXResult) ( GXResult res ) |
| 1175 | { |
| 1176 | switch (res.kind) { |
| 1177 | case GXR_Failure: |
| 1178 | VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1179 | case GXR_Addr: |
| 1180 | VG_(printf)("GXR_Addr(0x%lx)", res.word); break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1181 | case GXR_Value: |
| 1182 | VG_(printf)("GXR_Value(0x%lx)", res.word); break; |
| 1183 | case GXR_RegNo: |
| 1184 | VG_(printf)("GXR_RegNo(%lu)", res.word); break; |
| 1185 | default: |
| 1186 | VG_(printf)("GXR_???"); break; |
| 1187 | } |
| 1188 | } |
| 1189 | |
| 1190 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1191 | void ML_(pp_GX) ( GExpr* gx ) { |
| 1192 | Addr aMin, aMax; |
| 1193 | UChar uc; |
| 1194 | UShort nbytes; |
| 1195 | UChar* p = &gx->payload[0]; |
| 1196 | uc = *p++; |
| 1197 | VG_(printf)("GX(%s){", uc == 0 ? "final" : "Breqd" ); |
| 1198 | vg_assert(uc == 0 || uc == 1); |
| 1199 | while (True) { |
| 1200 | uc = *p++; |
| 1201 | if (uc == 1) |
| 1202 | break; /*isEnd*/ |
| 1203 | vg_assert(uc == 0); |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1204 | aMin = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1205 | aMax = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1206 | nbytes = ML_(read_UShort)(p); p += sizeof(UShort); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1207 | VG_(printf)("[%#lx,%#lx]=", aMin, aMax); |
| 1208 | while (nbytes > 0) { |
| 1209 | VG_(printf)("%02x", (UInt)*p++); |
| 1210 | nbytes--; |
| 1211 | } |
| 1212 | if (*p == 0) |
| 1213 | VG_(printf)(","); |
| 1214 | } |
| 1215 | VG_(printf)("}"); |
| 1216 | } |
| 1217 | |
| 1218 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1219 | /*--------------------------------------------------------------------*/ |
| 1220 | /*--- end d3basics.c ---*/ |
| 1221 | /*--------------------------------------------------------------------*/ |