diff options
| author | Greg Clayton <gclayton@apple.com> | 2011-05-19 00:17:26 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2011-05-19 00:17:26 +0000 |
| commit | e376938e93baa6bc0617efdc146526b660fccbbc (patch) | |
| tree | 6197bedcf07376b1eeead983124523531e7747bc /lldb | |
| parent | 3015a54813ee121eda7525fb4ab6bcc056ba63b1 (diff) | |
| download | bcm5719-llvm-e376938e93baa6bc0617efdc146526b660fccbbc.tar.gz bcm5719-llvm-e376938e93baa6bc0617efdc146526b660fccbbc.zip | |
Added the ability to sign extend a Scalar at any bit position for integer
types.
Added the abilty to set a RegisterValue type via accessor and enum.
Added the ability to read arguments for a function for ARM if you are on the
first instruction in ABIMacOSX_arm.
Fixed an issue where a file descriptor becoming invalid could cause an
inifnite loop spin in the libedit thread.
llvm-svn: 131610
Diffstat (limited to 'lldb')
| -rw-r--r-- | lldb/include/lldb/Core/RegisterValue.h | 6 | ||||
| -rw-r--r-- | lldb/include/lldb/Core/Scalar.h | 3 | ||||
| -rw-r--r-- | lldb/source/Core/ConnectionFileDescriptor.cpp | 4 | ||||
| -rw-r--r-- | lldb/source/Core/Scalar.cpp | 68 | ||||
| -rw-r--r-- | lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 259 |
5 files changed, 188 insertions, 152 deletions
diff --git a/lldb/include/lldb/Core/RegisterValue.h b/lldb/include/lldb/Core/RegisterValue.h index d84e4e058ed..0a0c4fcd09e 100644 --- a/lldb/include/lldb/Core/RegisterValue.h +++ b/lldb/include/lldb/Core/RegisterValue.h @@ -123,6 +123,12 @@ namespace lldb_private { bool CopyValue (const RegisterValue &rhs); + void + SetType (RegisterValue::Type type) + { + m_type = type; + } + RegisterValue::Type SetType (const RegisterInfo *reg_info); diff --git a/lldb/include/lldb/Core/Scalar.h b/lldb/include/lldb/Core/Scalar.h index c5105e8f117..3c22ce04379 100644 --- a/lldb/include/lldb/Core/Scalar.h +++ b/lldb/include/lldb/Core/Scalar.h @@ -54,6 +54,9 @@ public: //Scalar(const RegisterValue& reg_value); virtual ~Scalar(); + bool + SignExtend (uint32_t bit_pos); + size_t GetByteSize() const; diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index 2a9b16b7d63..80deb09fe59 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -229,7 +229,6 @@ ConnectionFileDescriptor::Read (void *dst, size_t dst_len, ConnectionStatus &sta status = eConnectionStatusSuccess; return 0; - case EBADF: // fildes is not a valid file or socket descriptor open for reading. case EFAULT: // Buf points outside the allocated address space. case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. case EINVAL: // The pointer associated with fildes was negative. @@ -246,6 +245,7 @@ ConnectionFileDescriptor::Read (void *dst, size_t dst_len, ConnectionStatus &sta status = eConnectionStatusError; break; // Break to close.... + case EBADF: // fildes is not a valid file or socket descriptor open for reading. case ENXIO: // An action is requested of a device that does not exist.. // A requested action cannot be performed by the device. case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket. @@ -391,6 +391,8 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt switch (error.GetError()) { case EBADF: // One of the descriptor sets specified an invalid descriptor. + return eConnectionStatusLostConnection; + case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. default: // Other unknown error return eConnectionStatusError; diff --git a/lldb/source/Core/Scalar.cpp b/lldb/source/Core/Scalar.cpp index 24e427c40d2..c32c33c1547 100644 --- a/lldb/source/Core/Scalar.cpp +++ b/lldb/source/Core/Scalar.cpp @@ -1922,6 +1922,74 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, uint32_t } bool +Scalar::SignExtend (uint32_t sign_bit_pos) +{ + const uint32_t max_bit_pos = GetByteSize() * 8; + + if (sign_bit_pos < max_bit_pos) + { + switch (m_type) + { + default: + case Scalar::e_void: + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + return false; + + case Scalar::e_sint: + case Scalar::e_uint: + if (max_bit_pos == sign_bit_pos) + return true; + else if (sign_bit_pos < (max_bit_pos-1)) + { + unsigned int sign_bit = 1u << sign_bit_pos; + if (m_data.uint & sign_bit) + { + const unsigned int mask = ~(sign_bit) + 1u; + m_data.uint |= mask; + } + return true; + } + break; + + case Scalar::e_slong: + case Scalar::e_ulong: + if (max_bit_pos == sign_bit_pos) + return true; + else if (sign_bit_pos < (max_bit_pos-1)) + { + unsigned long sign_bit = 1ul << sign_bit_pos; + if (m_data.uint & sign_bit) + { + const unsigned long mask = ~(sign_bit) + 1ul; + m_data.uint |= mask; + } + return true; + } + break; + + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + if (max_bit_pos == sign_bit_pos) + return true; + else if (sign_bit_pos < (max_bit_pos-1)) + { + unsigned long long sign_bit = 1ull << sign_bit_pos; + if (m_data.uint & sign_bit) + { + const unsigned long long mask = ~(sign_bit) + 1ull; + m_data.uint |= mask; + } + return true; + } + break; + } + } + return false; +} + +bool lldb_private::operator== (const Scalar& lhs, const Scalar& rhs) { // If either entry is void then we can just compare the types diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index b8ac50171da..212f06a0f31 100644 --- a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -175,161 +175,118 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, return true; } - -static bool -ReadIntegerArgument (Scalar &scalar, - unsigned int bit_width, - bool is_signed, - Process &process, - addr_t ¤t_stack_argument) -{ -// if (bit_width > 64) -// return false; // Scalar can't hold large integer arguments -// -// uint64_t arg_contents; -// uint32_t read_data; -// Error error; -// -// if (bit_width > 32) -// { -// if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data)) -// return false; -// -// arg_contents = read_data; -// -// if (process.ReadMemory(current_stack_argument + 4, &read_data, sizeof(read_data), error) != sizeof(read_data)) -// return false; -// -// arg_contents |= ((uint64_t)read_data) << 32; -// -// current_stack_argument += 8; -// } -// else { -// if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data)) -// return false; -// -// arg_contents = read_data; -// -// current_stack_argument += 4; -// } -// -// if (is_signed) -// { -// switch (bit_width) -// { -// default: -// return false; -// case 8: -// scalar = (int8_t)(arg_contents & 0xff); -// break; -// case 16: -// scalar = (int16_t)(arg_contents & 0xffff); -// break; -// case 32: -// scalar = (int32_t)(arg_contents & 0xffffffff); -// break; -// case 64: -// scalar = (int64_t)arg_contents; -// break; -// } -// } -// else -// { -// switch (bit_width) -// { -// default: -// return false; -// case 8: -// scalar = (uint8_t)(arg_contents & 0xff); -// break; -// case 16: -// scalar = (uint16_t)(arg_contents & 0xffff); -// break; -// case 32: -// scalar = (uint32_t)(arg_contents & 0xffffffff); -// break; -// case 64: -// scalar = (uint64_t)arg_contents; -// break; -// } -// } -// -// return true; - return false; -} - bool ABIMacOSX_arm::GetArgumentValues (Thread &thread, ValueList &values) const { -// unsigned int num_values = values.GetSize(); -// unsigned int value_index; -// -// // Extract the Clang AST context from the PC so that we can figure out type -// // sizes -// -// clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext(); -// -// // Get the pointer to the first stack argument so we have a place to start -// // when reading data -// -// RegisterContext *reg_ctx = thread.GetRegisterContext().get(); -// -// if (!reg_ctx) -// return false; -// -// addr_t sp = reg_ctx->GetSP(0); -// -// if (!sp) -// return false; -// -// addr_t current_stack_argument = sp + 4; // jump over return address -// -// for (value_index = 0; -// value_index < num_values; -// ++value_index) -// { -// Value *value = values.GetValueAtIndex(value_index); -// -// if (!value) -// return false; -// -// // We currently only support extracting values with Clang QualTypes. -// // Do we care about others? -// switch (value->GetContextType()) -// { -// default: -// return false; -// case Value::eContextTypeClangType: -// { -// void *value_type = value->GetClangType(); -// bool is_signed; -// -// if (ClangASTContext::IsIntegerType (value_type, is_signed)) -// { -// size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); -// -// ReadIntegerArgument(value->GetScalar(), -// bit_width, -// is_signed, -// thread.GetProcess(), -// current_stack_argument); -// } -// else if (ClangASTContext::IsPointerType (value_type)) -// { -// ReadIntegerArgument(value->GetScalar(), -// 32, -// false, -// thread.GetProcess(), -// current_stack_argument); -// } -// } -// break; -// } -// } -// -// return true; - return false; + uint32_t num_values = values.GetSize(); + + + // For now, assume that the types in the AST values come from the Target's + // scratch AST. + + clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext(); + + // Extract the register context so we can read arguments from registers + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + + if (!reg_ctx) + return false; + + bool arg_regs_exceeded = false; + + addr_t sp = reg_ctx->GetSP(0); + + if (!sp) + return false; + + for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) + { + // We currently only support extracting values with Clang QualTypes. + // Do we care about others? + Value *value = values.GetValueAtIndex(value_idx); + + if (!value) + return false; + + void *value_type = value->GetClangType(); + if (value_type) + { + bool is_signed = false; + size_t bit_width = 0; + if (ClangASTContext::IsIntegerType (value_type, is_signed)) + { + bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); + } + else if (ClangASTContext::IsPointerOrReferenceType (value_type)) + { + bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); + } + else + { + // We only handle integer, pointer and reference types currently... + return false; + } + + if (bit_width <= (thread.GetProcess().GetAddressByteSize() * 8)) + { + if (!arg_regs_exceeded) + { + uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); + if (arg_reg_num == LLDB_INVALID_REGNUM) + { + arg_regs_exceeded = true; + } + else + { + const RegisterInfo *arg_reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num); + RegisterValue reg_value; + + if (reg_ctx->ReadRegister(arg_reg_info, reg_value)) + { + if (is_signed) + reg_value.SignExtend(bit_width); + if (!reg_value.GetScalarValue(value->GetScalar())) + return false; + continue; + } + else + { + return false; + } + } + } + + + const uint32_t arg_byte_size = (bit_width + (8-1)) / 8; + if (arg_byte_size <= sizeof(uint64_t)) + { + uint8_t arg_data[sizeof(uint64_t)]; + Error error; + thread.GetProcess().ReadMemory(sp, arg_data, sizeof(arg_data), error); + DataExtractor arg_data_extractor (arg_data, sizeof(arg_data), + thread.GetProcess().GetTarget().GetArchitecture().GetByteOrder(), + thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize()); + uint32_t offset = 0; + if (arg_byte_size <= 4) + value->GetScalar() = arg_data_extractor.GetMaxU32 (&offset, arg_byte_size); + else if (arg_byte_size <= 8) + value->GetScalar() = arg_data_extractor.GetMaxU64 (&offset, arg_byte_size); + else + return false; + + if (offset == 0 || offset == UINT32_MAX) + return false; + + if (is_signed) + value->GetScalar().SignExtend (bit_width); + sp += arg_byte_size; + } + } + } + } + return true; } bool |

