Beispiel #1
0
 public static TypeUnit FromArgument(Argument arg)
 {
     switch (arg.type)
     {
         case VariableType.Normal:
             return FromTag(arg.tag);
         case VariableType.Array:
         case VariableType.ArrayReference:
             return new TypeUnit(new PawnType(arg.tag), arg.dimensions.Length);
     }
     return null;
 }
Beispiel #2
0
        public SourcePawnFile(byte[] binary)
        {
            BinaryReader reader = new BinaryReader(new MemoryStream(binary));
            header_.magic = reader.ReadUInt32();
            if (header_.magic != MAGIC)
                throw new Exception("bad magic - not SourcePawn file");
            header_.version = reader.ReadUInt16();
            header_.compression = (Compression)reader.ReadByte();
            header_.disksize = (int)reader.ReadUInt32();
            header_.imagesize = (int)reader.ReadUInt32();
            header_.sections = (int)reader.ReadByte();
            header_.stringtab = (int)reader.ReadUInt32();
            header_.dataoffs = (int)reader.ReadUInt32();

            sections_ = new Dictionary<string, Section>();

            // There was a brief period of incompatibility, where version == 0x0101
            // and the packing changed, at the same time .dbg.ntvarg was introduced.
            // Once the incompatibility was noted, version was bumped to 0x0102.
            debugUnpacked_ = (header_.version == 0x0101) && !sections_.ContainsKey(".dbg.natives");

            switch (header_.compression)
            {
                case Compression.Gzip:
                {
                    byte[] bits = new byte[header_.imagesize];
                    for (int i = 0; i < header_.dataoffs; i++)
                        bits[i] = binary[i];

                    int uncompressedSize = header_.imagesize - header_.dataoffs;
                    int compressedSize = header_.disksize - header_.dataoffs;
                    MemoryStream ms = new MemoryStream(binary, header_.dataoffs + 2, compressedSize - 2);
                    DeflateStream gzip = new DeflateStream(ms, CompressionMode.Decompress);

					int actualSize = gzip.Read(bits, header_.dataoffs, uncompressedSize);
					//Debug.Assert(actualSize == uncompressedSize, "uncompressed size mismatch, bad file?");

                    binary = bits;
                    break;
                }
            }

            // Read sections.
            for (int i = 0; i < header_.sections; i++)
            {
                int nameOffset = (int)reader.ReadUInt32();
                int dataoffs = (int)reader.ReadUInt32();
                int size = (int)reader.ReadUInt32();
                string name = ReadString(binary, header_.stringtab + nameOffset, header_.dataoffs);
                sections_[name] = new Section(dataoffs, size);
            }

            if (sections_.ContainsKey(".code"))
            {
                Section sc = sections_[".code"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                uint codesize = br.ReadUInt32();
                byte cellsize = br.ReadByte();
                byte codeversion = br.ReadByte();
                ushort flags = br.ReadUInt16();
                uint main = br.ReadUInt32();
                uint codeoffs = br.ReadUInt32();
                byte[] codeBytes = Slice(binary, sc.dataoffs + (int)codeoffs, (int)codesize);
                code_ = new Code(codeBytes, (int)flags, (int)codeversion);
            }

            if (sections_.ContainsKey(".data"))
            {
                Section sc = sections_[".data"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                uint datasize = br.ReadUInt32();
                uint memsize = br.ReadUInt32();
                uint dataoffs = br.ReadUInt32();
                byte[] dataBytes = Slice(binary, sc.dataoffs + (int)dataoffs, (int)datasize);
                data_ = new Data(dataBytes, (int)memsize);
            }

            if (sections_.ContainsKey(".publics"))
            {
                Section sc = sections_[".publics"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                int numPublics = sc.size / 8;
                publics_ = new Public[numPublics];
                for (int i = 0; i < numPublics; i++)
                {
                    uint address = br.ReadUInt32();
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".names"].dataoffs + (int)nameOffset, header_.dataoffs);
                    publics_[i] = new Public(name, address);
                }
            }

            if (sections_.ContainsKey(".pubvars"))
            {
                Section sc = sections_[".pubvars"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                int numPubVars = sc.size / 8;
                pubvars_ = new PubVar[numPubVars];
                for (int i = 0; i < numPubVars; i++)
                {
                    uint address = br.ReadUInt32();
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".names"].dataoffs + (int)nameOffset, header_.dataoffs);
                    pubvars_[i] = new PubVar(name, address);
                }
            }

            if (sections_.ContainsKey(".natives"))
            {
                Section sc = sections_[".natives"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                int numNatives = sc.size / 4;
                natives_ = new Native[numNatives];
                for (int i = 0; i < numNatives; i++)
                {
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".names"].dataoffs + (int)nameOffset, header_.dataoffs);
                    natives_[i] = new Native(name, i);
                }
            }

            if (sections_.ContainsKey(".tags"))
            {
                Section sc = sections_[".tags"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                int numTags = sc.size / 8;
                tags_ = new Tag[numTags];
                for (int i = 0; i < numTags; i++)
                {
                    uint tag_id = br.ReadUInt32();
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".names"].dataoffs + (int)nameOffset, header_.dataoffs);
                    tags_[i] = new Tag(name, tag_id);
                }
            }

            if (sections_.ContainsKey(".dbg.info"))
            {
                Section sc = sections_[".dbg.info"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                debugHeader_.numFiles = (int)br.ReadUInt32();
                debugHeader_.numLines = (int)br.ReadUInt32();
                debugHeader_.numSyms = (int)br.ReadUInt32();
            }

            if (sections_.ContainsKey(".dbg.files") && debugHeader_.numFiles > 0)
            {
                Section sc = sections_[".dbg.files"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                debugFiles_ = new DebugFile[debugHeader_.numFiles];
                for (int i = 0; i < debugHeader_.numFiles; i++)
                {
                    uint address = br.ReadUInt32();
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".dbg.strings"].dataoffs + (int)nameOffset, header_.dataoffs);
                    debugFiles_[i] = new DebugFile(name, nameOffset);
                }
            }

            if (sections_.ContainsKey(".dbg.lines") && debugHeader_.numLines > 0)
            {
                Section sc = sections_[".dbg.lines"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                debugLines_ = new DebugLine[debugHeader_.numLines];
                for (int i = 0; i < debugHeader_.numLines; i++)
                {
                    uint address = br.ReadUInt32();
                    uint line = br.ReadUInt32();
                    debugLines_[i] = new DebugLine((int)line, address);
                }
            }

            if (sections_.ContainsKey(".dbg.symbols") && debugHeader_.numSyms > 0)
            {
                Section sc = sections_[".dbg.symbols"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                List<Variable> locals = new List<Variable>();
                List<Variable> globals = new List<Variable>();
                List<Function> functions = new List<Function>();
                for (int i = 0; i < debugHeader_.numSyms; i++)
                {
                    int addr = br.ReadInt32();
                    short tagid = br.ReadInt16();
                    uint codestart = br.ReadUInt32();
                    uint codeend = br.ReadUInt32();
                    byte ident = br.ReadByte();
                    Scope vclass = (Scope)br.ReadByte();
                    ushort dimcount = br.ReadUInt16();
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".dbg.strings"].dataoffs + (int)nameOffset, header_.dataoffs);

                    if (ident == IDENT_FUNCTION)
                    {
                        Tag tag = tagid >= tags_.Length ? null : tags_[tagid];
                        Function func = new Function((uint)addr, codestart, codeend, name, tag);
                        functions.Add(func);
                    }
                    else
                    {
                        VariableType type = FromIdent(ident);
                        Dimension[] dims = null;
                        if (dimcount > 0)
                        {
                            dims = new Dimension[dimcount];
                            for (int dim = 0; dim < dimcount; dim++)
                            {
                                short dim_tagid = br.ReadInt16();
                                Tag dim_tag = dim_tagid >= tags_.Length ? null : tags_[dim_tagid];
                                uint size = br.ReadUInt32();
                                dims[dim] = new Dimension(dim_tagid, dim_tag, (int)size);
                            }
                        }

                        Tag tag = tagid >= tags_.Length ? null : tags_[tagid];
                        Variable var = new Variable(addr, tagid, tag, codestart, codeend, type, vclass, name, dims);
                        if (vclass == Scope.Global)
                            globals.Add(var);
                        else
                            locals.Add(var);
                    }
                }

                globals.Sort(delegate(Variable var1, Variable var2)
                {
                    return var1.address - var2.address;
                });
                functions.Sort(delegate(Function fun1, Function fun2)
                {
                    return (int)(fun1.address - fun2.address);
                });

                variables_ = locals.ToArray();
                globals_ = globals.ToArray();
                functions_ = functions.ToArray();
            }

            if (sections_.ContainsKey(".dbg.natives"))
            {
                Section sc = sections_[".dbg.natives"];
                BinaryReader br = new BinaryReader(new MemoryStream(binary, sc.dataoffs, sc.size));
                uint nentries = br.ReadUInt32();
                for (int i = 0; i < (int)nentries; i++)
                {
                    uint index = br.ReadUInt32();
                    uint nameOffset = br.ReadUInt32();
                    string name = ReadString(binary, sections_[".dbg.strings"].dataoffs + (int)nameOffset, header_.dataoffs);
                    short tagid = br.ReadInt16();
                    Tag tag = tagid >= tags_.Length ? null : tags_[tagid];
                    ushort nargs = br.ReadUInt16();

                    Argument[] args = new Argument[nargs];
                    for (ushort arg = 0; arg < nargs; arg++)
                    {
                        byte ident = br.ReadByte();
                        short arg_tagid = br.ReadInt16();
                        ushort dimcount = br.ReadUInt16();
                        uint argNameOffset = br.ReadUInt32();
                        string argName = ReadString(binary, sections_[".dbg.strings"].dataoffs + (int)argNameOffset, header_.dataoffs);
                        Tag argTag = arg_tagid >= tags_.Length ? null : tags_[arg_tagid];
                        VariableType type = FromIdent(ident);

                        Dimension[] dims = null;
                        if (dimcount > 0)
                        {
                            dims = new Dimension[dimcount];
                            for (int dim = 0; dim < dimcount; dim++)
                            {
                                short dim_tagid = br.ReadInt16();
                                Tag dim_tag = dim_tagid >= tags_.Length ? null : tags_[dim_tagid];
                                uint size = br.ReadUInt32();
                                dims[dim] = new Dimension(dim_tagid, dim_tag, (int)size);
                            }
                        }

                        args[arg] = new Argument(type, argName, arg_tagid, argTag, dims);
                    }

                    if ((int)index >+ natives_.Length)
                        continue;

                    natives_[index].setDebugInfo(tagid, tag, args);
                }
            }

            // For every function, attempt to build argument information.
            for (int i = 0; i < functions_.Length; i++)
            {
                Function fun = functions_[i];
                int argOffset = 12;
                var args = new List<Argument>();
                do
                {
                    Variable var = lookupVariable(fun.address, argOffset);
                    if (var == null)
                        break;
                    Argument arg = new Argument(var.type, var.name, (int)var.tag.tag_id, var.tag, var.dims);
                    args.Add(arg);
                    argOffset += 4;
                } while (true);
                fun.setArguments(args);
            }
        }
Beispiel #3
0
 public void setDebugInfo(int tag_id, Tag tag, Argument[] args)
 {
     tag_id_ = (uint)tag_id;
     tag_ = tag;
     args_ = args;
 }
Beispiel #4
0
 private string buildArgDeclaration(Argument arg)
 {
     string prefix = arg.type == VariableType.Reference
                     ? "&"
                     : "";
     string decl = prefix + buildTag(arg.tag) + arg.name;
     if (arg.dimensions != null)
     {
         for (int i = 0; i < arg.dimensions.Length; i++)
         {
             Dimension dim = arg.dimensions[i];
             decl += "[";
             if (dim.size >= 1)
             {
                 if (arg.tag != null && arg.tag.name == "String")
                     decl += dim.size * 4;
                 else
                     decl += dim.size;
             }
             decl += "]";
         }
     }
     return decl;
 }