void do_read_variables(TargetMemoryAccess memory)
{
if (!is_loaded)
throw new TargetException (TargetError.MethodNotLoaded);
if (has_variables)
return;
MonoLanguageBackend mono = file.MonoLanguage;
TargetAddress decl_klass = mono.MetadataHelper.MonoMethodGetClass (
memory, address.MonoMethod);
TargetType decl = mono.ReadMonoClass (memory, decl_klass);
if (decl.HasClassType)
decl_type = decl.ClassType;
else
decl_type = (TargetClassType) decl;
do_read_blocks ();
locals = new List<TargetVariable> ();
parameters = new List<TargetVariable> ();
scopes = new Dictionary<int,ScopeInfo> ();
var captured_vars = new Dictionary<string,CapturedVariable> ();
if (address.HasThis)
this_var = new MonoVariable (
"this", decl_type, true, true, this,
address.ThisVariableInfo);
var scope_list = new List<ScopeInfo> ();
C.ScopeVariable[] scope_vars = method.GetScopeVariables ();
int num_scope_vars = scope_vars != null ? scope_vars.Length : 0;
for (int i = 0; i < num_scope_vars; i++) {
C.ScopeVariable sv = scope_vars [i];
VariableInfo var;
if (sv.Index < 0) {
var = address.ThisVariableInfo;
this_is_captured = true;
this_var = null;
} else
var = address.LocalVariableInfo [sv.Index];
try {
TargetClassType type = mono.ReadStructType (memory, var.MonoType);
MonoVariable scope_var = new MonoVariable (
"$__" + sv.Scope, type, true, type.IsByRef, this, var);
ScopeInfo info = new ScopeInfo (sv.Scope, scope_var, type);
scopes.Add (sv.Scope, info);
scope_list.Add (info);
} catch (Exception ex) {
Report.Error ("Cannot read scope variable: {0}\n{1}", var, ex);
}
}
foreach (ScopeInfo scope in scope_list) {
read_scope (scope);
}
foreach (ScopeInfo scope in scopes.Values) {
C.AnonymousScopeEntry entry = file.File.GetAnonymousScope (scope.ID);
foreach (C.CapturedVariable captured in entry.CapturedVariables) {
CapturedVariable cv = new CapturedVariable (
scope, this, captured.Name, captured.CapturedName);
switch (captured.Kind) {
case C.CapturedVariable.CapturedKind.Local:
locals.Add (cv);
break;
case C.CapturedVariable.CapturedKind.Parameter:
parameters.Add (cv);
break;
case C.CapturedVariable.CapturedKind.This:
if (!cv.Resolve (memory))
throw new InternalError ();
if (cv.Type.HasClassType)
decl_type = cv.Type.ClassType;
else
decl_type = (TargetClassType) cv.Type;
this_var = cv;
continue;
default:
throw new InternalError ();
}
captured_vars.Add (captured.Name, cv);
}
}
Cecil.ParameterDefinitionCollection param_info = mdef.Parameters;
for (int i = 0; i < param_info.Count; i++) {
if (captured_vars.ContainsKey (param_info [i].Name))
continue;
VariableInfo var = address.ParamVariableInfo [i];
TargetType type = mono.ReadType (memory, var.MonoType);
if (type == null)
type = mono.VoidType;
parameters.Add (new MonoVariable (
param_info [i].Name, type, false, type.IsByRef,
this, var, 0, 0));
}
C.LocalVariableEntry[] symfile_locals = method.GetLocals ();
for (int i = 0; i < symfile_locals.Length; i++) {
C.LocalVariableEntry local = symfile_locals [i];
if (captured_vars.ContainsKey (local.Name))
continue;
VariableInfo var = address.LocalVariableInfo [local.Index];
TargetType type = mono.ReadType (memory, var.MonoType);
if (type == null)
type = mono.VoidType;
if (local.BlockIndex > 0) {
int index = local.BlockIndex - 1;
MonoCodeBlock block = code_blocks [index];
locals.Add (new MonoVariable (
local.Name, type, true, type.IsByRef, this, var,
block.StartAddress, block.EndAddress));
} else {
locals.Add (new MonoVariable (
local.Name, type, true, type.IsByRef, this, var));
}
}
has_variables = true;
}