Esempio n. 1
0
        public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
        {
            uint flags = 0;

            if (MethodAddress == null)
            {
                var mangled_name = mspec.MangleMethod();
                System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: requesting run-time address for " + mangled_name);
                MethodAddress = JitOperations.GetAddressOfObject(mspec.MangleMethod());
                if (MethodAddress == null)
                {
                    System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: jit compiling method");
                    MethodAddress = JitOperations.JitCompile(this.mspec);
                }
            }
            if (MethodAddress == null)
            {
                throw new System.Reflection.TargetException("Method does not have a defined implementation (" + OwningType.FullName + "." + Name + "())");
            }
            if (!IsStatic && (obj == null))
            {
                throw new System.Reflection.TargetException("Instance method and obj is null (" + OwningType.FullName + "." + Name + "())");
            }

            // TODO: check number and type of parameters is what the method expects

            // Get total number of parameters
            int p_length = 0;

            if (parameters != null)
            {
                p_length = parameters.Length;
            }
            if (!IsStatic)
            {
                p_length++;
            }

            // See InternalStrCpy for the rationale here
            int     max_stack_alloc = p_length > 512 ? 512 : p_length;
            IntPtr *pstack          = stackalloc IntPtr[max_stack_alloc];
            IntPtr *tstack          = stackalloc IntPtr[max_stack_alloc];

            void **ps, ts;

            if (max_stack_alloc <= 512)
            {
                ps = (void **)pstack;
                ts = (void **)tstack;
            }
            else
            {
                ps = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *));
                ts = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *));
            }

            // Build a new params array to include obj if necessary, and a tysos type array
            int curptr = 0;

            if (!IsStatic)
            {
                ps[0] = CastOperations.ReinterpretAsPointer(obj);
                ts[0] = OtherOperations.GetStaticObjectAddress("_Zu1O");
                curptr++;
            }
            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++, curptr++)
                {
                    var cp = CastOperations.ReinterpretAsPointer(parameters[i]);
                    ps[curptr] = cp;
                    ts[curptr] = *(void **)cp;
                }
            }

            if (!IsStatic)
            {
                flags |= invoke_flag_instance;
            }
            if (OwningType.IsValueType)
            {
                flags |= invoke_flag_vt;
            }
            if (ReturnType != null && ReturnType.IsValueType)
            {
                flags |= invoke_flag_vt_ret;
            }

            return(CastOperations.ReinterpretAsObject(InternalInvoke(MethodAddress, p_length, ps, ts,
                                                                     (ReturnType != null) ? TysosType.ReinterpretAsType(ReturnType)._impl : null, flags)));
        }
Esempio n. 2
0
        static void Main(string[] args)
        {
            var    argc = args.Length;
            char   c;
            var    go          = new XGetoptCS.XGetopt();
            var    arg_str     = "t:L:f:e:o:d:qDC:H:m:i";
            string target      = "x86";
            string debug_file  = null;
            string output_file = null;
            string epoint      = null;
            string cfile       = null;
            string hfile       = null;
            bool   quiet       = false;
            bool   require_metadata_version_match = true;
            bool   interactive = false;
            string act_epoint  = null;
            Dictionary <string, object> opts = new Dictionary <string, object>();

            while ((c = go.Getopt(argc, args, arg_str)) != '\0')
            {
                switch (c)
                {
                case 't':
                    target = go.Optarg;
                    break;

                case 'L':
                    new_search_dirs.Add(go.Optarg);
                    break;

                case 'd':
                    debug_file = go.Optarg;
                    break;

                case 'o':
                    output_file = go.Optarg;
                    break;

                case 'e':
                    epoint = go.Optarg;
                    break;

                case 'q':
                    quiet = true;
                    break;

                case 'D':
                    require_metadata_version_match = false;
                    break;

                case 'C':
                    cfile = go.Optarg;
                    break;

                case 'H':
                    hfile = go.Optarg;
                    break;

                case 'f':
                    parse_f_option(go);
                    break;

                case 'i':
                    interactive = true;
                    break;

                case 'g':
                    do_dwarf = true;
                    break;

                case 'm':
                {
                    var    opt    = go.Optarg;
                    object optval = true;
                    if (opt.Contains("="))
                    {
                        var optvals = opt.Substring(opt.IndexOf("=") + 1);
                        opt = opt.Substring(0, opt.IndexOf("="));

                        int intval;
                        if (optvals.ToLower() == "false" || optvals.ToLower() == "off" || optvals.ToLower() == "no")
                        {
                            optval = false;
                        }
                        else if (optvals.ToLower() == "true" || optvals.ToLower() == "on" || optvals.ToLower() == "yes")
                        {
                            optval = true;
                        }
                        else if (int.TryParse(optvals, out intval))
                        {
                            optval = intval;
                        }
                        else
                        {
                            optval = optvals;
                        }
                    }
                    else if (opt.StartsWith("no-"))
                    {
                        opt    = opt.Substring(3);
                        optval = false;
                    }
                    opts[opt] = optval;
                }
                break;
                }
            }

            var fname = go.Optarg;

            if (fname == String.Empty)
            {
                Console.WriteLine("No input file specified");
                return;
            }

            // Insert library directories specified on the command line before the defaults
            search_dirs.InsertRange(0, new_search_dirs);

            if (cfile != null && hfile == null)
            {
                Console.WriteLine("-H must be used if -C is used");
                return;
            }

            libtysila5.libtysila.AssemblyLoader al = new libtysila5.libtysila.AssemblyLoader(
                new FileSystemFileLoader());

            /* Load up type forwarders */
            foreach (var libdir in search_dirs)
            {
                try
                {
                    var di = new DirectoryInfo(libdir);
                    if (di.Exists)
                    {
                        foreach (var tfw_file in di.GetFiles("*.tfw"))
                        {
                            var tfr = new StreamReader(tfw_file.OpenRead());
                            while (!tfr.EndOfStream)
                            {
                                var tfr_line   = tfr.ReadLine();
                                var tfr_lsplit = tfr_line.Split('=');
                                al.TypeForwarders[tfr_lsplit[0]] = tfr_lsplit[1];
                            }
                            tfr.Close();
                        }
                    }
                }
                catch (Exception) { }
            }

            //search_dirs.Add(@"..\mono\corlib");
            al.RequireVersionMatch = require_metadata_version_match;

            // add containing directory of input to search dirs
            var ifi = new FileInfo(fname);

            search_dirs.Add(ifi.DirectoryName);

            var m = al.GetAssembly(fname);

            if (m == null)
            {
                Console.WriteLine("Input file " + fname + " not found");
                throw new Exception(fname + " not found");
            }

            t = libtysila5.target.Target.targets[target];
            // try and set target options
            foreach (var kvp in opts)
            {
                if (!t.Options.TrySet(kvp.Key, kvp.Value))
                {
                    Console.WriteLine("Unable to set target option " + kvp.Key + " to " + kvp.Value.ToString());
                    return;
                }
            }

            if (interactive)
            {
                if (new Interactive(m, t).DoInteractive() == false)
                {
                    return;
                }
            }

            libtysila5.dwarf.DwarfCU dwarf = null;
            if (do_dwarf)
            {
                dwarf = new libtysila5.dwarf.DwarfCU(t, m);
            }

            libtysila5.TysilaState s = new libtysila5.TysilaState();

            if (output_file != null)
            {
                var bf = new binary_library.elf.ElfFile(binary_library.Bitness.Bits32);
                s.bf = bf;
                bf.Init();
                bf.Architecture = target;
                var st = new libtysila5.StringTable(
                    m.GetStringEntry(metadata.MetadataStream.tid_Module,
                                     1, 1), al, t);
                s.st = st;
                s.r  = new libtysila5.CachingRequestor(m);
                t.InitIntcalls();

                /* for now, just assemble all public and protected
                 * non-generic methods in public types, plus the
                 * entry point */
                StringBuilder debug = new StringBuilder();
                for (int i = 1; i <= m.table_rows[metadata.MetadataStream.tid_MethodDef]; i++)
                {
                    metadata.MethodSpec ms = new metadata.MethodSpec
                    {
                        m     = m,
                        mdrow = i,
                        msig  = 0
                    };

                    ms.type = new metadata.TypeSpec
                    {
                        m     = m,
                        tdrow = m.methoddef_owners[ms.mdrow]
                    };

                    var mflags = m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                               i, 2);
                    var tflags = m.GetIntEntry(metadata.MetadataStream.tid_TypeDef,
                                               ms.type.tdrow, 0);

                    mflags &= 0x7;
                    tflags &= 0x7;

                    ms.msig = (int)m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                                 i, 4);

                    /* See if this is the entry point */
                    int tid, row;
                    m.InterpretToken(m.entry_point_token, out tid, out row);
                    if (tid == metadata.MetadataStream.tid_MethodDef)
                    {
                        if (row == i)
                        {
                            if (epoint != null)
                            {
                                ms.aliases = new List <string> {
                                    epoint
                                }
                            }
                            ;

                            mflags = 6;
                            tflags = 1;

                            ms.AlwaysCompile = true;
                            act_epoint       = ms.MangleMethod();
                        }
                    }

                    /* See if we have an always compile attribute */
                    if (ms.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs22AlwaysCompileAttribute_7#2Ector_Rv_P1u1t") ||
                        ms.type.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs22AlwaysCompileAttribute_7#2Ector_Rv_P1u1t"))
                    {
                        mflags = 6;
                        tflags = 1;

                        ms.AlwaysCompile = true;
                    }

                    if (ms.type.IsGenericTemplate == false &&
                        ms.IsGenericTemplate == false &&
                        (mflags == 0x4 || mflags == 0x5 || mflags == 0x6) &&
                        tflags != 0)
                    {
                        s.r.MethodRequestor.Request(ms);
                    }
                }

                /* Also assemble all public non-generic type infos */
                for (int i = 1; i <= m.table_rows[metadata.MetadataStream.tid_TypeDef]; i++)
                {
                    var flags = (int)m.GetIntEntry(metadata.MetadataStream.tid_TypeDef,
                                                   i, 0);
                    if (((flags & 0x7) != 0x1) &&
                        ((flags & 0x7) != 0x2))
                    {
                        continue;
                    }
                    var ts = new metadata.TypeSpec {
                        m = m, tdrow = i
                    };
                    if (ts.IsGeneric)
                    {
                        continue;
                    }
                    s.r.StaticFieldRequestor.Request(ts);
                    s.r.VTableRequestor.Request(ts.Box);
                }

                /* If corlib, add in the default equality comparers so we don't have to jit these
                 * commonly used classes */
                if (m.is_corlib)
                {
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemByte }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt8 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt16 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt16 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt32 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt32 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt64 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt64 }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemString }), ".ctor"));
                    s.r.MethodRequestor.Request(m.GetMethodSpec(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemObject }), ".ctor"));

                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemByte }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt8 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt16 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt16 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt32 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt32 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemInt64 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemUInt64 }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemString }));
                    s.r.VTableRequestor.Request(m.GetTypeSpec("System.Collections.Generic", "GenericEqualityComparer`1", new metadata.TypeSpec[] { m.SystemObject }));
                }

                /* Generate a thread-local data section.  We may not use it. */
                var tlsos = bf.CreateContentsSection();
                tlsos.Name          = ".tdata";
                tlsos.IsAlloc       = true;
                tlsos.IsExecutable  = false;
                tlsos.IsWriteable   = true;
                tlsos.IsThreadLocal = true;

                while (!s.r.Empty)
                {
                    if (!s.r.MethodRequestor.Empty)
                    {
                        var ms = s.r.MethodRequestor.GetNext();

                        ISection tsect    = null;
                        ISection datasect = null;
                        if (func_sects && !ms.ms.AlwaysCompile)
                        {
                            tsect    = get_decorated_section(bf, bf.GetTextSection(), "." + ms.ms.MangleMethod());
                            datasect = get_decorated_section(bf, bf.GetDataSection(), "." + ms.ms.MangleMethod() + "_SignatureTable");
                        }
                        else if (class_sects && !ms.ms.AlwaysCompile)
                        {
                            tsect    = get_decorated_section(bf, bf.GetTextSection(), "." + ms.ms.type.MangleType());
                            datasect = get_decorated_section(bf, bf.GetDataSection(), "." + ms.ms.type.MangleType() + "_SignatureTable");
                        }

                        libtysila5.libtysila.AssembleMethod(ms.ms,
                                                            bf, t, s, debug, m, ms.c, tsect, datasect, dwarf);
                        if (!quiet)
                        {
                            Console.WriteLine(ms.ms.m.MangleMethod(ms.ms));
                        }
                    }
                    else if (!s.r.StaticFieldRequestor.Empty)
                    {
                        var sf = s.r.StaticFieldRequestor.GetNext();

                        ISection tsect = null;
                        if (data_sects && !sf.AlwaysCompile)
                        {
                            tsect = get_decorated_section(bf, bf.GetDataSection(), "." + sf.MangleType() + "S");
                        }
                        else if (class_sects && !sf.AlwaysCompile)
                        {
                            tsect = get_decorated_section(bf, bf.GetDataSection(), "." + sf.MangleType() + "S");
                        }

                        libtysila5.layout.Layout.OutputStaticFields(sf,
                                                                    t, bf, m, tsect, tlsos);
                        if (!quiet)
                        {
                            Console.WriteLine(sf.MangleType() + "S");
                        }
                    }
                    else if (!s.r.EHRequestor.Empty)
                    {
                        var eh = s.r.EHRequestor.GetNext();

                        ISection tsect = null;
                        if (func_sects && !eh.ms.AlwaysCompile)
                        {
                            tsect = get_decorated_section(bf, bf.GetRDataSection(), "." + eh.ms.MangleMethod() + "EH");
                        }
                        else if (class_sects && !eh.ms.AlwaysCompile)
                        {
                            tsect = get_decorated_section(bf, bf.GetRDataSection(), "." + eh.ms.type.MangleType() + "EH");
                        }

                        libtysila5.layout.Layout.OutputEHdr(eh,
                                                            t, bf, s, m, tsect);
                        if (!quiet)
                        {
                            Console.WriteLine(eh.ms.MangleMethod() + "EH");
                        }
                    }
                    else if (!s.r.VTableRequestor.Empty)
                    {
                        var vt = s.r.VTableRequestor.GetNext();

                        ISection tsect     = null;
                        ISection data_sect = null;
                        if (data_sects && !vt.AlwaysCompile)
                        {
                            tsect     = get_decorated_section(bf, bf.GetRDataSection(), "." + vt.MangleType());
                            data_sect = get_decorated_section(bf, bf.GetDataSection(), "." + vt.MangleType() + "_SignatureTable");
                        }
                        else if (class_sects && !vt.AlwaysCompile)
                        {
                            tsect     = get_decorated_section(bf, bf.GetTextSection(), "." + vt.MangleType());
                            data_sect = get_decorated_section(bf, bf.GetDataSection(), "." + vt.MangleType() + "_SignatureTable");
                        }

                        libtysila5.layout.Layout.OutputVTable(vt,
                                                              t, bf, s, m, tsect, data_sect);
                        if (!quiet)
                        {
                            Console.WriteLine(vt.MangleType());
                        }
                    }
                    else if (!s.r.DelegateRequestor.Empty)
                    {
                        var d = s.r.DelegateRequestor.GetNext();
                        libtysila5.ir.ConvertToIR.CreateDelegate(d, t, s);
                        if (!quiet)
                        {
                            Console.WriteLine(d.MangleType() + "D");
                        }
                    }
                    else if (!s.r.BoxedMethodRequestor.Empty)
                    {
                        var bm = s.r.BoxedMethodRequestor.GetNext();

                        ISection tsect = null;
                        if (func_sects && !bm.ms.AlwaysCompile)
                        {
                            tsect = get_decorated_section(bf, bf.GetTextSection(), "." + bm.ms.MangleMethod());
                        }
                        else if (class_sects && !bm.ms.AlwaysCompile)
                        {
                            tsect = get_decorated_section(bf, bf.GetTextSection(), "." + bm.ms.type.MangleType());
                        }

                        libtysila5.libtysila.AssembleBoxedMethod(bm.ms,
                                                                 bf, t, s, debug, tsect);
                        if (!quiet)
                        {
                            Console.WriteLine(bm.ms.MangleMethod());
                        }
                    }
                }

                if (debug_file != null)
                {
                    string d = debug.ToString();

                    StreamWriter sw = new StreamWriter(debug_file);
                    sw.Write(d);
                    sw.Close();
                }

                if (tlsos.Length > 0)
                {
                    bf.AddSection(tlsos);
                }

                /* String table */
                st.WriteToOutput(bf, m, t);

                /* Include original metadata */
                var rdata = bf.GetRDataSection();
                rdata.Align(t.GetPointerSize());
                var mdsym = bf.CreateSymbol();
                mdsym.Name       = m.AssemblyName;
                mdsym.ObjectType = binary_library.SymbolObjectType.Object;
                mdsym.Offset     = (ulong)rdata.Data.Count;
                mdsym.Type       = binary_library.SymbolType.Global;
                var len = m.file.GetLength();
                mdsym.Size = len;
                rdata.AddSymbol(mdsym);

                for (int i = 0; i < len; i++)
                {
                    rdata.Data.Add(m.file.ReadByte(i));
                }

                var mdsymend = bf.CreateSymbol();
                mdsymend.Name       = m.AssemblyName + "_end";
                mdsymend.ObjectType = binary_library.SymbolObjectType.Object;
                mdsymend.Offset     = (ulong)rdata.Data.Count;
                mdsymend.Type       = binary_library.SymbolType.Global;
                mdsymend.Size       = 0;
                rdata.AddSymbol(mdsymend);

                /* Add resource symbol if present */
                if (m.GetPEFile().ResourcesSize != 0)
                {
                    var rsym = bf.CreateSymbol();
                    rsym.Name       = m.AssemblyName + "_resources";
                    rsym.ObjectType = SymbolObjectType.Object;
                    rsym.Offset     = (ulong)m.GetPEFile().ResourcesOffset + mdsym.Offset;
                    rsym.Type       = SymbolType.Global;
                    rsym.Size       = m.GetPEFile().ResourcesSize;
                    rdata.AddSymbol(rsym);
                }

                /* Add comment */
                var csect = bf.CreateContentsSection();
                csect.IsAlloc      = false;
                csect.IsExecutable = false;
                csect.IsWriteable  = false;
                csect.Name         = ".comment";
                var cbytes = Encoding.ASCII.GetBytes(comment);
                foreach (var cbyte in cbytes)
                {
                    csect.Data.Add(cbyte);
                }
                csect.Data.Add(0);
                if (act_epoint != null)
                {
                    var epbytes = Encoding.ASCII.GetBytes("entry: " +
                                                          act_epoint);
                    foreach (var epbyte in epbytes)
                    {
                        csect.Data.Add(epbyte);
                    }
                    csect.Data.Add(0);
                }
                bf.AddSection(csect);

                /* Add debugger sections */
                if (dwarf != null)
                {
                    var dwarf_sects = new libtysila5.dwarf.DwarfSections(bf);
                    dwarf.WriteToOutput(dwarf_sects);
                }


                /* Write output file */
                bf.Filename = output_file;
                bf.Write();
            }

            if (hfile != null)
            {
                COutput.WriteHeader(m, t, hfile, cfile);
            }
        }