bool ABIMacOSX_i386::GetArgumentValues (Thread &thread, ValueList &values) const { unsigned int num_values = values.GetSize(); unsigned int value_index; // 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? CompilerType compiler_type (value->GetCompilerType()); if (compiler_type) { bool is_signed; if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), is_signed, thread.GetProcess().get(), current_stack_argument); } else if (compiler_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), false, thread.GetProcess().get(), current_stack_argument); } } } return true; }
bool ABINyuzi::GetArgumentValues ( Thread &thread, ValueList &values ) const { printf("ABINyuzi::GetArgumentValues %d\n", values.GetSize()); assert(0); return false; }
bool ABISysV_i386::GetArgumentValues (Thread &thread, ValueList &values) const { unsigned int num_values = values.GetSize(); unsigned int value_index; RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; // Get pointer to the first stack argument 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; // Currently: Support for extracting values with Clang QualTypes only. CompilerType clang_type (value->GetCompilerType()); if (clang_type) { bool is_signed; if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), clang_type.GetBitSize(&thread), is_signed, thread.GetProcess().get(), current_stack_argument); } else if (clang_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), clang_type.GetBitSize(&thread), false, thread.GetProcess().get(), current_stack_argument); } } } return true; }
bool ABIMacOSX_arm::GetArgumentValues (Thread &thread, ValueList &values) const { uint32_t num_values = values.GetSize(); ExecutionContext exe_ctx (thread.shared_from_this()); // For now, assume that the types in the AST values come from the Target's // scratch AST. clang::ASTContext *ast_context = exe_ctx.GetTargetRef().GetScratchClangASTContext()->getASTContext(); // Extract the register context so we can read arguments from registers RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return 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 <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) { if (value_idx < 4) { // Arguments 1-4 are in r0-r3... const RegisterInfo *arg_reg_info = NULL; // Search by generic ID first, then fall back to by name uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (arg_reg_num != LLDB_INVALID_REGNUM) { arg_reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num); } else { switch (value_idx) { case 0: arg_reg_info = reg_ctx->GetRegisterInfoByName("r0"); break; case 1: arg_reg_info = reg_ctx->GetRegisterInfoByName("r1"); break; case 2: arg_reg_info = reg_ctx->GetRegisterInfoByName("r2"); break; case 3: arg_reg_info = reg_ctx->GetRegisterInfoByName("r3"); break; } } if (arg_reg_info) { 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; } } return false; } else { // Arguments 5 on up are on the stack const uint32_t arg_byte_size = (bit_width + (8-1)) / 8; Error error; if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error)) return false; sp += arg_byte_size; } } } } return true; }
bool ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); return false; } Error error; using namespace clang; ExecutionResults return_value = eExecutionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return return_value; if (process != m_jit_process_sp.get()) return false; if (args_addr_ref == LLDB_INVALID_ADDRESS) { args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error); if (args_addr_ref == LLDB_INVALID_ADDRESS) return false; m_wrapper_args_addrs.push_back (args_addr_ref); } else { // Make sure this is an address that we've already handed out. if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) { return false; } } // TODO: verify fun_addr needs to be a callable address Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); int first_offset = m_member_offsets[0]; process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); // FIXME: We will need to extend this for Variadic functions. Error value_error; size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { errors.Printf ("Wrong number of arguments - was: %lu should be: %lu", num_args, m_arg_values.GetSize()); return false; } for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. int offset = m_member_offsets[i+1]; // Clang sizes are in bytes. Value *arg_value = arg_values.GetValueAtIndex(i); // FIXME: For now just do scalars: // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings) if (arg_value->GetValueType() == Value::eValueTypeHostAddress && arg_value->GetContextType() == Value::eContextTypeClangType && ClangASTContext::IsPointerType(arg_value->GetClangType())) continue; const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext()); if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) return false; } return true; }
bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const { unsigned int num_values = values.GetSize(); unsigned int value_index; // Extract the register context so we can read arguments from registers RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; // Get the pointer to the first stack argument so we have a place to start // when reading data addr_t sp = reg_ctx->GetSP(0); if (!sp) return false; addr_t current_stack_argument = sp + 48; // jump over return address uint32_t argument_register_ids[8]; argument_register_ids[0] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1) ->kinds[eRegisterKindLLDB]; argument_register_ids[1] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2) ->kinds[eRegisterKindLLDB]; argument_register_ids[2] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3) ->kinds[eRegisterKindLLDB]; argument_register_ids[3] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4) ->kinds[eRegisterKindLLDB]; argument_register_ids[4] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5) ->kinds[eRegisterKindLLDB]; argument_register_ids[5] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6) ->kinds[eRegisterKindLLDB]; argument_register_ids[6] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7) ->kinds[eRegisterKindLLDB]; argument_register_ids[7] = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8) ->kinds[eRegisterKindLLDB]; unsigned int current_argument_register = 0; 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? CompilerType compiler_type = value->GetCompilerType(); if (!compiler_type) return false; bool is_signed; if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } else if (compiler_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, current_argument_register, current_stack_argument); } } return true; }
bool ABISysV_arm::GetArgumentValues (Thread &thread, ValueList &values) const { uint32_t num_values = values.GetSize(); ExecutionContext exe_ctx (thread.shared_from_this()); // For now, assume that the types in the AST values come from the Target's // scratch AST. // Extract the register context so we can read arguments from registers RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; addr_t sp = 0; 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; CompilerType compiler_type = value->GetCompilerType(); if (compiler_type) { bool is_signed = false; size_t bit_width = 0; if (compiler_type.IsIntegerType (is_signed)) { bit_width = compiler_type.GetBitSize(&thread); } else if (compiler_type.IsPointerOrReferenceType ()) { bit_width = compiler_type.GetBitSize(&thread); } else { // We only handle integer, pointer and reference types currently... return false; } if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) { if (value_idx < 4) { // Arguments 1-4 are in r0-r3... const RegisterInfo *arg_reg_info = NULL; arg_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (arg_reg_info) { 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; } } return false; } else { if (sp == 0) { // Read the stack pointer if it already hasn't been read sp = reg_ctx->GetSP(0); if (sp == 0) return false; } // Arguments 5 on up are on the stack const uint32_t arg_byte_size = (bit_width + (8-1)) / 8; Error error; if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error)) return false; sp += arg_byte_size; } } } } return true; }
bool FunctionCaller::WriteFunctionArguments( ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, DiagnosticManager &diagnostic_manager) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { diagnostic_manager.PutString(eDiagnosticSeverityError, "Argument information was not correctly " "parsed, so the function cannot be called."); return false; } Status error; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return return_value; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (process != jit_process_sp.get()) return false; if (args_addr_ref == LLDB_INVALID_ADDRESS) { args_addr_ref = process->AllocateMemory( m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, error); if (args_addr_ref == LLDB_INVALID_ADDRESS) return false; m_wrapper_args_addrs.push_back(args_addr_ref); } else { // Make sure this is an address that we've already handed out. if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) { return false; } } // TODO: verify fun_addr needs to be a callable address Scalar fun_addr( m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); uint64_t first_offset = m_member_offsets[0]; process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); // FIXME: We will need to extend this for Variadic functions. Status value_error; size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { diagnostic_manager.Printf( eDiagnosticSeverityError, "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); return false; } for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes. Value *arg_value = arg_values.GetValueAtIndex(i); // FIXME: For now just do scalars: // Special case: if it's a pointer, don't do anything (the ABI supports // passing cstrings) if (arg_value->GetValueType() == Value::eValueTypeHostAddress && arg_value->GetContextType() == Value::eContextTypeInvalid && arg_value->GetCompilerType().IsPointerType()) continue; const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx); if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) return false; } return true; }