private object ReadValue(MonoTypeEnum type, long addr) { switch (type) { case MonoTypeEnum.Boolean: return(_view.ReadBool(addr)); case MonoTypeEnum.U1: return(_view.ReadByte(addr)); case MonoTypeEnum.I1: return(_view.ReadSByte(addr)); case MonoTypeEnum.I2: return(_view.ReadShort(addr)); case MonoTypeEnum.U2: return(_view.ReadUshort(addr)); case MonoTypeEnum.Char: return((char)_view.ReadUshort(addr)); case MonoTypeEnum.I: case MonoTypeEnum.I4: return(_view.ReadInt(addr)); case MonoTypeEnum.U: case MonoTypeEnum.U4: return(_view.ReadUint(addr)); case MonoTypeEnum.I8: return(_view.ReadLong(addr)); case MonoTypeEnum.U8: return(_view.ReadUlong(addr)); case MonoTypeEnum.R4: return(_view.ReadFloat(addr)); case MonoTypeEnum.R8: return(_view.ReadDouble(addr)); case MonoTypeEnum.Szarray: addr = _view.ReadUint(addr); // deref object var vt = _view.ReadUint(addr); var pArrClass = _view.ReadUint(vt); var arrClass = new MonoClass(_view, pArrClass); var elClass = new MonoClass(_view, _view.ReadUint(pArrClass)); var count = _view.ReadInt(addr + 12); var start = addr + 16; var result = new object[count]; for (var i = 0; i < count; i++) { var ea = start + i * arrClass.Size; if (elClass.IsValueType) { if (elClass.ByvalArg.Type == MonoTypeEnum.ValueType) { result[i] = new MonoStruct(_view, elClass, (uint)ea); } else if (elClass.ByvalArg.Type == MonoTypeEnum.GenericInst) { result[i] = new MonoStruct(_view, elClass, (uint)ea); } else { result[i] = ReadValue(elClass.ByvalArg.Type, ea); } } else if (elClass.ByvalArg.Type == MonoTypeEnum.String) { result[i] = ReadValue(elClass.ByvalArg.Type, ea); } else { var po = _view.ReadUint(ea); if (po == 0) { result[i] = null; } else { result[i] = new MonoObject(_view, po); } } } return(result); case MonoTypeEnum.String: var pArr = _view.ReadUint(addr); if (pArr == 0) { return(null); } var strlen = _view.ReadInt(pArr + 8); if (strlen == 0) { return(string.Empty); } var buf = new byte[2 * strlen]; _view.ReadBytes(buf, 0, strlen * 2, pArr + 12); return(Encoding.Unicode.GetString(buf)); default: throw new Exception($"{type} not implemented"); } }
public object GetValue(MonoObject o) { var offset = Offset; var type = Type; var typeType = type.Type; bool isRef; switch (typeType) { case MonoTypeEnum.String: case MonoTypeEnum.Szarray: // Special case since it makes sense to treat these as values. isRef = false; break; case MonoTypeEnum.Object: case MonoTypeEnum.Class: case MonoTypeEnum.Array: isRef = true; break; case MonoTypeEnum.GenericInst: var genericClass = type.Data; var container = new MonoClass(_view, _view.ReadUint(genericClass)); isRef = !container.IsValueType; break; default: isRef = type.ByRef; break; } if (type.IsStatic) { var data = _view.ReadUint(Parent.VTable + Offsets.MonoVTable_data); if (isRef) { var po = _view.ReadUint(data + offset); return(po == 0 ? null : new MonoObject(_view, po)); } if (typeType == MonoTypeEnum.ValueType) { var sClass = new MonoClass(_view, type.Data); if (sClass.IsEnum) { return(ReadValue(new MonoClass(_view, _view.ReadUint(type.Data)).ByvalArg.Type, data + offset)); } return(new MonoStruct(_view, sClass, (uint)(data + offset))); } return(typeType == MonoTypeEnum.GenericInst ? null : ReadValue(typeType, data + offset)); } if (isRef) { var po = _view.ReadUint(o.PObject + offset); return(po == 0 ? null : new MonoObject(_view, po)); } if (typeType == MonoTypeEnum.ValueType) { var sClass = new MonoClass(_view, type.Data); if (sClass.IsEnum) { return(ReadValue(new MonoClass(_view, _view.ReadUint(type.Data)).ByvalArg.Type, o.PObject + offset)); } return(new MonoStruct(_view, sClass, (uint)(o.PObject + offset))); } if (typeType == MonoTypeEnum.GenericInst) { var sClass = new MonoClass(_view, _view.ReadUint(type.Data)); return(new MonoStruct(_view, sClass, (uint)(o.PObject + offset))); } return(ReadValue(typeType, o.PObject + offset)); }