1 //===-- DWARFExpression.h ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_DWARFExpression_h_ 11 #define liblldb_DWARFExpression_h_ 12 13 #include "lldb/Core/Address.h" 14 #include "lldb/Core/Disassembler.h" 15 #include "lldb/Utility/DataExtractor.h" 16 #include "lldb/Utility/Scalar.h" 17 #include "lldb/Utility/Status.h" 18 #include "lldb/lldb-private.h" 19 #include <functional> 20 21 class DWARFUnit; 22 23 namespace lldb_private { 24 25 //---------------------------------------------------------------------- 26 /// @class DWARFExpression DWARFExpression.h 27 /// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location 28 /// expression and interprets it. 29 /// 30 /// DWARF location expressions are used in two ways by LLDB. The first 31 /// use is to find entities specified in the debug information, since their 32 /// locations are specified in precisely this language. The second is to 33 /// interpret expressions without having to run the target in cases where the 34 /// overhead from copying JIT-compiled code into the target is too high or 35 /// where the target cannot be run. This class encapsulates a single DWARF 36 /// location expression or a location list and interprets it. 37 //---------------------------------------------------------------------- 38 class DWARFExpression { 39 public: 40 enum LocationListFormat : uint8_t { 41 NonLocationList, // Not a location list 42 RegularLocationList, // Location list format used in non-split dwarf files 43 SplitDwarfLocationList, // Location list format used in pre-DWARF v5 split 44 // dwarf files (.debug_loc.dwo) 45 LocLists, // Location list format used in DWARF v5 46 // (.debug_loclists/.debug_loclists.dwo). 47 }; 48 49 //------------------------------------------------------------------ 50 /// Constructor 51 //------------------------------------------------------------------ 52 explicit DWARFExpression(DWARFUnit *dwarf_cu); 53 54 //------------------------------------------------------------------ 55 /// Constructor 56 /// 57 /// @param[in] data 58 /// A data extractor configured to read the DWARF location expression's 59 /// bytecode. 60 /// 61 /// @param[in] data_offset 62 /// The offset of the location expression in the extractor. 63 /// 64 /// @param[in] data_length 65 /// The byte length of the location expression. 66 //------------------------------------------------------------------ 67 DWARFExpression(lldb::ModuleSP module, const DataExtractor &data, 68 DWARFUnit *dwarf_cu, lldb::offset_t data_offset, 69 lldb::offset_t data_length); 70 71 //------------------------------------------------------------------ 72 /// Copy constructor 73 //------------------------------------------------------------------ 74 DWARFExpression(const DWARFExpression &rhs); 75 76 //------------------------------------------------------------------ 77 /// Destructor 78 //------------------------------------------------------------------ 79 virtual ~DWARFExpression(); 80 81 //------------------------------------------------------------------ 82 /// Print the description of the expression to a stream 83 /// 84 /// @param[in] s 85 /// The stream to print to. 86 /// 87 /// @param[in] level 88 /// The level of verbosity to use. 89 /// 90 /// @param[in] location_list_base_addr 91 /// If this is a location list based expression, this is the 92 /// address of the object that owns it. NOTE: this value is 93 /// different from the DWARF version of the location list base 94 /// address which is compile unit relative. This base address 95 /// is the address of the object that owns the location list. 96 /// 97 /// @param[in] abi 98 /// An optional ABI plug-in that can be used to resolve register 99 /// names. 100 //------------------------------------------------------------------ 101 void GetDescription(Stream *s, lldb::DescriptionLevel level, 102 lldb::addr_t location_list_base_addr, ABI *abi) const; 103 104 //------------------------------------------------------------------ 105 /// Return true if the location expression contains data 106 //------------------------------------------------------------------ 107 bool IsValid() const; 108 109 //------------------------------------------------------------------ 110 /// Return true if a location list was provided 111 //------------------------------------------------------------------ 112 bool IsLocationList() const; 113 114 //------------------------------------------------------------------ 115 /// Search for a load address in the location list 116 /// 117 /// @param[in] process 118 /// The process to use when resolving the load address 119 /// 120 /// @param[in] addr 121 /// The address to resolve 122 /// 123 /// @return 124 /// True if IsLocationList() is true and the address was found; 125 /// false otherwise. 126 //------------------------------------------------------------------ 127 // bool 128 // LocationListContainsLoadAddress (Process* process, const Address &addr) 129 // const; 130 // 131 bool LocationListContainsAddress(lldb::addr_t loclist_base_addr, 132 lldb::addr_t addr) const; 133 134 //------------------------------------------------------------------ 135 /// If a location is not a location list, return true if the location 136 /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr. 137 /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true 138 /// if the variable there is any DW_OP_addr in a location that (yet still is 139 /// NOT a location list). This helps us detect if a variable is a global or 140 /// static variable since there is no other indication from DWARF debug 141 /// info. 142 /// 143 /// @param[in] op_addr_idx 144 /// The DW_OP_addr index to retrieve in case there is more than 145 /// one DW_OP_addr opcode in the location byte stream. 146 /// 147 /// @param[out] error 148 /// If the location stream contains unknown DW_OP opcodes or the 149 /// data is missing, \a error will be set to \b true. 150 /// 151 /// @return 152 /// LLDB_INVALID_ADDRESS if the location doesn't contain a 153 /// DW_OP_addr for \a op_addr_idx, otherwise a valid file address 154 //------------------------------------------------------------------ 155 lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const; 156 157 bool Update_DW_OP_addr(lldb::addr_t file_addr); 158 SetModule(const lldb::ModuleSP & module)159 void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } 160 161 bool ContainsThreadLocalStorage() const; 162 163 bool LinkThreadLocalStorage( 164 lldb::ModuleSP new_module_sp, 165 std::function<lldb::addr_t(lldb::addr_t file_addr)> const 166 &link_address_callback); 167 168 //------------------------------------------------------------------ 169 /// Make the expression parser read its location information from a given 170 /// data source. Does not change the offset and length 171 /// 172 /// @param[in] data 173 /// A data extractor configured to read the DWARF location expression's 174 /// bytecode. 175 //------------------------------------------------------------------ 176 void SetOpcodeData(const DataExtractor &data); 177 178 //------------------------------------------------------------------ 179 /// Make the expression parser read its location information from a given 180 /// data source 181 /// 182 /// @param[in] module_sp 183 /// The module that defines the DWARF expression. 184 /// 185 /// @param[in] data 186 /// A data extractor configured to read the DWARF location expression's 187 /// bytecode. 188 /// 189 /// @param[in] data_offset 190 /// The offset of the location expression in the extractor. 191 /// 192 /// @param[in] data_length 193 /// The byte length of the location expression. 194 //------------------------------------------------------------------ 195 void SetOpcodeData(lldb::ModuleSP module_sp, const DataExtractor &data, 196 lldb::offset_t data_offset, lldb::offset_t data_length); 197 198 //------------------------------------------------------------------ 199 /// Copy the DWARF location expression into a local buffer. 200 /// 201 /// It is a good idea to copy the data so we don't keep the entire object 202 /// file worth of data around just for a few bytes of location expression. 203 /// LLDB typically will mmap the entire contents of debug information files, 204 /// and if we use SetOpcodeData, it will get a shared reference to all of 205 /// this data for the and cause the object file to have to stay around. Even 206 /// worse, a very very large ".a" that contains one or more .o files could 207 /// end up being referenced. Location lists are typically small so even 208 /// though we are copying the data, it shouldn't amount to that much for the 209 /// variables we end up parsing. 210 /// 211 /// @param[in] module_sp 212 /// The module that defines the DWARF expression. 213 /// 214 /// @param[in] data 215 /// A data extractor configured to read and copy the DWARF 216 /// location expression's bytecode. 217 /// 218 /// @param[in] data_offset 219 /// The offset of the location expression in the extractor. 220 /// 221 /// @param[in] data_length 222 /// The byte length of the location expression. 223 //------------------------------------------------------------------ 224 void CopyOpcodeData(lldb::ModuleSP module_sp, const DataExtractor &data, 225 lldb::offset_t data_offset, lldb::offset_t data_length); 226 227 void CopyOpcodeData(const void *data, lldb::offset_t data_length, 228 lldb::ByteOrder byte_order, uint8_t addr_byte_size); 229 230 void CopyOpcodeData(uint64_t const_value, 231 lldb::offset_t const_value_byte_size, 232 uint8_t addr_byte_size); 233 234 //------------------------------------------------------------------ 235 /// Tells the expression that it refers to a location list. 236 /// 237 /// @param[in] slide 238 /// This value should be a slide that is applied to any values 239 /// in the location list data so the values become zero based 240 /// offsets into the object that owns the location list. We need 241 /// to make location lists relative to the objects that own them 242 /// so we can relink addresses on the fly. 243 //------------------------------------------------------------------ 244 void SetLocationListSlide(lldb::addr_t slide); 245 246 //------------------------------------------------------------------ 247 /// Return the call-frame-info style register kind 248 //------------------------------------------------------------------ 249 int GetRegisterKind(); 250 251 //------------------------------------------------------------------ 252 /// Set the call-frame-info style register kind 253 /// 254 /// @param[in] reg_kind 255 /// The register kind. 256 //------------------------------------------------------------------ 257 void SetRegisterKind(lldb::RegisterKind reg_kind); 258 259 //------------------------------------------------------------------ 260 /// Wrapper for the static evaluate function that accepts an 261 /// ExecutionContextScope instead of an ExecutionContext and uses member 262 /// variables to populate many operands 263 //------------------------------------------------------------------ 264 bool Evaluate(ExecutionContextScope *exe_scope, 265 lldb::addr_t loclist_base_load_addr, 266 const Value *initial_value_ptr, const Value *object_address_ptr, 267 Value &result, Status *error_ptr) const; 268 269 //------------------------------------------------------------------ 270 /// Wrapper for the static evaluate function that uses member variables to 271 /// populate many operands 272 //------------------------------------------------------------------ 273 bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, 274 lldb::addr_t loclist_base_load_addr, 275 const Value *initial_value_ptr, const Value *object_address_ptr, 276 Value &result, Status *error_ptr) const; 277 278 //------------------------------------------------------------------ 279 /// Evaluate a DWARF location expression in a particular context 280 /// 281 /// @param[in] exe_ctx 282 /// The execution context in which to evaluate the location 283 /// expression. The location expression may access the target's 284 /// memory, especially if it comes from the expression parser. 285 /// 286 /// @param[in] opcode_ctx 287 /// The module which defined the expression. 288 /// 289 /// @param[in] opcodes 290 /// This is a static method so the opcodes need to be provided 291 /// explicitly. 292 /// 293 /// @param[in] expr_locals 294 /// If the location expression was produced by the expression parser, 295 /// the list of local variables referenced by the DWARF expression. 296 /// This list should already have been populated during parsing; 297 /// the DWARF expression refers to variables by index. Can be NULL if 298 /// the location expression uses no locals. 299 /// 300 /// @param[in] decl_map 301 /// If the location expression was produced by the expression parser, 302 /// the list of external variables referenced by the location 303 /// expression. Can be NULL if the location expression uses no 304 /// external variables. 305 /// 306 /// @param[in] reg_ctx 307 /// An optional parameter which provides a RegisterContext for use 308 /// when evaluating the expression (i.e. for fetching register values). 309 /// Normally this will come from the ExecutionContext's StackFrame but 310 /// in the case where an expression needs to be evaluated while building 311 /// the stack frame list, this short-cut is available. 312 /// 313 /// @param[in] offset 314 /// The offset of the location expression in the data extractor. 315 /// 316 /// @param[in] length 317 /// The length in bytes of the location expression. 318 /// 319 /// @param[in] reg_set 320 /// The call-frame-info style register kind. 321 /// 322 /// @param[in] initial_value_ptr 323 /// A value to put on top of the interpreter stack before evaluating 324 /// the expression, if the expression is parametrized. Can be NULL. 325 /// 326 /// @param[in] result 327 /// A value into which the result of evaluating the expression is 328 /// to be placed. 329 /// 330 /// @param[in] error_ptr 331 /// If non-NULL, used to report errors in expression evaluation. 332 /// 333 /// @return 334 /// True on success; false otherwise. If error_ptr is non-NULL, 335 /// details of the failure are provided through it. 336 //------------------------------------------------------------------ 337 static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, 338 lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes, 339 DWARFUnit *dwarf_cu, const lldb::offset_t offset, 340 const lldb::offset_t length, 341 const lldb::RegisterKind reg_set, 342 const Value *initial_value_ptr, 343 const Value *object_address_ptr, Value &result, 344 Status *error_ptr); 345 GetExpressionData(DataExtractor & data)346 bool GetExpressionData(DataExtractor &data) const { 347 data = m_data; 348 return data.GetByteSize() > 0; 349 } 350 351 bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level, 352 lldb::addr_t loclist_base_load_addr, 353 lldb::addr_t address, ABI *abi); 354 355 static size_t LocationListSize(const DWARFUnit *dwarf_cu, 356 const DataExtractor &debug_loc_data, 357 lldb::offset_t offset); 358 359 static bool PrintDWARFExpression(Stream &s, const DataExtractor &data, 360 int address_size, int dwarf_ref_size, 361 bool location_expression); 362 363 static void PrintDWARFLocationList(Stream &s, const DWARFUnit *cu, 364 const DataExtractor &debug_loc_data, 365 lldb::offset_t offset); 366 367 bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); 368 369 protected: 370 //------------------------------------------------------------------ 371 /// Pretty-prints the location expression to a stream 372 /// 373 /// @param[in] stream 374 /// The stream to use for pretty-printing. 375 /// 376 /// @param[in] offset 377 /// The offset into the data buffer of the opcodes to be printed. 378 /// 379 /// @param[in] length 380 /// The length in bytes of the opcodes to be printed. 381 /// 382 /// @param[in] level 383 /// The level of detail to use in pretty-printing. 384 /// 385 /// @param[in] abi 386 /// An optional ABI plug-in that can be used to resolve register 387 /// names. 388 //------------------------------------------------------------------ 389 void DumpLocation(Stream *s, lldb::offset_t offset, lldb::offset_t length, 390 lldb::DescriptionLevel level, ABI *abi) const; 391 392 bool GetLocation(lldb::addr_t base_addr, lldb::addr_t pc, 393 lldb::offset_t &offset, lldb::offset_t &len); 394 395 static bool AddressRangeForLocationListEntry( 396 const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data, 397 lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc); 398 399 bool GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset, 400 lldb::offset_t &end_offset); 401 402 //------------------------------------------------------------------ 403 /// Classes that inherit from DWARFExpression can see and modify these 404 //------------------------------------------------------------------ 405 406 lldb::ModuleWP m_module_wp; ///< Module which defined this expression. 407 DataExtractor m_data; ///< A data extractor capable of reading opcode bytes 408 DWARFUnit *m_dwarf_cu; ///< The DWARF compile unit this expression 409 ///belongs to. It is used 410 ///< to evaluate values indexing into the .debug_addr section (e.g. 411 ///< DW_OP_GNU_addr_index, DW_OP_GNU_const_index) 412 lldb::RegisterKind 413 m_reg_kind; ///< One of the defines that starts with LLDB_REGKIND_ 414 lldb::addr_t m_loclist_slide; ///< A value used to slide the location list 415 ///offsets so that 416 ///< they are relative to the object that owns the location list 417 ///< (the function for frame base and variable location lists) 418 }; 419 420 } // namespace lldb_private 421 422 #endif // liblldb_DWARFExpression_h_ 423