1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace Mono.Profiler.Aot
{
//
// Read the contents of a .aotprofile created by the AOT profiler
// See mono-profiler-aot.h for a description of the file format
//
public sealed class ProfileReader : ProfileBase
{
DataConverter conv;
byte[] data;
int pos;
public ProfileReader ()
{
conv = DataConverter.LittleEndian;
}
int ReadByte ()
{
int res = data [pos];
pos ++;
return res;
}
int ReadInt ()
{
int res = conv.GetInt32 (data, pos);
pos += 4;
return res;
}
string ReadString ()
{
int len = ReadInt ();
var res = new string (Encoding.UTF8.GetChars (data, pos, len));
pos += len;
return res;
}
public ProfileData ReadAllData (Stream stream)
{
byte[] buf = new byte [16];
int len = stream.Read (buf, 0, MAGIC.Length);
if (len != MAGIC.Length)
throw new IOException ("Input file is too small.");
var magic = new String (Encoding.UTF8.GetChars (buf, 0, MAGIC.Length));
if (magic != MAGIC)
throw new IOException ("Input file is not a AOT profiler output file.");
// Profile files are not expected to be large, so reading them is ok
len = (int)stream.Length - MAGIC.Length;
data = new byte [len];
pos = 0;
int count = stream.Read (data, 0, len);
if (count != len)
throw new IOException ("Can't read profile file.");
int version = ReadInt ();
int expected_version = (MAJOR_VERSION << 16) | MINOR_VERSION;
if (version != expected_version)
throw new IOException (String.Format ("Expected file version 0x{0:x}, got 0x{1:x}.", expected_version, version));
var modules = new List<ModuleRecord> ();
var types = new List<TypeRecord> ();
var methods = new List<MethodRecord> ();
Dictionary<int, ProfileRecord> records = new Dictionary<int, ProfileRecord> ();
while (true) {
RecordType rtype = (RecordType)data [pos];
pos ++;
if (rtype == RecordType.NONE)
break;
int id = ReadInt ();
switch (rtype) {
case RecordType.IMAGE: {
string name = ReadString ();
string mvid = ReadString ();
var module = new ModuleRecord (id, name, mvid);
records [id] = module;
modules.Add (module);
break;
}
case RecordType.GINST: {
int argc = ReadInt ();
TypeRecord[] tr = new TypeRecord [argc];
for (int i = 0; i < argc; ++i) {
int type_id = ReadInt ();
tr [i] = (TypeRecord)records [type_id];
}
var ginst = new GenericInstRecord (id, tr);
records [id] = ginst;
break;
}
case RecordType.TYPE: {
MonoTypeEnum ttype = (MonoTypeEnum)ReadByte ();
switch (ttype) {
case MonoTypeEnum.MONO_TYPE_CLASS: {
int image_id = ReadInt ();
int ginst_id = ReadInt ();
string name = ReadString ();
GenericInstRecord inst = null;
if (ginst_id != -1)
inst = (GenericInstRecord)records [ginst_id];
var module = (ModuleRecord)records [image_id];
var type = new TypeRecord (id, module, name, inst);
types.Add (type);
records [id] = type;
break;
}
default:
throw new NotImplementedException ();
}
break;
}
case RecordType.METHOD: {
int class_id = ReadInt ();
int ginst_id = ReadInt ();
int param_count = ReadInt ();
string name = ReadString ();
string sig = ReadString ();
var type = (TypeRecord)records [class_id];
GenericInstRecord ginst = ginst_id != -1 ? (GenericInstRecord)records [ginst_id] : null;
var method = new MethodRecord (id, type, ginst, name, sig, param_count);
methods.Add (method);
records [id] = method;
break;
}
default:
throw new NotImplementedException (rtype.ToString ());
}
}
return new ProfileData (modules.ToArray (), types.ToArray (), methods.ToArray ());
}
}
}
|