Example #1
0
        public KoiStream(string name, IReadableSegment contents, ILogger logger)
            : base(name, contents)
        {
            var reader = contents.CreateReader();

            logger.Debug(Tag, "Reading koi stream header...");
            uint magic = reader.ReadUInt32();

            if (magic != Signature)
            {
                logger.Warning(Tag, $"Koi stream data does not start with a valid signature (Expected 0x{Signature:X4} but read 0x{magic:X4}).");
            }

            uint mdCount  = reader.ReadUInt32();
            uint strCount = reader.ReadUInt32();
            uint expCount = reader.ReadUInt32();

            logger.Debug(Tag, $"Reading {mdCount} references...");
            for (int i = 0; i < mdCount; i++)
            {
                uint id    = Utils.ReadCompressedUInt(ref reader);
                uint token = Utils.FromCodedToken(Utils.ReadCompressedUInt(ref reader));
                References.Add(id, new MetadataToken(token));
            }

            logger.Debug(Tag, $"Reading {strCount} strings...");
            for (int i = 0; i < strCount; i++)
            {
                uint id     = Utils.ReadCompressedUInt(ref reader);
                int  length = (int)Utils.ReadCompressedUInt(ref reader);

                byte[] buffer = new byte[length * 2];
                reader.ReadBytes(buffer, 0, buffer.Length);
                Strings.Add(id, Encoding.Unicode.GetString(buffer));
            }

            logger.Debug(Tag, $"Reading {expCount} exports...");
            for (int i = 0; i < expCount; i++)
            {
                uint id         = Utils.ReadCompressedUInt(ref reader);
                var  exportInfo = VMExportInfo.FromReader(ref reader);

                // Exports in KoiVM either point to entrypoints of virtualised methods, or just act as a descriptor
                // for methods that are intra linked through instructions like ldftn.

                if (exportInfo.IsSignatureOnly)
                {
                    logger.Debug(Tag, $"Export {id} maps to a method signature of an intra-linked method.");
                }
                else
                {
                    logger.Debug(Tag, $"Export {id} maps to function_{exportInfo.EntrypointAddress:X4}.");
                }

                Exports.Add(id, exportInfo);
            }
        }
Example #2
0
        public static KoiStream FromReadingContext(ReadingContext context, ILogger logger)
        {
            var reader = context.Reader;
            var result = new KoiStream {
                StartOffset = reader.Position
            };

            logger.Debug(Tag, "Reading koi stream header...");
            uint magic = reader.ReadUInt32();

            if (magic != Signature)
            {
                logger.Warning(Tag, $"Koi stream data does not start with a valid signature (Expected 0x{Signature:X4} but read 0x{magic:X4}).");
            }

            uint mdCount  = reader.ReadUInt32();
            uint strCount = reader.ReadUInt32();
            uint expCount = reader.ReadUInt32();

            logger.Debug(Tag, $"Reading {mdCount} references...");
            for (int i = 0; i < mdCount; i++)
            {
                uint id    = Utils.ReadCompressedUInt(reader);
                uint token = Utils.FromCodedToken(Utils.ReadCompressedUInt(reader));
                result.References.Add(id, new MetadataToken(token));
            }

            logger.Debug(Tag, $"Reading {strCount} strings...");
            for (int i = 0; i < strCount; i++)
            {
                uint id     = Utils.ReadCompressedUInt(reader);
                int  length = (int)Utils.ReadCompressedUInt(reader);

                result.Strings.Add(id, Encoding.Unicode.GetString(reader.ReadBytes(length * 2)));
            }

            logger.Debug(Tag, $"Reading {expCount} exports...");
            for (int i = 0; i < expCount; i++)
            {
                uint id         = Utils.ReadCompressedUInt(reader);
                var  exportInfo = VMExportInfo.FromReader(reader);

                // Exports in KoiVM either point to entrypoints of virtualised methods, or just act as a descriptor
                // for methods that are intra linked through instructions like ldftn.

                if (exportInfo.IsSignatureOnly)
                {
                    logger.Debug(Tag, $"Export {id} maps to a method signature of an intra-linked method.");
                }
                else
                {
                    logger.Debug(Tag, $"Export {id} maps to function_{exportInfo.EntrypointAddress:X4}.");
                }

                result.Exports.Add(id, exportInfo);
            }

            reader.Position = reader.StartPosition;
            result.Data     = reader.ReadBytes((int)reader.Length);

            return(result);
        }