From 496970f6eec7697dbda6d02fc4f8dc595a24145f Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Tue, 11 Dec 2012 22:39:36 +0000 Subject: [PATCH] Fixed the IRInterpreter's handling of "this" and "self" when those pointers are in registers. Previously in this case the IRInterpreter would handle them just as if the user had typed in "$rdi", which isn't safe because $rdi is passed in through the argument struct. Now we correctly break out all three cases (i.e., normal variables in registers, $reg, and this/self), and handle them in a way that's a little bit easier to read and change. This results in more accurate printing of "this" and "self" pointers all around. I have strengthened the optimized-code test case for Objective-C to ensure that we catch regressions in this area reliably in the future. llvm-svn: 169924 --- lldb/source/Expression/IRInterpreter.cpp | 160 ++++++++++++++------- .../lang/objc/objc-optimized/TestObjcOptimized.py | 18 ++- 2 files changed, 122 insertions(+), 56 deletions(-) diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index b812875..626e270 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -619,7 +619,7 @@ public: // array then we need to build an extra level of indirection // for it. This is the default; only magic arguments like // "this", "self", and "_cmd" are direct. - bool indirect_variable = true; + bool variable_is_this = false; // Attempt to resolve the value using the program's data. // If it is, the values to be created are: @@ -664,69 +664,121 @@ public: name_str == "_cmd") resolved_value = m_decl_map.GetSpecialValue(lldb_private::ConstString(name_str.c_str())); - indirect_variable = false; + variable_is_this = true; } if (resolved_value.GetScalar().GetType() != lldb_private::Scalar::e_void) { if (resolved_value.GetContextType() == lldb_private::Value::eContextTypeRegisterInfo) { - bool bare_register = (flags & lldb_private::ClangExpressionVariable::EVBareRegister); - - if (bare_register) - indirect_variable = false; - - lldb_private::RegisterInfo *reg_info = resolved_value.GetRegisterInfo(); - Memory::Region data_region = (reg_info->encoding == lldb::eEncodingVector) ? + if (variable_is_this) + { + Memory::Region data_region = m_memory.Place(value->getType(), resolved_value.GetScalar().ULongLong(), resolved_value); + + lldb_private::Value origin; + + origin.SetValueType(lldb_private::Value::eValueTypeLoadAddress); + origin.SetContext(lldb_private::Value::eContextTypeInvalid, NULL); + origin.GetScalar() = resolved_value.GetScalar(); + + data_region.m_allocation->m_origin = origin; + + Memory::Region ref_region = m_memory.Malloc(value->getType()); + + if (ref_region.IsInvalid()) + return Memory::Region(); + + DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region); + + if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX) + return Memory::Region(); + + if (log) + { + log->Printf("Made an allocation for \"this\" register variable %s", PrintValue(value).c_str()); + log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base); + log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base); + } + + m_values[value] = ref_region; + return ref_region; + } + else if (flags & lldb_private::ClangExpressionVariable::EVBareRegister) + { + lldb_private::RegisterInfo *reg_info = resolved_value.GetRegisterInfo(); + Memory::Region data_region = (reg_info->encoding == lldb::eEncodingVector) ? m_memory.Malloc(reg_info->byte_size, m_target_data.getPrefTypeAlignment(value->getType())) : m_memory.Malloc(value->getType()); - - data_region.m_allocation->m_origin = resolved_value; - Memory::Region ref_region = m_memory.Malloc(value->getType()); - Memory::Region pointer_region; - - if (indirect_variable) + + data_region.m_allocation->m_origin = resolved_value; + Memory::Region ref_region = m_memory.Malloc(value->getType()); + + if (!Cache(data_region.m_allocation, value->getType())) + return Memory::Region(); + + if (ref_region.IsInvalid()) + return Memory::Region(); + + DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region); + + if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX) + return Memory::Region(); + + if (log) + { + log->Printf("Made an allocation for bare register variable %s", PrintValue(value).c_str()); + log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str()); + log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base); + log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base); + } + + m_values[value] = ref_region; + return ref_region; + } + else + { + lldb_private::RegisterInfo *reg_info = resolved_value.GetRegisterInfo(); + Memory::Region data_region = (reg_info->encoding == lldb::eEncodingVector) ? + m_memory.Malloc(reg_info->byte_size, m_target_data.getPrefTypeAlignment(value->getType())) : + m_memory.Malloc(value->getType()); + + data_region.m_allocation->m_origin = resolved_value; + Memory::Region ref_region = m_memory.Malloc(value->getType()); + Memory::Region pointer_region; + pointer_region = m_memory.Malloc(value->getType()); - - if (!Cache(data_region.m_allocation, value->getType())) - return Memory::Region(); - - if (ref_region.IsInvalid()) - return Memory::Region(); - - if (pointer_region.IsInvalid() && indirect_variable) - return Memory::Region(); - - DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region); - - if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX) - return Memory::Region(); - - if (log) - { - log->Printf("Made an allocation for register variable %s", PrintValue(value).c_str()); - log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str()); - log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base); - log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base); - if (indirect_variable) + + if (!Cache(data_region.m_allocation, value->getType())) + return Memory::Region(); + + if (ref_region.IsInvalid()) + return Memory::Region(); + + if (pointer_region.IsInvalid()) + return Memory::Region(); + + DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region); + + if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX) + return Memory::Region(); + + if (log) + { + log->Printf("Made an allocation for ordinary register variable %s", PrintValue(value).c_str()); + log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str()); + log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base); + log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base); log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base); - } - - if (indirect_variable) - { - DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region); + } + DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region); + if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX) return Memory::Region(); m_values[value] = pointer_region; return pointer_region; } - else - { - m_values[value] = ref_region; - return ref_region; - } } else { @@ -734,13 +786,13 @@ public: Memory::Region ref_region = m_memory.Malloc(value->getType()); Memory::Region pointer_region; - if (indirect_variable) + if (!variable_is_this) pointer_region = m_memory.Malloc(value->getType()); if (ref_region.IsInvalid()) return Memory::Region(); - if (pointer_region.IsInvalid() && indirect_variable) + if (pointer_region.IsInvalid() && !variable_is_this) return Memory::Region(); DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region); @@ -748,7 +800,7 @@ public: if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX) return Memory::Region(); - if (indirect_variable) + if (!variable_is_this) { DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region); @@ -764,14 +816,14 @@ public: log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str()); log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base); log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base); - if (indirect_variable) + if (!variable_is_this) log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base); } - if (indirect_variable) - return pointer_region; - else + if (variable_is_this) return ref_region; + else + return pointer_region; } } } diff --git a/lldb/test/lang/objc/objc-optimized/TestObjcOptimized.py b/lldb/test/lang/objc/objc-optimized/TestObjcOptimized.py index 59d1f4e..a7a9d23 100644 --- a/lldb/test/lang/objc/objc-optimized/TestObjcOptimized.py +++ b/lldb/test/lang/objc/objc-optimized/TestObjcOptimized.py @@ -12,6 +12,7 @@ import unittest2 import lldb from lldbtest import * import lldbutil +import re # rdar://problem/9087739 # test failure: objc_optimized does not work for "-C clang -A i386" @@ -50,8 +51,21 @@ class ObjcOptimizedTestCase(TestBase): self.expect('expression member', startstr = "(int) $0 = 5") - self.expect('expression self', - startstr = "(%s *) $1 = " % self.myclass) + # + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interp.HandleCommand('frame variable self', result) + output = result.GetOutput() + + desired_pointer = "0x0" + + mo = re.search("0x[0-9a-f]+", output) + + if mo: + desired_pointer = mo.group(0) + + self.expect('expression (self)', + substrs = [("(%s *) $1 = " % self.myclass), desired_pointer]) self.expect('expression self->non_member', error=True, substrs = ["does not have a member named 'non_member'"]) -- 2.7.4