diff options
Diffstat (limited to 'source/Expression/DWARFExpression.cpp')
| -rw-r--r-- | source/Expression/DWARFExpression.cpp | 165 | 
1 files changed, 152 insertions, 13 deletions
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index ebcc28460395..b81d60e9b065 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -1003,7 +1003,128 @@ DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr)  }  bool -DWARFExpression::LocationListContainsAddress (lldb::addr_t loclist_base_addr, lldb::addr_t addr) const +DWARFExpression::ContainsThreadLocalStorage() const +{ +    // We are assuming for now that any thread local variable will not +    // have a location list. This has been true for all thread local +    // variables we have seen so far produced by any compiler. +    if (IsLocationList()) +        return false; +    lldb::offset_t offset = 0; +    while (m_data.ValidOffset(offset)) +    { +        const uint8_t op = m_data.GetU8(&offset); + +        if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) +            return true; +        const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); +        if (op_arg_size == LLDB_INVALID_OFFSET) +            return false; +        else +            offset += op_arg_size; +    } +    return false; +} +bool +DWARFExpression::LinkThreadLocalStorage( +    lldb::ModuleSP new_module_sp, std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback) +{ +    // We are assuming for now that any thread local variable will not +    // have a location list. This has been true for all thread local +    // variables we have seen so far produced by any compiler. +    if (IsLocationList()) +        return false; + +    const uint32_t addr_byte_size = m_data.GetAddressByteSize(); +    // We have to make a copy of the data as we don't know if this +    // data is from a read only memory mapped buffer, so we duplicate +    // all of the data first, then modify it, and if all goes well, +    // we then replace the data for this expression + +    // So first we copy the data into a heap buffer +    std::shared_ptr<DataBufferHeap> heap_data_sp(new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); + +    // Make en encoder so we can write the address into the buffer using +    // the correct byte order (endianness) +    DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), m_data.GetByteOrder(), addr_byte_size); + +    lldb::offset_t offset = 0; +    lldb::offset_t const_offset = 0; +    lldb::addr_t const_value = 0; +    size_t const_byte_size = 0; +    while (m_data.ValidOffset(offset)) +    { +        const uint8_t op = m_data.GetU8(&offset); + +        bool decoded_data = false; +        switch (op) +        { +            case DW_OP_const4u: +                // Remember the const offset in case we later have a DW_OP_form_tls_address +                // or DW_OP_GNU_push_tls_address +                const_offset = offset; +                const_value = m_data.GetU32(&offset); +                decoded_data = true; +                const_byte_size = 4; +                break; + +            case DW_OP_const8u: +                // Remember the const offset in case we later have a DW_OP_form_tls_address +                // or DW_OP_GNU_push_tls_address +                const_offset = offset; +                const_value = m_data.GetU64(&offset); +                decoded_data = true; +                const_byte_size = 8; +                break; + +            case DW_OP_form_tls_address: +            case DW_OP_GNU_push_tls_address: +                // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded by +                // a file address on the stack. We assume that DW_OP_const4u or DW_OP_const8u +                // is used for these values, and we check that the last opcode we got before +                // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can link +                // the value accodingly. For Darwin, the value in the DW_OP_const4u or +                // DW_OP_const8u is the file address of a structure that contains a function +                // pointer, the pthread key and the offset into the data pointed to by the +                // pthread key. So we must link this address and also set the module of this +                // expression to the new_module_sp so we can resolve the file address correctly +                if (const_byte_size > 0) +                { +                    lldb::addr_t linked_file_addr = link_address_callback(const_value); +                    if (linked_file_addr == LLDB_INVALID_ADDRESS) +                        return false; +                    // Replace the address in the new buffer +                    if (encoder.PutMaxU64(const_offset, const_byte_size, linked_file_addr) == UINT32_MAX) +                        return false; +                } +                break; + +            default: +                const_offset = 0; +                const_value = 0; +                const_byte_size = 0; +                break; +        } + +        if (!decoded_data) +        { +            const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); +            if (op_arg_size == LLDB_INVALID_OFFSET) +                return false; +            else +                offset += op_arg_size; +        } +    } + +    // If we linked the TLS address correctly, update the module so that when the expression +    // is evaluated it can resolve the file address to a load address and read the TLS data +    m_module_wp = new_module_sp; +    m_data.SetData(heap_data_sp); +    return true; +} + +bool +DWARFExpression::LocationListContainsAddress(lldb::addr_t loclist_base_addr, lldb::addr_t addr) const  {      if (addr == LLDB_INVALID_ADDRESS)          return false; @@ -1108,12 +1229,21 @@ DWARFExpression::Evaluate      ClangExpressionDeclMap *decl_map,      lldb::addr_t loclist_base_load_addr,      const Value* initial_value_ptr, +    const Value* object_address_ptr,      Value& result,      Error *error_ptr  ) const  {      ExecutionContext exe_ctx (exe_scope); -    return Evaluate(&exe_ctx, expr_locals, decl_map, NULL, loclist_base_load_addr, initial_value_ptr, result, error_ptr); +    return Evaluate(&exe_ctx, +                    expr_locals, +                    decl_map, +                    nullptr, +                    loclist_base_load_addr, +                    initial_value_ptr, +                    object_address_ptr, +                    result, +                    error_ptr);  }  bool @@ -1125,6 +1255,7 @@ DWARFExpression::Evaluate      RegisterContext *reg_ctx,      lldb::addr_t loclist_base_load_addr,      const Value* initial_value_ptr, +    const Value* object_address_ptr,      Value& result,      Error *error_ptr  ) const @@ -1189,6 +1320,7 @@ DWARFExpression::Evaluate                                                        length,                                                        m_reg_kind,                                                        initial_value_ptr, +                                                      object_address_ptr,                                                        result,                                                        error_ptr);                  } @@ -1212,6 +1344,7 @@ DWARFExpression::Evaluate                                        m_data.GetByteSize(),                                        m_reg_kind,                                        initial_value_ptr, +                                      object_address_ptr,                                        result,                                        error_ptr);  } @@ -1232,6 +1365,7 @@ DWARFExpression::Evaluate      const lldb::offset_t opcodes_length,      const lldb::RegisterKind reg_kind,      const Value* initial_value_ptr, +    const Value* object_address_ptr,      Value& result,      Error *error_ptr  ) @@ -1931,7 +2065,7 @@ DWARFExpression::Evaluate              {                  tmp = stack.back();                  stack.pop_back(); -                stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) + tmp.ResolveValue(exe_ctx); +                stack.back().GetScalar() += tmp.GetScalar();              }              break; @@ -1952,8 +2086,8 @@ DWARFExpression::Evaluate              {                  const uint64_t uconst_value = opcodes.GetULEB128(&offset);                  // Implicit conversion from a UINT to a Scalar... -                stack.back().ResolveValue(exe_ctx) += uconst_value; -                if (!stack.back().ResolveValue(exe_ctx).IsValid()) +                stack.back().GetScalar() += uconst_value; +                if (!stack.back().GetScalar().IsValid())                  {                      if (error_ptr)                          error_ptr->SetErrorString("DW_OP_plus_uconst failed."); @@ -2689,9 +2823,15 @@ DWARFExpression::Evaluate          // during user expression evaluation.          //----------------------------------------------------------------------          case DW_OP_push_object_address: -            if (error_ptr) -                error_ptr->SetErrorString ("Unimplemented opcode DW_OP_push_object_address."); -            return false; +            if (object_address_ptr) +                stack.push_back(*object_address_ptr); +            else +            { +                if (error_ptr) +                    error_ptr->SetErrorString ("DW_OP_push_object_address used without specifying an object address"); +                return false; +            } +            break;          //----------------------------------------------------------------------          // OPCODE: DW_OP_call2 @@ -2826,18 +2966,17 @@ DWARFExpression::Evaluate                  }                  // Lookup the TLS block address for this thread and module. -                addr_t tls_addr = thread->GetThreadLocalData (module_sp); +                const addr_t tls_file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); +                const addr_t tls_load_addr = thread->GetThreadLocalData(module_sp, tls_file_addr); -                if (tls_addr == LLDB_INVALID_ADDRESS) +                if (tls_load_addr == LLDB_INVALID_ADDRESS)                  {                      if (error_ptr)                          error_ptr->SetErrorString ("No TLS data currently exists for this thread.");                      return false;                  } -                // Convert the TLS offset into the absolute address. -                Scalar tmp = stack.back().ResolveValue(exe_ctx); -                stack.back() = tmp + tls_addr; +                stack.back().GetScalar() = tls_load_addr;                  stack.back().SetValueType (Value::eValueTypeLoadAddress);              }              break;  | 
