summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-08-03 21:33:28 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-08-03 21:33:28 +0800
commit7f6d0fed8b2d713daa1668c66ffdcc5ac89d7874 (patch)
treed280ea6288977ec5c3884084b070cb9c268644bc
parentb71606533fec98ef791de4a17423c03645bb6c3e (diff)
downloadmrust-7f6d0fed8b2d713daa1668c66ffdcc5ac89d7874.tar.gz
standalone miri - stat, errno, char casts
-rw-r--r--tools/standalone_miri/miri.cpp38
-rw-r--r--tools/standalone_miri/value.cpp82
-rw-r--r--tools/standalone_miri/value.hpp31
3 files changed, 90 insertions, 61 deletions
diff --git a/tools/standalone_miri/miri.cpp b/tools/standalone_miri/miri.cpp
index d4bb267c..c955ef3b 100644
--- a/tools/standalone_miri/miri.cpp
+++ b/tools/standalone_miri/miri.cpp
@@ -12,11 +12,13 @@
#include <iomanip>
#include "debug.hpp"
#include "miri.hpp"
+// VVV FFI
#include <cstring> // memrchr
#ifdef _WIN32
# define NOMINMAX
# include <Windows.h>
#endif
+#include <sys/stat.h>
#undef DEBUG
unsigned ThreadState::s_next_tls_key = 1;
@@ -800,7 +802,7 @@ bool InterpreterThread::step_one(Value& out_thread_result)
case RawType::Char: new_val.write_u32(0, src_value.read_u32(0) ); break;
case RawType::U8: new_val.write_u32(0, src_value.read_u8(0) ); break;
default:
- LOG_ERROR("Cat from " << src_ty << " to char isn't valid");
+ LOG_ERROR("Cast from " << src_ty << " to char isn't valid");
break;
}
break;
@@ -829,8 +831,21 @@ bool InterpreterThread::step_one(Value& out_thread_result)
new_val = src_value.read_value(0, re.type.get_size());
break;
case RawType::Char:
- LOG_ASSERT(re.type.inner_type == RawType::U32, "Char can only be casted to u32, instead " << re.type);
- new_val = src_value.read_value(0, 4);
+ switch(re.type.inner_type)
+ {
+ case RawType::U8: {
+ uint32_t v = src_value.read_u32(0);
+ if( v > 0xFF ) {
+ LOG_NOTICE("Casting to u8 from char above 255");
+ }
+ new_val.write_u8(0, v & 0xFF);
+ } break;
+ case RawType::U32:
+ new_val = src_value.read_value(0, 4);
+ break;
+ default:
+ LOG_ERROR("Char can only be casted to u32/u8, instead " << re.type);
+ }
break;
case RawType::Unit:
LOG_FATAL("Cast of unit");
@@ -1948,6 +1963,23 @@ bool InterpreterThread::call_extern(Value& rv, const ::std::string& link_name, c
{
rv = Value::new_i32(0);
}
+ // - Linux extensions
+ else if( link_name == "stat64" )
+ {
+ const auto* path = FfiHelpers::read_cstr(args.at(0), 0);
+ auto outbuf_vr = args.at(1).read_pointer_valref_mut(0, sizeof(struct stat));
+
+ LOG_DEBUG("stat64(\"" << path << "\", " << outbuf_vr << ")");
+ int rv_i = stat(path, reinterpret_cast<struct stat*>(outbuf_vr.data_ptr_mut()));
+ LOG_DEBUG("= " << rv_i);
+
+ rv = Value(::HIR::TypeRef(RawType::I32));
+ rv.write_i32(0, rv_i);
+ }
+ else if( link_name == "__errno_location" )
+ {
+ rv = Value::new_ffiptr(FFIPointer::new_const_bytes(&errno, sizeof(errno)));
+ }
#endif
// std C
else if( link_name == "signal" )
diff --git a/tools/standalone_miri/value.cpp b/tools/standalone_miri/value.cpp
index 7344ef46..3fb4c238 100644
--- a/tools/standalone_miri/value.cpp
+++ b/tools/standalone_miri/value.cpp
@@ -13,6 +13,16 @@
#include <algorithm>
#include "debug.hpp"
+namespace {
+ static bool in_bounds(size_t ofs, size_t size, size_t max_size) {
+ if( !(ofs < max_size) )
+ return false;
+ if( !(size <= max_size) )
+ return false;
+ return ofs + size <= max_size;
+ }
+};
+
::std::ostream& operator<<(::std::ostream& os, const Allocation* x)
{
os << "A(" << static_cast<const void*>(x) << " " << x->tag() /*<< " +" << x->size()*/ << ")";
@@ -207,7 +217,7 @@ size_t RelocationPtr::get_size() const
os << "\"" << x.str() << "\"";
break;
case RelocationPtr::Ty::FfiPointer:
- os << "FFI " << x.ffi().tag_name << " " << x.ffi().ptr_value;
+ os << "FFI '" << x.ffi().tag_name << "' " << x.ffi().ptr_value;
break;
}
}
@@ -314,7 +324,7 @@ void Allocation::resize(size_t new_size)
void Allocation::check_bytes_valid(size_t ofs, size_t size) const
{
- if( !(ofs + size <= this->size()) ) {
+ if( !in_bounds(ofs, size, this->size()) ) {
LOG_FATAL("Out of range - " << ofs << "+" << size << " > " << this->size());
}
for(size_t i = ofs; i < ofs + size; i++)
@@ -410,15 +420,7 @@ void Allocation::read_bytes(size_t ofs, void* dst, size_t count) const
if(count == 0)
return ;
- if(ofs >= this->size() ) {
- LOG_ERROR("Out of bounds read, " << ofs << "+" << count << " > " << this->size());
- throw "ERROR";
- }
- if(count > this->size() ) {
- LOG_ERROR("Out of bounds read, " << ofs << "+" << count << " > " << this->size());
- throw "ERROR";
- }
- if(ofs+count > this->size() ) {
+ if( !in_bounds(ofs, count, this->size()) ) {
LOG_ERROR("Out of bounds read, " << ofs << "+" << count << " > " << this->size());
throw "ERROR";
}
@@ -507,15 +509,7 @@ void Allocation::write_bytes(size_t ofs, const void* src, size_t count)
if(count == 0)
return ;
TRACE_FUNCTION_R("Allocation::write_bytes " << this << " " << ofs << "+" << count, *this);
- if(ofs >= this->size() ) {
- LOG_ERROR("Out of bounds write, " << ofs << "+" << count << " > " << this->size());
- throw "ERROR";
- }
- if(count > this->size() ) {
- LOG_ERROR("Out of bounds write, " << ofs << "+" << count << " > " << this->size());
- throw "ERROR";
- }
- if(ofs+count > this->size() ) {
+ if( !in_bounds(ofs, count, this->size()) ) {
LOG_ERROR("Out of bounds write, " << ofs << "+" << count << " > " << this->size());
throw "ERROR";
}
@@ -690,11 +684,7 @@ void Value::check_bytes_valid(size_t ofs, size_t size) const
if( size == 0 && this->direct_data.size > 0 ) {
return ;
}
- if( ofs >= this->direct_data.size ) {
- LOG_ERROR("Read out of bounds " << ofs << "+" << size << " > " << int(this->direct_data.size));
- throw "ERROR";
- }
- if( ofs+size > this->direct_data.size ) {
+ if( !in_bounds(ofs, size, this->direct_data.size) ) {
LOG_ERROR("Read out of bounds " << ofs+size << " >= " << int(this->direct_data.size));
throw "ERROR";
}
@@ -753,15 +743,8 @@ void Value::read_bytes(size_t ofs, void* dst, size_t count) const
{
check_bytes_valid(ofs, count);
- if(ofs >= this->direct_data.size ) {
- LOG_ERROR("Out of bounds read, " << ofs << "+" << count << " > " << this->size());
- throw "ERROR";
- }
- if(count > this->direct_data.size ) {
- LOG_ERROR("Out of bounds read, " << ofs << "+" << count << " > " << this->size());
- throw "ERROR";
- }
- if(ofs+count > this->direct_data.size ) {
+ // TODO: Redundant due to above?
+ if( !in_bounds(ofs, count, this->direct_data.size) ) {
LOG_ERROR("Out of bounds read, " << ofs << "+" << count << " > " << this->size());
throw "ERROR";
}
@@ -779,13 +762,7 @@ void Value::write_bytes(size_t ofs, const void* src, size_t count)
}
else
{
- if(ofs >= this->direct_data.size ) {
- LOG_BUG("Write to offset outside value size (" << ofs << "+" << count << " >= " << (int)this->direct_data.size << ")");
- }
- if(count > this->direct_data.size ){
- LOG_BUG("Write larger than value size (" << ofs << "+" << count << " >= " << (int)this->direct_data.size << ")");
- }
- if(ofs+count > this->direct_data.size ) {
+ if( !in_bounds(ofs, count, this->direct_data.size) ) {
LOG_BUG("Write extends outside value size (" << ofs << "+" << count << " >= " << (int)this->direct_data.size << ")");
}
::std::memcpy(this->direct_data.data + ofs, src, count);
@@ -905,9 +882,7 @@ extern ::std::ostream& operator<<(::std::ostream& os, const ValueRef& v)
break;
case RelocationPtr::Ty::StdString: {
const auto& s = alloc_ptr.str();
- assert(v.m_offset < s.size());
- assert(v.m_size < s.size());
- assert(v.m_offset + v.m_size <= s.size());
+ assert( in_bounds(v.m_offset, v.m_size, s.size()) );
auto flags = os.flags();
os << ::std::hex;
for(size_t i = v.m_offset; i < v.m_offset + v.m_size; i++)
@@ -987,7 +962,7 @@ Value ValueRef::read_value(size_t ofs, size_t size) const
{
if( size == 0 )
return Value();
- if( !(ofs < m_size && size <= m_size && ofs + size <= m_size) ) {
+ if( !in_bounds(ofs, size, m_size) ) {
LOG_ERROR("Read exceeds bounds, " << ofs << " + " << size << " > " << m_size << " - from " << *this);
}
if( m_alloc ) {
@@ -997,16 +972,19 @@ Value ValueRef::read_value(size_t ofs, size_t size) const
return m_alloc.alloc().read_value(m_offset + ofs, size);
case RelocationPtr::Ty::StdString: {
auto rv = Value::with_size(size, false);
- //ASSERT_BUG(ofs <= m_alloc.str().size(), "");
- //ASSERT_BUG(size <= m_alloc.str().size(), "");
- //ASSERT_BUG(ofs+size <= m_alloc.str().size(), "");
- assert(m_offset+ofs <= m_alloc.str().size() && size <= m_alloc.str().size() && m_offset+ofs+size <= m_alloc.str().size());
+ LOG_ASSERT(in_bounds(ofs, size, m_alloc.str().size()), "");
rv.write_bytes(0, m_alloc.str().data() + m_offset + ofs, size);
return rv;
}
- default:
- //ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << );
- throw "TODO";
+ case RelocationPtr::Ty::FfiPointer: {
+ auto rv = Value::with_size(size, false);
+ LOG_ASSERT(in_bounds(ofs, size, m_alloc.ffi().get_size()), "");
+ rv.write_bytes(0, reinterpret_cast<const char*>(m_alloc.ffi().ptr_value) + m_offset + ofs, size);
+ return rv;
+ }
+ default: {
+ LOG_TODO("read_value from " << m_alloc);
+ }
}
}
else {
diff --git a/tools/standalone_miri/value.hpp b/tools/standalone_miri/value.hpp
index 68fa492f..e8567d02 100644
--- a/tools/standalone_miri/value.hpp
+++ b/tools/standalone_miri/value.hpp
@@ -214,8 +214,7 @@ struct ValueCommonRead
bool is_mut;
void* rv = read_pointer_unsafe(rd_ofs, 0, out_size, is_mut);
if(!is_mut)
- throw "";
- //LOG_FATAL("Attempting to get an uninit pointer to immutable data");
+ LOG_FATAL("Attempting to get an uninit pointer to immutable data");
return rv;
}
/// Read a pointer and return a ValueRef to it (mutable data)
@@ -393,7 +392,7 @@ struct ValueRef:
}
break;
default:
- throw "TODO";
+ LOG_TODO("");
}
}
}
@@ -436,7 +435,7 @@ struct ValueRef:
case RelocationPtr::Ty::StdString:
return reinterpret_cast<const uint8_t*>(m_alloc.str().data() + m_offset);
default:
- throw "TODO";
+ LOG_TODO("");
}
}
else if( m_value ) {
@@ -446,6 +445,26 @@ struct ValueRef:
return nullptr;
}
}
+ uint8_t* data_ptr_mut() {
+ if( m_alloc ) {
+ switch(m_alloc.get_ty())
+ {
+ case RelocationPtr::Ty::Allocation:
+ return m_alloc.alloc().data_ptr() + m_offset;
+ break;
+ default:
+ LOG_TODO("");
+ }
+ }
+ else if( m_value ) {
+ return m_value->data_ptr() + m_offset;
+ }
+ else {
+ return nullptr;
+ }
+ }
+ void mark_valid(size_t ofs, size_t size);
+
void read_bytes(size_t ofs, void* dst, size_t size) const {
if( size == 0 )
return ;
@@ -464,7 +483,7 @@ struct ValueRef:
break;
default:
//ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << );
- throw "TODO";
+ LOG_TODO("");
}
}
else {
@@ -488,7 +507,7 @@ struct ValueRef:
break;
default:
//ASSERT_BUG(m_alloc.is_alloc(), "read_value on non-data backed Value - " << );
- throw "TODO";
+ LOG_TODO("");
}
}
else {