to force all of your Mono processes to use LLVM or SGEN without having
to modify any launch scripts.
.TP
+\fBMONO_ENV_OPTIONS\fR
+Used to pass extra options to the debugger agent in the runtime, as they were passed
+using --debugger-agent=.
+.TP
\fBMONO_EVENTLOG_TYPE\fR
Sets the type of event log provider to use (for System.Diagnostics.EventLog).
.Sp
Mono.Debugger.Soft/CustomAttributeDataMirror.cs
Mono.Debugger.Soft/ThreadStartEvent.cs
Mono.Debugger.Soft/ILInstruction.cs
+Mono.Debugger.Soft/InterfaceMappingMirror.cs
Mono.Debugger.Soft/PrimitiveValue.cs
Mono.Debugger.Soft/VMDisconnectedException.cs
Mono.Debugger.Soft/Mirror.cs
public long[] nested;
}
+ struct IfaceMapInfo {
+ public long iface_id;
+ public long[] iface_methods;
+ public long[] target_methods;
+ }
+
class MethodInfo {
public int attributes, iattributes, token;
}
* with newer runtimes, and vice versa.
*/
internal const int MAJOR_VERSION = 2;
- internal const int MINOR_VERSION = 10;
+ internal const int MINOR_VERSION = 11;
enum WPSuspendPolicy {
NONE = 0,
/* FIXME: Merge into GET_VALUES when the major protocol version is increased */
GET_VALUES_2 = 14,
CMD_TYPE_GET_METHODS_BY_NAME_FLAGS = 15,
+ GET_INTERFACES = 16,
+ GET_INTERFACE_MAP = 17
}
enum BindingFlagsExtensions {
throw new NotImplementedException ("Unable to handle type " + etype);
}
}
+
+ public long[] ReadIds (int n) {
+ long[] res = new long [n];
+ for (int i = 0; i < n; ++i)
+ res [i] = ReadId ();
+ return res;
+ }
}
class PacketWriter {
res [i] = r.ReadId ();
return res;
}
+
+ internal long[] Type_GetInterfaces (long id) {
+ PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_INTERFACES, new PacketWriter ().WriteId (id));
+ int len = r.ReadInt ();
+ return r.ReadIds (len);
+ }
+
+ internal IfaceMapInfo[] Type_GetInterfaceMap (long id, long[] ids) {
+ PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_INTERFACE_MAP, new PacketWriter ().WriteId (id).WriteInt (ids.Length).WriteIds (ids));
+ var res = new IfaceMapInfo [ids.Length];
+ for (int i = 0; i < ids.Length; ++i) {
+ int n = r.ReadInt ();
+
+ res [i].iface_id = ids [i];
+ res [i].iface_methods = r.ReadIds (n);
+ res [i].target_methods = r.ReadIds (n);
+ }
+
+ return res;
+ }
+
/*
* EVENTS
*/
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using C = Mono.Cecil;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+ public class InterfaceMappingMirror : Mirror {
+
+ internal InterfaceMappingMirror (VirtualMachine vm, TypeMirror target, TypeMirror iface, MethodMirror[] iface_methods, MethodMirror[] target_methods) : base (vm, 0) {
+ TargetType = target;
+ InterfaceType = iface;
+ InterfaceMethods = iface_methods;
+ TargetMethods = target_methods;
+ }
+
+ public MethodMirror[] InterfaceMethods;
+
+ public TypeMirror InterfaceType;
+
+ public MethodMirror[] TargetMethods;
+
+ public TypeMirror TargetType;
+ }
+}
TypeMirror base_type, element_type;
TypeMirror[] nested;
CustomAttributeDataMirror[] cattrs;
+ TypeMirror[] ifaces;
+ Dictionary<TypeMirror, InterfaceMappingMirror> iface_map;
internal const BindingFlags DefaultBindingFlags =
BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
- }
+ }
+
+ // Since protocol version 2.11
+ public TypeMirror[] GetInterfaces () {
+ if (ifaces == null)
+ ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id));
+ return ifaces;
+ }
+
+ // Since protocol version 2.11
+ public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) {
+ if (interfaceType == null)
+ throw new ArgumentNullException ("interfaceType");
+ if (!interfaceType.IsInterface)
+ throw new ArgumentException ("Argument must be an interface.", "interfaceType");
+ if (IsInterface)
+ throw new ArgumentException ("'this' type cannot be an interface itself");
+
+ if (iface_map == null) {
+ // Query the info in bulk
+ GetInterfaces ();
+ var ids = new long [ifaces.Length];
+ for (int i = 0; i < ifaces.Length; ++i)
+ ids [i] = ifaces [i].Id;
+
+ var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids);
+
+ var imap = new Dictionary<TypeMirror, InterfaceMappingMirror> ();
+ for (int i = 0; i < ifacemap.Length; ++i) {
+ IfaceMapInfo info = ifacemap [i];
+
+ MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length];
+ for (int j = 0; j < info.iface_methods.Length; ++j)
+ imethods [j] = vm.GetMethod (info.iface_methods [j]);
+
+ MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length];
+ for (int j = 0; j < info.target_methods.Length; ++j)
+ tmethods [j] = vm.GetMethod (info.target_methods [j]);
+
+ InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods);
+
+ imap [map.InterfaceType] = map;
+ }
+
+ iface_map = imap;
+ }
+
+ InterfaceMappingMirror res;
+ if (!iface_map.TryGetValue (interfaceType, out res))
+ throw new ArgumentException ("Interface not found", "interfaceType");
+ return res;
+ }
+
}
}
}
}
+ internal TypeMirror[] GetTypes (long[] ids) {
+ var res = new TypeMirror [ids.Length];
+ for (int i = 0; i < ids.Length; ++i)
+ res [i] = GetType (ids [i]);
+ return res;
+ }
+
Dictionary <long, ObjectMirror> objects;
object objects_lock = new object ();
}
}
+interface ITest
+{
+ void Foo ();
+ void Bar ();
+}
+
+interface ITest<T>
+{
+ void Foo ();
+ void Bar ();
+}
+
+class TestIfaces : ITest
+{
+ void ITest.Foo () {
+ }
+
+ void ITest.Bar () {
+ }
+
+ TestIfaces<int> Baz () {
+ return null;
+ }
+}
+
+class TestIfaces<T> : ITest<T>
+{
+ void ITest<T>.Foo () {
+ }
+
+ void ITest<T>.Bar () {
+ }
+}
+
public class Tests : TestsBase
{
#pragma warning disable 0414
s.GetChars (2, 2);
});
}
+
+ [Test]
+ public void GetInterfaces () {
+ var e = run_until ("arg2");
+
+ var frame = e.Thread.GetFrames () [0];
+
+ var cl1 = frame.Method.DeclaringType.Assembly.GetType ("TestIfaces");
+ var ifaces = cl1.GetInterfaces ();
+ Assert.AreEqual (1, ifaces.Length);
+ Assert.AreEqual ("ITest", ifaces [0].Name);
+
+ var cl2 = cl1.GetMethod ("Baz").ReturnType;
+ var ifaces2 = cl2.GetInterfaces ();
+ Assert.AreEqual (1, ifaces2.Length);
+ Assert.AreEqual ("ITest`1", ifaces2 [0].Name);
+ }
+
+ [Test]
+ public void GetInterfaceMap () {
+ var e = run_until ("arg2");
+
+ var frame = e.Thread.GetFrames () [0];
+
+ var cl1 = frame.Method.DeclaringType.Assembly.GetType ("TestIfaces");
+ var iface = cl1.Assembly.GetType ("ITest");
+ var map = cl1.GetInterfaceMap (iface);
+ Assert.AreEqual (cl1, map.TargetType);
+ Assert.AreEqual (iface, map.InterfaceType);
+ Assert.AreEqual (2, map.InterfaceMethods.Length);
+ Assert.AreEqual (2, map.TargetMethods.Length);
+ }
}
}
bool ConnectAsyncReal (SocketAsyncEventArgs e)
- {
- IPAddress [] addresses = null;
+ {
bool use_remoteep = true;
#if MOONLIGHT || NET_4_0
+ IPAddress [] addresses = null;
use_remoteep = !GetCheckedIPs (e, out addresses);
bool policy_failed = (e.SocketError == SocketError.AccessDenied);
#endif
public IWebProxy Proxy {
get {
- if (proxySet)
+ if (!proxySet)
return WebRequest.DefaultWebProxy;
return proxy;
int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
if (iProxyEnable > 0) {
- string strHttpProxy = "";
- string[] bypassList = null;
+ string strHttpProxy = "";
bool bBypassOnLocal = false;
+ ArrayList al = new ArrayList ();
string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null);
string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null);
}
} else strHttpProxy = strProxyServer;
- if (strProxyOverrride != null)
- bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
-
- ArrayList al = new ArrayList ();
+ if (strProxyOverrride != null) {
+ string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (string str in bypassList) {
- if (str != "<local>")al.Add (str);
- else bBypassOnLocal = true;
+ foreach (string str in bypassList) {
+ if (str != "<local>")
+ al.Add (str);
+ else
+ bBypassOnLocal = true;
+ }
}
return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
}
}
- bool bBypassOnLocal = false;
- string[] bypassList = null;
+ bool bBypassOnLocal = false;
ArrayList al = new ArrayList ();
string bypass = Environment.GetEnvironmentVariable ("no_proxy");
if (bypass == null)
bypass = Environment.GetEnvironmentVariable ("NO_PROXY");
- if (bypass != null)
- bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ if (bypass != null) {
+ string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (string str in bypassList) {
- if (str != "*.local")al.Add (str);
- else bBypassOnLocal = true;
+ foreach (string str in bypassList) {
+ if (str != "*.local")
+ al.Add (str);
+ else
+ bBypassOnLocal = true;
+ }
}
return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
public virtual InterfaceMapping GetInterfaceMap (Type interfaceType) {
if (!IsSystemType)
throw new NotSupportedException ("Derived classes must provide an implementation.");
+ if (interfaceType == null)
+ throw new ArgumentNullException ("interfaceType");
if (!interfaceType.IsSystemType)
throw new ArgumentException ("interfaceType", "Type is an user type");
InterfaceMapping res;
- if (interfaceType == null)
- throw new ArgumentNullException ("interfaceType");
if (!interfaceType.IsInterface)
throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "interfaceType");
if (IsInterface)
#define HEADER_LENGTH 11
#define MAJOR_VERSION 2
-#define MINOR_VERSION 10
+#define MINOR_VERSION 11
typedef enum {
CMD_SET_VM = 1,
CMD_TYPE_GET_SOURCE_FILES_2 = 13,
CMD_TYPE_GET_VALUES_2 = 14,
CMD_TYPE_GET_METHODS_BY_NAME_FLAGS = 15,
+ CMD_TYPE_GET_INTERFACES = 16,
+ CMD_TYPE_GET_INTERFACE_MAP = 17,
} CmdType;
typedef enum {
char **args, **ptr;
char *host;
int port;
+ char *extra;
#ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
fprintf (stderr, "--debugger-agent is not supported on this platform.\n");
exit (1);
#endif
+ extra = getenv ("MONO_SDB_ENV_OPTIONS");
+ if (extra)
+ options = g_strdup_printf ("%s,%s", options, extra);
+
agent_config.enabled = TRUE;
agent_config.suspend = TRUE;
agent_config.server = FALSE;
}
}
+/* FIXME: Code duplication with icall.c */
+static void
+collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
+{
+ int i;
+ MonoClass *ic;
+
+ mono_class_setup_interfaces (klass, error);
+ if (!mono_error_ok (error))
+ return;
+
+ for (i = 0; i < klass->interface_count; i++) {
+ ic = klass->interfaces [i];
+ g_hash_table_insert (ifaces, ic, ic);
+
+ collect_interfaces (ic, ifaces, error);
+ if (!mono_error_ok (error))
+ return;
+ }
+}
+
static ErrorCode
type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint8 *p, guint8 *end, Buffer *buf)
{
g_free (name);
break;
}
+ case CMD_TYPE_GET_INTERFACES: {
+ MonoClass *parent;
+ GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
+ MonoError error;
+ MonoClass *tclass, *iface;
+ GHashTableIter iter;
+
+ tclass = klass;
+
+ for (parent = tclass; parent; parent = parent->parent) {
+ mono_class_setup_interfaces (parent, &error);
+ if (!mono_error_ok (&error))
+ return ERR_LOADER_ERROR;
+ collect_interfaces (parent, iface_hash, &error);
+ if (!mono_error_ok (&error))
+ return ERR_LOADER_ERROR;
+ }
+
+ buffer_add_int (buf, g_hash_table_size (iface_hash));
+
+ g_hash_table_iter_init (&iter, iface_hash);
+ while (g_hash_table_iter_next (&iter, NULL, (void**)&iface))
+ buffer_add_typeid (buf, domain, iface);
+ g_hash_table_destroy (iface_hash);
+ break;
+ }
+ case CMD_TYPE_GET_INTERFACE_MAP: {
+ int tindex, ioffset;
+ gboolean variance_used;
+ MonoClass *iclass;
+ int len, nmethods, i;
+ gpointer iter;
+ MonoMethod *method;
+
+ len = decode_int (p, &p, end);
+ mono_class_setup_vtable (klass);
+
+ for (tindex = 0; tindex < len; ++tindex) {
+ iclass = decode_typeid (p, &p, end, NULL, &err);
+ if (err)
+ return err;
+
+ ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
+ if (ioffset == -1)
+ return ERR_INVALID_ARGUMENT;
+
+ nmethods = mono_class_num_methods (iclass);
+ buffer_add_int (buf, nmethods);
+
+ iter = NULL;
+ while ((method = mono_class_get_methods (iclass, &iter))) {
+ buffer_add_methodid (buf, domain, method);
+ }
+ for (i = 0; i < nmethods; ++i)
+ buffer_add_methodid (buf, domain, klass->vtable [i + ioffset]);
+ }
+ break;
+ }
default:
return ERR_NOT_IMPLEMENTED;
}
mono_100ns_ticks (void)
{
static LARGE_INTEGER freq;
+ static UINT64 start_time;
+ UINT64 cur_time;
LARGE_INTEGER value;
- if (!freq.QuadPart && !QueryPerformanceFrequency (&freq))
- return mono_100ns_datetime ();
+ if (!freq.QuadPart) {
+ if (!QueryPerformanceFrequency (&freq))
+ return mono_100ns_datetime ();
+ QueryPerformanceCounter (&value);
+ start_time = value.QuadPart;
+ }
QueryPerformanceCounter (&value);
- return value.QuadPart * MTICKS_PER_SEC / freq.QuadPart;
+ cur_time = value.QuadPart;
+ /* we use unsigned numbers and return the difference to avoid overflows */
+ return (cur_time - start_time) * MTICKS_PER_SEC / freq.QuadPart;
}
/*