diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-08-03 21:33:28 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-08-03 21:33:28 +0800 |
commit | 7f6d0fed8b2d713daa1668c66ffdcc5ac89d7874 (patch) | |
tree | d280ea6288977ec5c3884084b070cb9c268644bc | |
parent | b71606533fec98ef791de4a17423c03645bb6c3e (diff) | |
download | mrust-7f6d0fed8b2d713daa1668c66ffdcc5ac89d7874.tar.gz |
standalone miri - stat, errno, char casts
-rw-r--r-- | tools/standalone_miri/miri.cpp | 38 | ||||
-rw-r--r-- | tools/standalone_miri/value.cpp | 82 | ||||
-rw-r--r-- | tools/standalone_miri/value.hpp | 31 |
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 { |