summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins
diff options
context:
space:
mode:
authorAbhishek Aggarwal <abhishek.a.aggarwal@intel.com>2015-09-04 07:44:05 +0000
committerAbhishek Aggarwal <abhishek.a.aggarwal@intel.com>2015-09-04 07:44:05 +0000
commit2cf87a895d5b64c5c6e2c242f4e12ce2a8d68a94 (patch)
treec2612d3894cea8b7e9379abb174cb75653ecfb2f /lldb/source/Plugins
parent5ca46f0df128a6b3868f332fcfd4c10d01152c19 (diff)
downloadbcm5719-llvm-2cf87a895d5b64c5c6e2c242f4e12ce2a8d68a94.tar.gz
bcm5719-llvm-2cf87a895d5b64c5c6e2c242f4e12ce2a8d68a94.zip
SysV ABI for i386 Architecture
Summary: - Capability to force return user specified values from inside of a function on lldb command terminal - Support for Integral, Pointer and Floating Point values Signed-off-by: Abhishek Aggarwal <abhishek.a.aggarwal@intel.com> Reviewers: jingham, clayborg Subscribers: tberghammer Differential Revision: http://reviews.llvm.org/D12595 llvm-svn: 246841
Diffstat (limited to 'lldb/source/Plugins')
-rwxr-xr-x[-rw-r--r--]lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp145
1 files changed, 143 insertions, 2 deletions
diff --git a/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
index c6f3fd2d32d..af439cdb35b 100644..100755
--- a/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
+++ b/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -418,8 +418,149 @@ Error
ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
{
Error error;
- //ToDo: Yet to be implemented
- error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet");
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ CompilerType clang_type = new_value_sp->GetCompilerType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ const uint32_t type_flags = clang_type.GetTypeInfo ();
+ Thread *thread = frame_sp->GetThread().get();
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ bool register_write_successful = true;
+
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
+ // The terminology 'Fundamental Data Types' used here is adopted from
+ // Table 2.1 of the reference document (specified on top of this file)
+
+ if (type_flags & eTypeIsPointer) // 'Pointer'
+ {
+ if(num_bytes != sizeof(uint32_t))
+ {
+ error.SetErrorString("Pointer to be returned is not 4 bytes wide");
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ }
+ else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
+ {
+ lldb::offset_t offset = 0;
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+
+ if (type_flags & eTypeIsInteger) // 'Integral' except enum
+ {
+ switch (num_bytes)
+ {
+ default:
+ break;
+ case 16:
+ // For clang::BuiltinType::UInt128 & Int128
+ // ToDo: Need to decide how to handle it
+ break;
+ case 8:
+ {
+ uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
+ const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
+ uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
+ register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) &&
+ reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high));
+ break;
+ }
+ case 4:
+ case 2:
+ case 1:
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ break;
+ }
+ }
+ }
+ else if (type_flags & eTypeIsEnumeration) // handles enum
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ }
+ else if (type_flags & eTypeIsFloat) // 'Floating Point'
+ {
+ RegisterValue st0_value, fstat_value, ftag_value;
+ const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
+ const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0);
+ const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
+
+ /* According to Page 3-12 of document
+ System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition
+ To return Floating Point values, all st% registers except st0 should be empty after exiting from
+ a function. This requires setting fstat and ftag registers to specific values.
+ fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific
+ value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */
+ uint32_t value_fstat_u32 = 0x00003800;
+
+ /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set
+ 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance
+ with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */
+ uint32_t value_ftag_u32 = 0x00000080;
+
+ if (num_bytes <= 12) // handles float, double, long double, __float80
+ {
+ long double value_long_dbl = 0.0;
+ if (num_bytes == 4)
+ value_long_dbl = data.GetFloat(&offset);
+ else if (num_bytes == 8)
+ value_long_dbl = data.GetDouble(&offset);
+ else if (num_bytes == 12)
+ value_long_dbl = data.GetLongDouble(&offset);
+ else
+ {
+ error.SetErrorString ("Invalid number of bytes for this return type");
+ return error;
+ }
+ st0_value.SetLongDouble(value_long_dbl);
+ fstat_value.SetUInt32(value_fstat_u32);
+ ftag_value.SetUInt32(value_ftag_u32);
+ register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) &&
+ reg_ctx->WriteRegister(fstat_info, fstat_value) &&
+ reg_ctx->WriteRegister(ftag_info, ftag_value);
+ }
+ else if(num_bytes == 16) // handles __float128
+ {
+ error.SetErrorString ("Implementation is missing for this clang type.");
+ }
+ }
+ else
+ {
+ // Neither 'Integral' nor 'Floating Point'. If flow reaches here
+ // then check type_flags. This type_flags is not a valid type.
+ error.SetErrorString ("Invalid clang type");
+ }
+ }
+ else
+ {
+ /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types
+ are yet to be implemented */
+ error.SetErrorString ("Currently only Integral and Floating Point clang types are supported.");
+ }
+ if(!register_write_successful)
+ error.SetErrorString ("Register writing failed");
return error;
}
OpenPOWER on IntegriCloud