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 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame^] | 11 | Copyright (C) 2008-2017 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"; |
philippe | af18689 | 2014-10-07 21:25:36 +0000 | [diff] [blame] | 327 | case DW_AT_GNU_all_tail_call_sites: return "DW_AT_GNU_all_tail_call_sites"; |
| 328 | case DW_AT_GNU_all_call_sites: return "DW_AT_GNU_all_call_sites"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 329 | /* VMS extensions. */ |
| 330 | case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; |
| 331 | /* UPC extension. */ |
| 332 | case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled"; |
| 333 | /* PGI (STMicroelectronics) extensions. */ |
| 334 | case DW_AT_PGI_lbase: return "DW_AT_PGI_lbase"; |
| 335 | case DW_AT_PGI_soffset: return "DW_AT_PGI_soffset"; |
| 336 | case DW_AT_PGI_lstride: return "DW_AT_PGI_lstride"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 337 | } |
bart | dac4779 | 2012-01-16 09:22:25 +0000 | [diff] [blame] | 338 | return "DW_AT_???"; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | |
| 342 | /* ------ To do with evaluation of Dwarf expressions ------ */ |
| 343 | |
| 344 | /* FIXME: duplicated in readdwarf.c */ |
| 345 | static |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 346 | ULong read_leb128 ( const UChar* data, Int* length_return, Int sign ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 347 | { |
| 348 | ULong result = 0; |
| 349 | UInt num_read = 0; |
| 350 | Int shift = 0; |
| 351 | UChar byte; |
| 352 | |
| 353 | vg_assert(sign == 0 || sign == 1); |
| 354 | |
| 355 | do |
| 356 | { |
| 357 | byte = * data ++; |
| 358 | num_read ++; |
| 359 | |
| 360 | result |= ((ULong)(byte & 0x7f)) << shift; |
| 361 | |
| 362 | shift += 7; |
| 363 | |
| 364 | } |
| 365 | while (byte & 0x80); |
| 366 | |
| 367 | if (length_return != NULL) |
| 368 | * length_return = num_read; |
| 369 | |
| 370 | if (sign && (shift < 64) && (byte & 0x40)) |
| 371 | result |= -(1ULL << shift); |
| 372 | |
| 373 | return result; |
| 374 | } |
| 375 | |
| 376 | /* Small helper functions easier to use |
| 377 | * value is returned and the given pointer is |
| 378 | * moved past end of leb128 data */ |
| 379 | /* FIXME: duplicated in readdwarf.c */ |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 380 | static ULong read_leb128U( const UChar **data ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 381 | { |
| 382 | Int len; |
| 383 | ULong val = read_leb128( *data, &len, 0 ); |
| 384 | *data += len; |
| 385 | return val; |
| 386 | } |
| 387 | |
| 388 | /* Same for signed data */ |
| 389 | /* FIXME: duplicated in readdwarf.c */ |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 390 | static Long read_leb128S( const UChar **data ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 391 | { |
| 392 | Int len; |
| 393 | ULong val = read_leb128( *data, &len, 1 ); |
| 394 | *data += len; |
| 395 | return (Long)val; |
| 396 | } |
| 397 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 398 | /* FIXME: duplicates logic in readdwarf.c: copy_convert_CfiExpr_tree |
| 399 | and {FP,SP}_REG decls */ |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 400 | static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 401 | { |
| 402 | vg_assert(regs); |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 403 | # if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \ |
| 404 | || defined(VGP_x86_solaris) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 405 | if (regno == 5/*EBP*/) { *a = regs->fp; return True; } |
| 406 | if (regno == 4/*ESP*/) { *a = regs->sp; return True; } |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 407 | # elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \ |
| 408 | || defined(VGP_amd64_solaris) |
njn | de706e3 | 2009-05-20 02:27:00 +0000 | [diff] [blame] | 409 | if (regno == 6/*RBP*/) { *a = regs->fp; return True; } |
| 410 | if (regno == 7/*RSP*/) { *a = regs->sp; return True; } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 411 | # elif defined(VGP_ppc32_linux) |
| 412 | if (regno == 1/*SP*/) { *a = regs->sp; return True; } |
carll | cae0cc2 | 2014-08-07 23:17:29 +0000 | [diff] [blame] | 413 | # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 414 | if (regno == 1/*SP*/) { *a = regs->sp; return True; } |
sewardj | 59570ff | 2010-01-01 11:59:33 +0000 | [diff] [blame] | 415 | # elif defined(VGP_arm_linux) |
| 416 | if (regno == 13) { *a = regs->sp; return True; } |
| 417 | if (regno == 11) { *a = regs->fp; return True; } |
sewardj | b5b8740 | 2011-03-07 16:05:35 +0000 | [diff] [blame] | 418 | # elif defined(VGP_s390x_linux) |
| 419 | if (regno == 15) { *a = regs->sp; return True; } |
| 420 | if (regno == 11) { *a = regs->fp; return True; } |
sewardj | 5db1540 | 2012-06-07 09:13:21 +0000 | [diff] [blame] | 421 | # elif defined(VGP_mips32_linux) |
| 422 | if (regno == 29) { *a = regs->sp; return True; } |
| 423 | if (regno == 30) { *a = regs->fp; return True; } |
petarj | 4df0bfc | 2013-02-27 23:17:33 +0000 | [diff] [blame] | 424 | # elif defined(VGP_mips64_linux) |
| 425 | if (regno == 29) { *a = regs->sp; return True; } |
| 426 | if (regno == 30) { *a = regs->fp; return True; } |
sewardj | f0c1250 | 2014-01-12 12:54:00 +0000 | [diff] [blame] | 427 | # elif defined(VGP_arm64_linux) |
sewardj | e22cbf3 | 2014-07-15 15:22:41 +0000 | [diff] [blame] | 428 | if (regno == 31) { *a = regs->sp; return True; } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 429 | # else |
| 430 | # error "Unknown platform" |
| 431 | # endif |
| 432 | return False; |
| 433 | } |
| 434 | |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 435 | /* Convert a stated address to an actual address */ |
| 436 | static Bool bias_address( Addr* a, const DebugInfo* di ) |
| 437 | { |
| 438 | if (di->text_present |
| 439 | && di->text_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 440 | && *a >= di->text_debug_svma && *a < di->text_debug_svma + di->text_size) { |
| 441 | *a += di->text_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 442 | } |
| 443 | else if (di->data_present |
| 444 | && di->data_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 445 | && *a >= di->data_debug_svma && *a < di->data_debug_svma + di->data_size) { |
| 446 | *a += di->data_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 447 | } |
| 448 | else if (di->sdata_present |
| 449 | && di->sdata_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 450 | && *a >= di->sdata_debug_svma && *a < di->sdata_debug_svma + di->sdata_size) { |
| 451 | *a += di->sdata_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 452 | } |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 453 | else if (di->rodata_present |
| 454 | && di->rodata_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 455 | && *a >= di->rodata_debug_svma && *a < di->rodata_debug_svma + di->rodata_size) { |
| 456 | *a += di->rodata_debug_bias; |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 457 | } |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 458 | else if (di->bss_present |
| 459 | && di->bss_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 460 | && *a >= di->bss_debug_svma && *a < di->bss_debug_svma + di->bss_size) { |
| 461 | *a += di->bss_debug_bias; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 462 | } |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 463 | else if (di->sbss_present |
| 464 | && di->sbss_size > 0 |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 465 | && *a >= di->sbss_debug_svma && *a < di->sbss_debug_svma + di->sbss_size) { |
| 466 | *a += di->sbss_debug_bias; |
tom | 160d5a8 | 2009-01-22 14:14:13 +0000 | [diff] [blame] | 467 | } |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 468 | else { |
| 469 | return False; |
| 470 | } |
| 471 | |
| 472 | return True; |
| 473 | } |
| 474 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 475 | |
| 476 | /* Evaluate a standard DWARF3 expression. See detailed description in |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 477 | priv_d3basics.h. Doesn't handle DW_OP_piece/DW_OP_bit_piece yet. */ |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 478 | GXResult ML_(evaluate_Dwarf3_Expr) ( const UChar* expr, UWord exprszB, |
| 479 | const GExpr* fbGX, const RegSummary* regs, |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 480 | const DebugInfo* di, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 481 | Bool push_initial_zero ) |
| 482 | { |
| 483 | # define N_EXPR_STACK 20 |
| 484 | |
| 485 | # define FAIL(_str) \ |
| 486 | do { \ |
| 487 | res.kind = GXR_Failure; \ |
| 488 | res.word = (UWord)(_str); \ |
| 489 | return res; \ |
| 490 | } while (0) |
| 491 | |
| 492 | # define PUSH(_arg) \ |
| 493 | do { \ |
| 494 | vg_assert(sp >= -1 && sp < N_EXPR_STACK); \ |
| 495 | if (sp == N_EXPR_STACK-1) \ |
| 496 | FAIL("evaluate_Dwarf3_Expr: stack overflow(1)"); \ |
| 497 | sp++; \ |
| 498 | stack[sp] = (_arg); \ |
| 499 | } while (0) |
| 500 | |
| 501 | # define POP(_lval) \ |
| 502 | do { \ |
| 503 | vg_assert(sp >= -1 && sp < N_EXPR_STACK); \ |
| 504 | if (sp == -1) \ |
| 505 | FAIL("evaluate_Dwarf3_Expr: stack underflow(1)"); \ |
| 506 | _lval = stack[sp]; \ |
| 507 | sp--; \ |
| 508 | } while (0) |
| 509 | |
| 510 | UChar opcode; |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 511 | const UChar* limit; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 512 | Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */ |
| 513 | Addr stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */ |
| 514 | GXResult fbval, res; |
| 515 | Addr a1; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 516 | Word sw1, sw2; |
| 517 | UWord uw1, uw2; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 518 | Bool ok; |
| 519 | |
| 520 | sp = -1; |
| 521 | vg_assert(expr); |
| 522 | vg_assert(exprszB >= 0); |
| 523 | limit = expr + exprszB; |
| 524 | |
| 525 | /* Deal with the case where the entire expression is a single |
| 526 | Register Name Operation (D3 spec sec 2.6.1). Then the |
| 527 | denotation of the expression as a whole is a register name. */ |
| 528 | if (exprszB == 1 |
| 529 | && expr[0] >= DW_OP_reg0 && expr[0] <= DW_OP_reg31) { |
| 530 | res.kind = GXR_RegNo; |
| 531 | res.word = (UWord)(expr[0] - DW_OP_reg0); |
| 532 | return res; |
| 533 | } |
| 534 | if (exprszB > 1 |
| 535 | && expr[0] == DW_OP_regx) { |
| 536 | /* JRS: 2008Feb20: I believe the following is correct, but would |
| 537 | like to see a test case show up before enabling it. */ |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 538 | expr++; |
| 539 | res.kind = GXR_RegNo; |
| 540 | res.word = (UWord)read_leb128U( &expr ); |
| 541 | if (expr != limit) |
| 542 | FAIL("evaluate_Dwarf3_Expr: DW_OP_regx*: invalid expr size"); |
| 543 | else |
| 544 | return res; |
| 545 | /*NOTREACHED*/ |
| 546 | } |
| 547 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 548 | /* Evidently this expression denotes a value, not a register name. |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 549 | So evaluate it accordingly. */ |
| 550 | |
| 551 | if (push_initial_zero) |
| 552 | PUSH(0); |
| 553 | |
| 554 | while (True) { |
| 555 | |
| 556 | vg_assert(sp >= -1 && sp < N_EXPR_STACK); |
| 557 | |
| 558 | if (expr > limit) |
| 559 | /* overrun - something's wrong */ |
| 560 | FAIL("evaluate_Dwarf3_Expr: ran off end of expr"); |
| 561 | |
| 562 | if (expr == limit) { |
| 563 | /* end of expr - return expr on the top of stack. */ |
| 564 | if (sp == -1) |
| 565 | /* stack empty. Bad. */ |
| 566 | FAIL("evaluate_Dwarf3_Expr: stack empty at end of expr"); |
| 567 | else |
| 568 | break; |
| 569 | } |
| 570 | |
| 571 | opcode = *expr++; |
| 572 | switch (opcode) { |
| 573 | case DW_OP_addr: |
| 574 | /* Presumably what is given in the Dwarf3 is a SVMA (how |
tom | 402c9ee | 2009-03-09 09:19:03 +0000 | [diff] [blame] | 575 | could it be otherwise?) So we add the appropriate bias |
| 576 | on before pushing the result. */ |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 577 | a1 = ML_(read_Addr)(expr); |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 578 | if (bias_address(&a1, di)) { |
| 579 | PUSH( a1 ); |
| 580 | expr += sizeof(Addr); |
| 581 | } |
| 582 | else { |
| 583 | FAIL("evaluate_Dwarf3_Expr: DW_OP_addr with address " |
| 584 | "in unknown section"); |
| 585 | } |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 586 | break; |
| 587 | case DW_OP_fbreg: |
| 588 | if (!fbGX) |
| 589 | FAIL("evaluate_Dwarf3_Expr: DW_OP_fbreg with " |
| 590 | "no expr for fbreg present"); |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 591 | fbval = ML_(evaluate_GX)(fbGX, NULL, regs, di); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 592 | /* Convert fbval into something we can use. If we got a |
| 593 | Value, no problem. However, as per D3 spec sec 3.3.5 |
| 594 | (Low Level Information) sec 2, we could also get a |
| 595 | RegNo, and that is taken to mean the value in the |
| 596 | indicated register. So we have to manually |
| 597 | "dereference" it. */ |
| 598 | a1 = 0; |
| 599 | switch (fbval.kind) { |
| 600 | case GXR_Failure: |
| 601 | return fbval; /* propagate failure */ |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 602 | case GXR_Addr: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 603 | a1 = fbval.word; break; /* use as-is */ |
| 604 | case GXR_RegNo: |
| 605 | ok = get_Dwarf_Reg( &a1, fbval.word, regs ); |
| 606 | if (!ok) return fbval; /* propagate failure */ |
| 607 | break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 608 | case GXR_Value: |
| 609 | FAIL("evaluate_Dwarf3_Expr: DW_OP_{implicit,stack}_value " |
| 610 | "in DW_AT_frame_base"); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 611 | default: |
| 612 | vg_assert(0); |
| 613 | } |
| 614 | sw1 = (Word)read_leb128S( &expr ); |
| 615 | PUSH( a1 + sw1 ); |
| 616 | break; |
| 617 | /* DW_OP_breg* denotes 'contents of specified register, plus |
| 618 | constant offset'. So provided we know what the register's |
| 619 | value is, we can evaluate this. Contrast DW_OP_reg*, |
| 620 | which indicates that denoted location is in a register |
| 621 | itself. If DW_OP_reg* shows up here the expression is |
| 622 | malformed, since we are evaluating for value now, and |
| 623 | DW_OP_reg* denotes a register location, not a value. See |
| 624 | D3 Spec sec 2.6.1 ("Register Name Operations") for |
| 625 | details. */ |
| 626 | case DW_OP_breg0 ... DW_OP_breg31: |
| 627 | if (!regs) |
| 628 | FAIL("evaluate_Dwarf3_Expr: DW_OP_breg* but no reg info"); |
| 629 | a1 = 0; |
| 630 | if (!get_Dwarf_Reg( &a1, opcode - DW_OP_breg0, regs )) |
| 631 | FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_breg*"); |
| 632 | sw1 = (Word)read_leb128S( &expr ); |
| 633 | a1 += sw1; |
| 634 | PUSH( a1 ); |
| 635 | break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 636 | case DW_OP_bregx: |
| 637 | if (!regs) |
| 638 | FAIL("evaluate_Dwarf3_Expr: DW_OP_bregx but no reg info"); |
| 639 | a1 = 0; |
| 640 | uw1 = (UWord)read_leb128U( &expr ); |
| 641 | if (!get_Dwarf_Reg( &a1, uw1, regs )) |
| 642 | FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_bregx reg value"); |
| 643 | sw1 = (Word)read_leb128S( &expr ); |
| 644 | a1 += sw1; |
| 645 | PUSH( a1 ); |
| 646 | break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 647 | /* As per comment on DW_OP_breg*, the following denote that |
| 648 | the value in question is in a register, not in memory. So |
| 649 | we simply return failure. (iow, the expression is |
| 650 | malformed). */ |
| 651 | case DW_OP_reg0 ... DW_OP_reg31: |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 652 | case DW_OP_regx: |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 653 | FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* " |
| 654 | "whilst evaluating for a value"); |
| 655 | break; |
| 656 | case DW_OP_plus_uconst: |
| 657 | POP(uw1); |
| 658 | uw1 += (UWord)read_leb128U( &expr ); |
| 659 | PUSH(uw1); |
| 660 | break; |
| 661 | case DW_OP_GNU_push_tls_address: |
| 662 | /* GDB contains the following cryptic comment: */ |
| 663 | /* Variable is at a constant offset in the thread-local |
| 664 | storage block into the objfile for the current thread and |
| 665 | the dynamic linker module containing this expression. Here |
| 666 | we return returns the offset from that base. The top of the |
| 667 | stack has the offset from the beginning of the thread |
| 668 | control block at which the variable is located. Nothing |
| 669 | should follow this operator, so the top of stack would be |
| 670 | returned. */ |
| 671 | /* But no spec resulting from Googling. Punt for now. */ |
| 672 | FAIL("warning: evaluate_Dwarf3_Expr: unhandled " |
| 673 | "DW_OP_GNU_push_tls_address"); |
| 674 | /*NOTREACHED*/ |
sewardj | aa3c28a | 2008-03-08 10:44:39 +0000 | [diff] [blame] | 675 | case DW_OP_deref: |
| 676 | POP(uw1); |
| 677 | if (VG_(am_is_valid_for_client)( (Addr)uw1, sizeof(Addr), |
| 678 | VKI_PROT_READ )) { |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 679 | uw1 = ML_(read_UWord)((void *)uw1); |
sewardj | aa3c28a | 2008-03-08 10:44:39 +0000 | [diff] [blame] | 680 | PUSH(uw1); |
| 681 | } else { |
| 682 | FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref: " |
| 683 | "address not valid for client"); |
| 684 | } |
| 685 | break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 686 | case DW_OP_deref_size: |
| 687 | POP(uw1); |
| 688 | uw2 = *expr++; |
| 689 | if (VG_(am_is_valid_for_client)( (Addr)uw1, uw2, |
| 690 | VKI_PROT_READ )) { |
| 691 | switch (uw2) { |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 692 | case 1: uw1 = ML_(read_UChar)((void*)uw1); break; |
| 693 | case 2: uw1 = ML_(read_UShort)((void*)uw1); break; |
| 694 | case 4: uw1 = ML_(read_UInt)((void*)uw1); break; |
| 695 | case 8: uw1 = ML_(read_ULong)((void*)uw1); break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 696 | default: |
| 697 | FAIL("warning: evaluate_Dwarf3_Expr: unhandled " |
| 698 | "DW_OP_deref_size size"); |
| 699 | } |
| 700 | PUSH(uw1); |
| 701 | } else { |
| 702 | FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref_size: " |
| 703 | "address not valid for client"); |
| 704 | } |
| 705 | break; |
| 706 | case DW_OP_lit0 ... DW_OP_lit31: |
| 707 | PUSH(opcode - DW_OP_lit0); |
| 708 | break; |
| 709 | case DW_OP_const1u: |
| 710 | uw1 = *expr++; |
| 711 | PUSH(uw1); |
| 712 | break; |
| 713 | case DW_OP_const2u: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 714 | uw1 = ML_(read_UShort)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 715 | expr += 2; |
| 716 | PUSH(uw1); |
| 717 | break; |
| 718 | case DW_OP_const4u: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 719 | uw1 = ML_(read_UInt)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 720 | expr += 4; |
| 721 | PUSH(uw1); |
| 722 | break; |
| 723 | case DW_OP_const8u: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 724 | uw1 = ML_(read_ULong)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 725 | expr += 8; |
| 726 | PUSH(uw1); |
| 727 | break; |
| 728 | case DW_OP_constu: |
| 729 | uw1 = read_leb128U( &expr ); |
| 730 | PUSH(uw1); |
| 731 | break; |
| 732 | case DW_OP_const1s: |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 733 | uw1 = *(const Char *)expr; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 734 | expr++; |
| 735 | PUSH(uw1); |
| 736 | break; |
| 737 | case DW_OP_const2s: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 738 | uw1 = ML_(read_Short)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 739 | expr += 2; |
| 740 | PUSH(uw1); |
| 741 | break; |
| 742 | case DW_OP_const4s: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 743 | uw1 = ML_(read_Int)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 744 | expr += 4; |
| 745 | PUSH(uw1); |
| 746 | break; |
| 747 | case DW_OP_const8s: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 748 | uw1 = ML_(read_Long)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 749 | expr += 8; |
| 750 | PUSH(uw1); |
| 751 | break; |
| 752 | case DW_OP_consts: |
| 753 | uw1 = read_leb128S( &expr ); |
| 754 | PUSH(uw1); |
| 755 | break; |
| 756 | case DW_OP_dup: |
| 757 | POP(uw1); |
| 758 | PUSH(uw1); |
| 759 | PUSH(uw1); |
| 760 | break; |
| 761 | case DW_OP_drop: |
| 762 | POP(uw1); |
| 763 | break; |
| 764 | case DW_OP_over: |
| 765 | uw1 = 1; |
| 766 | goto do_pick; |
| 767 | case DW_OP_pick: |
| 768 | uw1 = *expr++; |
| 769 | do_pick: |
| 770 | if (sp < (Int)uw1) |
| 771 | FAIL("evaluate_Dwarf3_Expr: stack underflow"); |
| 772 | uw1 = stack[sp - uw1]; |
| 773 | PUSH(uw1); |
| 774 | break; |
| 775 | case DW_OP_swap: |
| 776 | if (sp < 1) |
| 777 | FAIL("evaluate_Dwarf3_Expr: stack underflow"); |
| 778 | uw1 = stack[sp]; |
| 779 | stack[sp] = stack[sp - 1]; |
| 780 | stack[sp - 1] = uw1; |
| 781 | break; |
| 782 | case DW_OP_rot: |
| 783 | if (sp < 2) |
| 784 | FAIL("evaluate_Dwarf3_Expr: stack underflow"); |
| 785 | uw1 = stack[sp]; |
| 786 | stack[sp] = stack[sp - 1]; |
| 787 | stack[sp - 1] = stack[sp - 2]; |
| 788 | stack[sp - 2] = uw1; |
| 789 | break; |
| 790 | case DW_OP_abs: |
| 791 | POP(sw1); |
| 792 | if (sw1 < 0) |
| 793 | sw1 = -sw1; |
| 794 | PUSH(sw1); |
| 795 | break; |
| 796 | case DW_OP_div: |
| 797 | POP(sw2); |
| 798 | if (sw2 == 0) |
| 799 | FAIL("evaluate_Dwarf3_Expr: division by zero"); |
| 800 | POP(sw1); |
| 801 | sw1 /= sw2; |
| 802 | PUSH(sw1); |
| 803 | break; |
| 804 | case DW_OP_mod: |
tom | b9c17d2 | 2010-01-21 10:19:46 +0000 | [diff] [blame] | 805 | POP(uw2); |
| 806 | if (uw2 == 0) |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 807 | FAIL("evaluate_Dwarf3_Expr: division by zero"); |
tom | b9c17d2 | 2010-01-21 10:19:46 +0000 | [diff] [blame] | 808 | POP(uw1); |
| 809 | uw1 %= uw2; |
| 810 | PUSH(uw1); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 811 | break; |
| 812 | #define BINARY(name, op, s) \ |
| 813 | case DW_OP_##name: \ |
| 814 | POP(s##w2); \ |
| 815 | POP(s##w1); \ |
| 816 | s##w1 = s##w1 op s##w2; \ |
| 817 | PUSH(s##w1); \ |
| 818 | break |
| 819 | #define UNARY(name, op, s) \ |
| 820 | case DW_OP_##name: \ |
| 821 | POP(s##w1); \ |
| 822 | s##w1 = op s##w1; \ |
| 823 | PUSH(s##w1); \ |
| 824 | break |
| 825 | BINARY (and, &, u); |
| 826 | BINARY (minus, -, u); |
| 827 | BINARY (mul, *, u); |
| 828 | UNARY (neg, -, u); |
| 829 | UNARY (not, ~, u); |
| 830 | BINARY (or, |, u); |
| 831 | BINARY (plus, +, u); |
| 832 | BINARY (shl, <<, u); |
| 833 | BINARY (shr, >>, u); |
| 834 | BINARY (shra, >>, s); |
| 835 | BINARY (xor, ^, u); |
| 836 | BINARY (le, <=, s); |
| 837 | BINARY (lt, <, s); |
| 838 | BINARY (ge, >=, s); |
| 839 | BINARY (gt, >, s); |
| 840 | BINARY (ne, !=, u); |
| 841 | BINARY (eq, ==, u); |
| 842 | #undef UNARY |
| 843 | #undef BINARY |
| 844 | case DW_OP_skip: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 845 | sw1 = ML_(read_Short)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 846 | expr += 2; |
| 847 | if (expr + sw1 < limit - exprszB) |
| 848 | FAIL("evaluate_Dwarf3_Expr: DW_OP_skip before start of expr"); |
| 849 | if (expr + sw1 >= limit) |
| 850 | FAIL("evaluate_Dwarf3_Expr: DW_OP_skip after end of expr"); |
| 851 | expr += sw1; |
| 852 | break; |
| 853 | case DW_OP_bra: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 854 | sw1 = ML_(read_Short)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 855 | expr += 2; |
| 856 | if (expr + sw1 < limit - exprszB) |
| 857 | FAIL("evaluate_Dwarf3_Expr: DW_OP_bra before start of expr"); |
| 858 | if (expr + sw1 >= limit) |
| 859 | FAIL("evaluate_Dwarf3_Expr: DW_OP_bra after end of expr"); |
| 860 | POP(uw1); |
| 861 | if (uw1) |
| 862 | expr += sw1; |
| 863 | break; |
| 864 | case DW_OP_nop: |
| 865 | break; |
| 866 | case DW_OP_call_frame_cfa: |
| 867 | if (!regs) |
sewardj | 3026f71 | 2010-01-01 18:46:41 +0000 | [diff] [blame] | 868 | FAIL("evaluate_Dwarf3_Expr: " |
| 869 | "DW_OP_call_frame_cfa but no reg info"); |
carll | cae0cc2 | 2014-08-07 23:17:29 +0000 | [diff] [blame] | 870 | #if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \ |
| 871 | || defined(VGP_ppc64le_linux) |
sewardj | 3026f71 | 2010-01-01 18:46:41 +0000 | [diff] [blame] | 872 | /* Valgrind on ppc32/ppc64 currently doesn't use unwind info. */ |
sewardj | 50f5cea | 2011-10-20 10:41:37 +0000 | [diff] [blame] | 873 | uw1 = ML_(read_Addr)((UChar*)regs->sp); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 874 | #else |
| 875 | uw1 = ML_(get_CFA)(regs->ip, regs->sp, regs->fp, 0, ~(UWord) 0); |
| 876 | #endif |
sewardj | 3026f71 | 2010-01-01 18:46:41 +0000 | [diff] [blame] | 877 | /* we expect this to fail on arm-linux, since ML_(get_CFA) |
| 878 | always returns zero at present. */ |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 879 | if (!uw1) |
| 880 | FAIL("evaluate_Dwarf3_Expr: Could not resolve " |
| 881 | "DW_OP_call_frame_cfa"); |
| 882 | PUSH(uw1); |
| 883 | break; |
| 884 | case DW_OP_implicit_value: |
| 885 | sw1 = (Word)read_leb128S( &expr ); |
| 886 | uw1 = 0; |
| 887 | switch (sw1) { |
| 888 | case 1: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 889 | uw1 = ML_(read_UChar)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 890 | expr += 1; |
| 891 | break; |
| 892 | case 2: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 893 | uw1 = ML_(read_UShort)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 894 | expr += 2; |
| 895 | break; |
| 896 | case 4: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 897 | uw1 = ML_(read_UInt)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 898 | expr += 4; |
| 899 | break; |
| 900 | case 8: |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 901 | uw1 = ML_(read_ULong)(expr); |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 902 | expr += 8; |
| 903 | break; |
| 904 | default: |
| 905 | FAIL("evaluate_Dwarf3_Expr: Unhandled " |
| 906 | "DW_OP_implicit_value size"); |
| 907 | } |
| 908 | if (expr != limit) |
| 909 | FAIL("evaluate_Dwarf3_Expr: DW_OP_implicit_value " |
| 910 | "does not terminate expression"); |
| 911 | res.word = uw1; |
| 912 | res.kind = GXR_Value; |
| 913 | return res; |
| 914 | case DW_OP_stack_value: |
| 915 | POP (uw1); |
| 916 | res.word = uw1; |
| 917 | res.kind = GXR_Value; |
| 918 | if (expr != limit) |
| 919 | FAIL("evaluate_Dwarf3_Expr: DW_OP_stack_value " |
| 920 | "does not terminate expression"); |
| 921 | break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 922 | default: |
| 923 | if (!VG_(clo_xml)) |
| 924 | VG_(message)(Vg_DebugMsg, |
| 925 | "warning: evaluate_Dwarf3_Expr: unhandled " |
sewardj | 738856f | 2009-07-15 14:48:32 +0000 | [diff] [blame] | 926 | "DW_OP_ 0x%x\n", (Int)opcode); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 927 | FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_"); |
| 928 | /*NOTREACHED*/ |
| 929 | } |
| 930 | |
| 931 | } |
| 932 | |
| 933 | vg_assert(sp >= 0 && sp < N_EXPR_STACK); |
| 934 | res.word = stack[sp]; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 935 | res.kind = GXR_Addr; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 936 | return res; |
| 937 | |
| 938 | # undef POP |
| 939 | # undef PUSH |
| 940 | # undef FAIL |
| 941 | # undef N_EXPR_STACK |
| 942 | } |
| 943 | |
| 944 | |
| 945 | /* Evaluate a so-called Guarded (DWARF3) expression. See detailed |
| 946 | description in priv_d3basics.h. */ |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 947 | GXResult ML_(evaluate_GX)( const GExpr* gx, const GExpr* fbGX, |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 948 | const RegSummary* regs, const DebugInfo* di ) |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 949 | { |
| 950 | GXResult res; |
| 951 | Addr aMin, aMax; |
| 952 | UChar uc; |
| 953 | UShort nbytes; |
| 954 | UWord nGuards = 0; |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 955 | const UChar* p = &gx->payload[0]; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 956 | uc = *p++; /*biasMe*/ |
| 957 | vg_assert(uc == 0 || uc == 1); |
| 958 | /* in fact it's senseless to evaluate if the guards need biasing. |
| 959 | So don't. */ |
| 960 | vg_assert(uc == 0); |
| 961 | while (True) { |
| 962 | uc = *p++; |
| 963 | if (uc == 1) { /*isEnd*/ |
| 964 | /* didn't find any matching range. */ |
| 965 | res.kind = GXR_Failure; |
| 966 | res.word = (UWord)"no matching range"; |
| 967 | return res; |
| 968 | } |
| 969 | vg_assert(uc == 0); |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 970 | aMin = ML_(read_Addr)(p); p += sizeof(Addr); |
| 971 | aMax = ML_(read_Addr)(p); p += sizeof(Addr); |
| 972 | nbytes = ML_(read_UShort)(p); p += sizeof(UShort); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 973 | nGuards++; |
florian | c6e5d76 | 2015-08-05 22:27:24 +0000 | [diff] [blame] | 974 | if (0) VG_(printf)(" guard %lu: %#lx %#lx\n", |
| 975 | nGuards, aMin,aMax); |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 976 | if (regs == NULL) { |
| 977 | vg_assert(aMin == (Addr)0); |
| 978 | vg_assert(aMax == ~(Addr)0); |
| 979 | /* Assert this is the first guard. */ |
| 980 | vg_assert(nGuards == 1); |
| 981 | res = ML_(evaluate_Dwarf3_Expr)( |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 982 | p, (UWord)nbytes, fbGX, regs, di, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 983 | False/*push_initial_zero*/ ); |
| 984 | /* Now check there are no more guards. */ |
| 985 | p += (UWord)nbytes; |
| 986 | vg_assert(*p == 1); /*isEnd*/ |
| 987 | return res; |
| 988 | } else { |
| 989 | if (aMin <= regs->ip && regs->ip <= aMax) { |
| 990 | /* found a matching range. Evaluate the expression. */ |
| 991 | return ML_(evaluate_Dwarf3_Expr)( |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 992 | p, (UWord)nbytes, fbGX, regs, di, |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 993 | False/*push_initial_zero*/ ); |
| 994 | } |
| 995 | } |
| 996 | /* else keep searching */ |
| 997 | p += (UWord)nbytes; |
| 998 | } |
| 999 | } |
| 1000 | |
| 1001 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1002 | /* Evaluate a very simple Guarded (DWARF3) expression. The expression |
| 1003 | is expected to denote a constant, with no reference to any |
| 1004 | registers nor to any frame base expression. The expression is |
| 1005 | expected to have at least one guard. If there is more than one |
| 1006 | guard, all the sub-expressions are evaluated and compared. The |
| 1007 | address ranges on the guards are ignored. GXR_Failure is returned |
| 1008 | in the following circumstances: |
| 1009 | * no guards |
| 1010 | * any of the subexpressions require a frame base expression |
| 1011 | * any of the subexpressions denote a register location |
| 1012 | * any of the subexpressions do not produce a manifest constant |
| 1013 | * there's more than one subexpression, all of which successfully |
| 1014 | evaluate to a constant, but they don't all produce the same constant. |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1015 | JRS 23Jan09: the special-casing in this function is a nasty kludge. |
| 1016 | Really it ought to be pulled out and turned into a general |
| 1017 | constant- expression evaluator. |
| 1018 | */ |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 1019 | GXResult ML_(evaluate_trivial_GX)( const GExpr* gx, const DebugInfo* di ) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1020 | { |
| 1021 | GXResult res; |
| 1022 | Addr aMin, aMax; |
| 1023 | UChar uc; |
| 1024 | UShort nbytes; |
| 1025 | Word i, nGuards; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1026 | MaybeULong *mul, *mul2; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1027 | |
florian | 6bd9dc1 | 2012-11-23 16:17:43 +0000 | [diff] [blame] | 1028 | const HChar* badness = NULL; |
florian | 3297124 | 2014-10-23 17:47:15 +0000 | [diff] [blame] | 1029 | const UChar* p = &gx->payload[0]; /* must remain unsigned */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1030 | XArray* results = VG_(newXA)( ML_(dinfo_zalloc), "di.d3basics.etG.1", |
| 1031 | ML_(dinfo_free), |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1032 | sizeof(MaybeULong) ); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1033 | |
| 1034 | uc = *p++; /*biasMe*/ |
| 1035 | vg_assert(uc == 0 || uc == 1); |
| 1036 | /* in fact it's senseless to evaluate if the guards need biasing. |
| 1037 | So don't. */ |
| 1038 | vg_assert(uc == 0); |
| 1039 | |
| 1040 | nGuards = 0; |
| 1041 | while (True) { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1042 | MaybeULong thisResult; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1043 | uc = *p++; |
| 1044 | if (uc == 1) /*isEnd*/ |
| 1045 | break; |
| 1046 | vg_assert(uc == 0); |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1047 | aMin = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1048 | aMax = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1049 | nbytes = ML_(read_UShort)(p); p += sizeof(UShort); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1050 | nGuards++; |
| 1051 | if (0) VG_(printf)(" guard %ld: %#lx %#lx\n", |
| 1052 | nGuards, aMin,aMax); |
| 1053 | |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1054 | thisResult.b = False; |
| 1055 | thisResult.ul = 0; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1056 | |
| 1057 | /* Peer at this particular subexpression, to see if it's |
| 1058 | obviously a constant. */ |
| 1059 | if (nbytes == 1 + sizeof(Addr) && *p == DW_OP_addr) { |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1060 | /* DW_OP_addr a */ |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1061 | Addr a = ML_(read_Addr)((p+1)); |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 1062 | if (bias_address(&a, di)) { |
| 1063 | thisResult.b = True; |
| 1064 | thisResult.ul = (ULong)a; |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1065 | } else { |
| 1066 | if (!badness) |
| 1067 | badness = "trivial GExpr denotes constant address " |
| 1068 | "in unknown section (1)"; |
tom | 588658b | 2009-01-22 13:40:12 +0000 | [diff] [blame] | 1069 | } |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1070 | } |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1071 | else |
| 1072 | if (nbytes == 1 + sizeof(Addr) + 1 + 1 |
| 1073 | /* 11 byte block: 3 c0 b6 2b 0 0 0 0 0 23 4 |
| 1074 | (DW_OP_addr: 2bb6c0; DW_OP_plus_uconst: 4) |
| 1075 | This is really a nasty kludge - only matches if the |
| 1076 | trailing ULEB denotes a number in the range 0 .. 127 |
| 1077 | inclusive. */ |
| 1078 | && p[0] == DW_OP_addr |
| 1079 | && p[1 + sizeof(Addr)] == DW_OP_plus_uconst |
| 1080 | && p[1 + sizeof(Addr) + 1] < 0x80 /*1-byte ULEB*/) { |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1081 | Addr a = ML_(read_Addr)(&p[1]); |
sewardj | ec3f2ce | 2009-01-24 00:06:13 +0000 | [diff] [blame] | 1082 | if (bias_address(&a, di)) { |
| 1083 | thisResult.b = True; |
| 1084 | thisResult.ul = (ULong)a + (ULong)p[1 + sizeof(Addr) + 1]; |
| 1085 | } else { |
| 1086 | if (!badness) |
| 1087 | badness = "trivial GExpr denotes constant address " |
| 1088 | "in unknown section (2)"; |
| 1089 | } |
| 1090 | } |
| 1091 | else |
| 1092 | if (nbytes == 2 + sizeof(Addr) |
| 1093 | && *p == DW_OP_addr |
| 1094 | && *(p + 1 + sizeof(Addr)) == DW_OP_GNU_push_tls_address) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1095 | if (!badness) |
| 1096 | badness = "trivial GExpr is DW_OP_addr plus trailing junk"; |
| 1097 | } |
| 1098 | else if (nbytes >= 1 && *p >= DW_OP_reg0 && *p <= DW_OP_reg31) { |
| 1099 | if (!badness) |
| 1100 | badness = "trivial GExpr denotes register (1)"; |
| 1101 | } |
| 1102 | else if (nbytes >= 1 && *p == DW_OP_fbreg) { |
| 1103 | if (!badness) |
| 1104 | badness = "trivial GExpr requires fbGX"; |
| 1105 | } |
| 1106 | else if (nbytes >= 1 && *p >= DW_OP_breg0 && *p <= DW_OP_breg31) { |
| 1107 | if (!badness) |
| 1108 | badness = "trivial GExpr requires register value"; |
| 1109 | } |
| 1110 | else if (nbytes >= 1 && *p == DW_OP_regx) { |
| 1111 | if (!badness) |
| 1112 | badness = "trivial GExpr denotes register (2)"; |
| 1113 | } |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1114 | else if (0) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1115 | VG_(printf)(" ML_(evaluate_trivial_GX): unhandled:\n "); |
| 1116 | ML_(pp_GX)( gx ); |
| 1117 | VG_(printf)("\n"); |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 1118 | vg_assert(0); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1119 | } |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1120 | else |
| 1121 | if (!badness) |
| 1122 | badness = "non-trivial GExpr"; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1123 | |
| 1124 | VG_(addToXA)( results, &thisResult ); |
| 1125 | |
| 1126 | p += (UWord)nbytes; |
| 1127 | } |
| 1128 | |
| 1129 | res.kind = GXR_Failure; |
| 1130 | |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 1131 | vg_assert(nGuards == VG_(sizeXA)( results )); |
| 1132 | vg_assert(nGuards >= 0); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1133 | if (nGuards == 0) { |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 1134 | vg_assert(!badness); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1135 | res.word = (UWord)"trivial GExpr has no guards (!)"; |
| 1136 | VG_(deleteXA)( results ); |
| 1137 | return res; |
| 1138 | } |
| 1139 | |
| 1140 | for (i = 0; i < nGuards; i++) { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1141 | mul = VG_(indexXA)( results, i ); |
| 1142 | if (mul->b == False) |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1143 | break; |
| 1144 | } |
| 1145 | |
| 1146 | vg_assert(i >= 0 && i <= nGuards); |
| 1147 | if (i < nGuards) { |
| 1148 | /* at least one subexpression failed to produce a manifest constant. */ |
| 1149 | vg_assert(badness); |
| 1150 | res.word = (UWord)badness; |
| 1151 | VG_(deleteXA)( results ); |
| 1152 | return res; |
| 1153 | } |
| 1154 | |
| 1155 | /* All the subexpressions produced a constant, but did they all produce |
| 1156 | the same one? */ |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1157 | mul = VG_(indexXA)( results, 0 ); |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 1158 | vg_assert(mul->b == True); /* we just established that all exprs are ok */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1159 | |
| 1160 | for (i = 1; i < nGuards; i++) { |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1161 | mul2 = VG_(indexXA)( results, i ); |
florian | e2800c9 | 2014-09-15 20:57:45 +0000 | [diff] [blame] | 1162 | vg_assert(mul2->b == True); |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1163 | if (mul2->ul != mul->ul) { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1164 | res.word = (UWord)"trivial GExpr: subexpressions disagree"; |
| 1165 | VG_(deleteXA)( results ); |
| 1166 | return res; |
| 1167 | } |
| 1168 | } |
| 1169 | |
| 1170 | /* Well, we have success. All subexpressions evaluated, and |
| 1171 | they all agree. Hurrah. */ |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1172 | res.kind = GXR_Addr; |
sewardj | 50fde23 | 2008-10-20 16:08:55 +0000 | [diff] [blame] | 1173 | res.word = (UWord)mul->ul; /* NB: narrowing from ULong */ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1174 | VG_(deleteXA)( results ); |
| 1175 | return res; |
| 1176 | } |
| 1177 | |
| 1178 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1179 | void ML_(pp_GXResult) ( GXResult res ) |
| 1180 | { |
| 1181 | switch (res.kind) { |
| 1182 | case GXR_Failure: |
| 1183 | VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break; |
tom | 3c9cf34 | 2009-11-12 13:28:34 +0000 | [diff] [blame] | 1184 | case GXR_Addr: |
| 1185 | VG_(printf)("GXR_Addr(0x%lx)", res.word); break; |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1186 | case GXR_Value: |
| 1187 | VG_(printf)("GXR_Value(0x%lx)", res.word); break; |
| 1188 | case GXR_RegNo: |
| 1189 | VG_(printf)("GXR_RegNo(%lu)", res.word); break; |
| 1190 | default: |
| 1191 | VG_(printf)("GXR_???"); break; |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 1196 | void ML_(pp_GX) ( const GExpr* gx ) |
| 1197 | { |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1198 | Addr aMin, aMax; |
| 1199 | UChar uc; |
| 1200 | UShort nbytes; |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 1201 | const UChar* p = &gx->payload[0]; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1202 | uc = *p++; |
| 1203 | VG_(printf)("GX(%s){", uc == 0 ? "final" : "Breqd" ); |
| 1204 | vg_assert(uc == 0 || uc == 1); |
| 1205 | while (True) { |
| 1206 | uc = *p++; |
| 1207 | if (uc == 1) |
| 1208 | break; /*isEnd*/ |
| 1209 | vg_assert(uc == 0); |
tom | 86781fa | 2011-10-05 08:48:07 +0000 | [diff] [blame] | 1210 | aMin = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1211 | aMax = ML_(read_Addr)(p); p += sizeof(Addr); |
| 1212 | nbytes = ML_(read_UShort)(p); p += sizeof(UShort); |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 1213 | VG_(printf)("[%#lx,%#lx]=", aMin, aMax); |
| 1214 | while (nbytes > 0) { |
| 1215 | VG_(printf)("%02x", (UInt)*p++); |
| 1216 | nbytes--; |
| 1217 | } |
| 1218 | if (*p == 0) |
| 1219 | VG_(printf)(","); |
| 1220 | } |
| 1221 | VG_(printf)("}"); |
| 1222 | } |
| 1223 | |
| 1224 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 1225 | /*--------------------------------------------------------------------*/ |
| 1226 | /*--- end d3basics.c ---*/ |
| 1227 | /*--------------------------------------------------------------------*/ |