summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBValue.h3
-rw-r--r--lldb/include/lldb/Core/Scalar.h3
-rw-r--r--lldb/include/lldb/Core/ValueObject.h3
-rw-r--r--lldb/include/lldb/Core/ValueObjectDynamicValue.h3
-rw-r--r--lldb/include/lldb/Core/ValueObjectRegister.h3
-rw-r--r--lldb/source/API/SBValue.cpp59
-rw-r--r--lldb/source/Core/Scalar.cpp64
-rw-r--r--lldb/source/Core/ValueObject.cpp78
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp39
-rw-r--r--lldb/source/Core/ValueObjectRegister.cpp18
-rw-r--r--lldb/test/functionalities/set-data/Makefile7
-rw-r--r--lldb/test/functionalities/set-data/TestSetData.py70
-rw-r--r--lldb/test/functionalities/set-data/main.m19
13 files changed, 369 insertions, 0 deletions
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h
index 91cf6380674..1f6f096ce53 100644
--- a/lldb/include/lldb/API/SBValue.h
+++ b/lldb/include/lldb/API/SBValue.h
@@ -290,6 +290,9 @@ public:
lldb::SBData
GetData ();
+ bool
+ SetData (lldb::SBData &data, lldb::SBError& error);
+
lldb::SBDeclaration
GetDeclaration ();
diff --git a/lldb/include/lldb/Core/Scalar.h b/lldb/include/lldb/Core/Scalar.h
index 3636b243eb6..2a89a598b5a 100644
--- a/lldb/include/lldb/Core/Scalar.h
+++ b/lldb/include/lldb/Core/Scalar.h
@@ -220,6 +220,9 @@ public:
Error
SetValueFromCString (const char *s, lldb::Encoding encoding, size_t byte_size);
+
+ Error
+ SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t byte_size);
static bool
UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index 869166aacc7..056387c4fb6 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -998,6 +998,9 @@ public:
virtual uint64_t
GetData (DataExtractor& data);
+
+ virtual bool
+ SetData (DataExtractor &data, Error &error);
bool
GetIsConstant () const
diff --git a/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/lldb/include/lldb/Core/ValueObjectDynamicValue.h
index a44afc41686..9efcbee2611 100644
--- a/lldb/include/lldb/Core/ValueObjectDynamicValue.h
+++ b/lldb/include/lldb/Core/ValueObjectDynamicValue.h
@@ -90,6 +90,9 @@ public:
virtual bool
SetValueFromCString (const char *value_str, Error& error);
+ virtual bool
+ SetData (DataExtractor &data, Error &error)
+
protected:
virtual bool
UpdateValue ();
diff --git a/lldb/include/lldb/Core/ValueObjectRegister.h b/lldb/include/lldb/Core/ValueObjectRegister.h
index 5c6ab890a56..73f6e583ad6 100644
--- a/lldb/include/lldb/Core/ValueObjectRegister.h
+++ b/lldb/include/lldb/Core/ValueObjectRegister.h
@@ -159,6 +159,9 @@ public:
virtual bool
SetValueFromCString (const char *value_str, Error& error);
+
+ virtual bool
+ SetData (DataExtractor &data, Error &error);
virtual bool
ResolveValue (Scalar &scalar);
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index 906fed18128..41c12a5689e 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -1880,6 +1880,65 @@ SBValue::GetData ()
return sb_data;
}
+bool
+SBValue::SetData (lldb::SBData &data, SBError &error)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ lldb::ValueObjectSP value_sp(GetSP());
+ bool ret = true;
+
+ if (value_sp)
+ {
+ ProcessSP process_sp(value_sp->GetProcessSP());
+ Process::StopLocker stop_locker;
+ if (process_sp && !stop_locker.TryLock(&process_sp->GetRunLock()))
+ {
+ if (log)
+ log->Printf ("SBValue(%p)::SetData() => error: process is running", value_sp.get());
+
+ error.SetErrorString("Process is running");
+ ret = false;
+ }
+ else
+ {
+ DataExtractor *data_extractor = data.get();
+
+ if (!data_extractor)
+ {
+ if (log)
+ log->Printf ("SBValue(%p)::SetData() => error: no data to set", value_sp.get());
+
+ error.SetErrorString("No data to set");
+ ret = false;
+ }
+ else
+ {
+ Error set_error;
+
+ value_sp->SetData(*data_extractor, set_error);
+
+ if (!set_error.Success())
+ {
+ error.SetErrorStringWithFormat("Couldn't set data: %s", set_error.AsCString());
+ ret = false;
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("Couldn't set data: invalid SBValue");
+ ret = false;
+ }
+
+ if (log)
+ log->Printf ("SBValue(%p)::SetData (%p) => %s",
+ value_sp.get(),
+ data.get(),
+ ret ? "true" : "false");
+ return ret;
+}
+
lldb::SBDeclaration
SBValue::GetDeclaration ()
{
diff --git a/lldb/source/Core/Scalar.cpp b/lldb/source/Core/Scalar.cpp
index 0fa112c80d6..16d8230cdef 100644
--- a/lldb/source/Core/Scalar.cpp
+++ b/lldb/source/Core/Scalar.cpp
@@ -1868,6 +1868,70 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
return error;
}
+Error
+Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t byte_size)
+{
+ Error error;
+
+ switch (encoding)
+ {
+ case lldb::eEncodingInvalid:
+ error.SetErrorString ("invalid encoding");
+ break;
+ case lldb::eEncodingVector:
+ error.SetErrorString ("vector encoding unsupported");
+ break;
+ case lldb::eEncodingUint:
+ {
+ lldb::offset_t offset;
+
+ switch (byte_size)
+ {
+ case 1: operator=((uint8_t)data.GetU8(&offset)); break;
+ case 2: operator=((uint16_t)data.GetU16(&offset)); break;
+ case 4: operator=((uint32_t)data.GetU32(&offset)); break;
+ case 8: operator=((uint64_t)data.GetU64(&offset)); break;
+ default:
+ error.SetErrorStringWithFormat ("unsupported unsigned integer byte size: %zu", byte_size);
+ break;
+ }
+ }
+ break;
+ case lldb::eEncodingSint:
+ {
+ lldb::offset_t offset;
+
+ switch (byte_size)
+ {
+ case 1: operator=((int8_t)data.GetU8(&offset)); break;
+ case 2: operator=((int16_t)data.GetU16(&offset)); break;
+ case 4: operator=((int32_t)data.GetU32(&offset)); break;
+ case 8: operator=((int64_t)data.GetU64(&offset)); break;
+ default:
+ error.SetErrorStringWithFormat ("unsupported signed integer byte size: %zu", byte_size);
+ break;
+ }
+ }
+ break;
+ case lldb::eEncodingIEEE754:
+ {
+ lldb::offset_t offset;
+
+ if (byte_size == sizeof (float))
+ operator=((float)data.GetFloat(&offset));
+ else if (byte_size == sizeof (double))
+ operator=((double)data.GetDouble(&offset));
+ else if (byte_size == sizeof (long double))
+ operator=((long double)data.GetLongDouble(&offset));
+ else
+ error.SetErrorStringWithFormat ("unsupported float byte size: %zu", byte_size);
+ }
+ break;
+ }
+
+ return error;
+}
+
bool
Scalar::SignExtend (uint32_t sign_bit_pos)
{
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index dcc9e0e8265..19dfdee5b2a 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -1013,6 +1013,84 @@ ValueObject::GetData (DataExtractor& data)
return data.GetByteSize();
}
+bool
+ValueObject::SetData (DataExtractor &data, Error &error)
+{
+ error.Clear();
+ // Make sure our value is up to date first so that our location and location
+ // type is valid.
+ if (!UpdateValueIfNeeded(false))
+ {
+ error.SetErrorString("unable to read value");
+ return false;
+ }
+
+ uint64_t count = 0;
+ Encoding encoding = ClangASTType::GetEncoding (GetClangType(), count);
+
+ const size_t byte_size = GetByteSize();
+
+ Value::ValueType value_type = m_value.GetValueType();
+
+ switch (value_type)
+ {
+ case Value::eValueTypeScalar:
+ {
+ Error set_error = m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
+
+ if (!set_error.Success())
+ {
+ error.SetErrorStringWithFormat("unable to set scalar value: %s", set_error.AsCString());
+ return false;
+ }
+ }
+ break;
+ case Value::eValueTypeLoadAddress:
+ {
+ // If it is a load address, then the scalar value is the storage location
+ // of the data, and we have to shove this value down to that load location.
+ ExecutionContext exe_ctx (GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ size_t bytes_written = process->WriteMemory(target_addr,
+ data.GetDataStart(),
+ byte_size,
+ error);
+ if (!error.Success())
+ return false;
+ if (bytes_written != byte_size)
+ {
+ error.SetErrorString("unable to write value to memory");
+ return false;
+ }
+ }
+ }
+ break;
+ case Value::eValueTypeHostAddress:
+ {
+ // If it is a host address, then we stuff the scalar as a DataBuffer into the Value's data.
+ DataBufferSP buffer_sp (new DataBufferHeap(byte_size, 0));
+ m_data.SetData(buffer_sp, 0);
+ data.CopyByteOrderedData (0,
+ byte_size,
+ const_cast<uint8_t *>(m_data.GetDataStart()),
+ byte_size,
+ m_data.GetByteOrder());
+ m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
+ }
+ break;
+ case Value::eValueTypeFileAddress:
+ case Value::eValueTypeVector:
+ break;
+ }
+
+ // If we have reached this point, then we have successfully changed the value.
+ SetNeedsUpdate();
+ return true;
+}
+
// will compute strlen(str), but without consuming more than
// maxlen bytes out of str (this serves the purpose of reading
// chunks of a string without having to worry about
diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp
index f82c66602ba..95108f386fa 100644
--- a/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -343,3 +343,42 @@ ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& erro
SetNeedsUpdate();
return ret_val;
}
+
+bool
+ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error)
+{
+ if (!UpdateValueIfNeeded(false))
+ {
+ error.SetErrorString("unable to read value");
+ return false;
+ }
+
+ uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
+ uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
+
+ if (my_value == UINT64_MAX || parent_value == UINT64_MAX)
+ {
+ error.SetErrorString("unable to read value");
+ return false;
+ }
+
+ // if we are at an offset from our parent, in order to set ourselves correctly we would need
+ // to change the new value so that it refers to the correct dynamic type. we choose not to deal
+ // with that - if anything more than a value overwrite is required, you should be using the
+ // expression parser instead of the value editing facility
+ if (my_value != parent_value)
+ {
+ // but NULL'ing out a value should always be allowed
+ lldb::offset_t offset = 0;
+
+ if (data.GetPointer(&offset) != 0)
+ {
+ error.SetErrorString("unable to modify dynamic value, use 'expression' command");
+ return false;
+ }
+ }
+
+ bool ret_val = m_parent->SetData(data, error);
+ SetNeedsUpdate();
+ return ret_val;
+}
diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp
index 9ac8aa49205..f03db384f48 100644
--- a/lldb/source/Core/ValueObjectRegister.cpp
+++ b/lldb/source/Core/ValueObjectRegister.cpp
@@ -423,6 +423,24 @@ ValueObjectRegister::SetValueFromCString (const char *value_str, Error& error)
}
bool
+ValueObjectRegister::SetData (DataExtractor &data, Error &error)
+{
+ error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false);
+ if (error.Success())
+ {
+ if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value))
+ {
+ SetNeedsUpdate();
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
+bool
ValueObjectRegister::ResolveValue (Scalar &scalar)
{
if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything
diff --git a/lldb/test/functionalities/set-data/Makefile b/lldb/test/functionalities/set-data/Makefile
new file mode 100644
index 00000000000..9e1d63a183b
--- /dev/null
+++ b/lldb/test/functionalities/set-data/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../make
+
+OBJC_SOURCES := main.m
+
+include $(LEVEL)/Makefile.rules
+
+LDFLAGS += -framework Foundation
diff --git a/lldb/test/functionalities/set-data/TestSetData.py b/lldb/test/functionalities/set-data/TestSetData.py
new file mode 100644
index 00000000000..166ef6706fc
--- /dev/null
+++ b/lldb/test/functionalities/set-data/TestSetData.py
@@ -0,0 +1,70 @@
+"""
+Set the contents of variables and registers using raw data
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+class SetDataTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "set-data")
+
+ @dsym_test
+ def test_set_data_dsym(self):
+ """Test setting the contents of variables and registers using raw data."""
+ self.buildDsym()
+ self.setData()
+
+ def setData(self):
+ """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'."""
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("br s -p First");
+ self.runCmd("br s -p Second");
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ self.expect("p myFoo.x", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ['2'])
+
+ process = self.dbg.GetSelectedTarget().GetProcess()
+ frame = process.GetSelectedThread().GetFrameAtIndex(0)
+
+ x = frame.FindVariable("myFoo").GetChildMemberWithName("x")
+
+ my_data = lldb.SBData.CreateDataFromSInt32Array(lldb.eByteOrderLittle, 8, [4])
+ err = lldb.SBError()
+
+ self.assertTrue (x.SetData(my_data, err))
+
+ self.runCmd("continue")
+
+ self.expect("p myFoo.x", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ['4'])
+
+ frame = process.GetSelectedThread().GetFrameAtIndex(0)
+
+ x = frame.FindVariable("string")
+
+ if process.GetAddressByteSize() == 8:
+ my_data = lldb.SBData.CreateDataFromUInt64Array(process.GetByteOrder(), 8, [0])
+ else:
+ my_data = lldb.SBData.CreateDataFromUInt32Array(process.GetByteOrder(), 4, [0])
+
+ err = lldb.SBError()
+
+ self.assertTrue (x.SetData(my_data, err))
+
+ self.expect("fr var -d run-target string", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ['NSString *', 'nil'])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/functionalities/set-data/main.m b/lldb/test/functionalities/set-data/main.m
new file mode 100644
index 00000000000..e1e69dc5571
--- /dev/null
+++ b/lldb/test/functionalities/set-data/main.m
@@ -0,0 +1,19 @@
+#import <Foundation/Foundation.h>
+
+int main ()
+{
+ @autoreleasepool
+ {
+ struct foo {
+ int x;
+ int y;
+ } myFoo;
+
+ myFoo.x = 2;
+ myFoo.y = 3; // First breakpoint
+
+ NSString *string = [NSString stringWithFormat:@"%s", "Hello world!"];
+
+ NSLog(@"%d %@", myFoo.x, string); // Second breakpoint
+ }
+}
OpenPOWER on IntegriCloud