static int Main(string[] args) { /* Parse args */ var argc = args.Length; char c; var go = new XGetoptCS.XGetopt(); var arg_str = "t:L:o:"; while ((c = go.Getopt(argc, args, arg_str)) != '\0') { switch (c) { case 't': arch = go.Optarg; break; case 'L': new_search_dirs.Add(go.Optarg); break; case 'o': output_name = go.Optarg; break; case '?': dump_opts(); return(-1); } } tysila4.Program.search_dirs.InsertRange(0, new_search_dirs); var curopt = go.Optind; while (curopt < argc) { input_files.Add(args[curopt++]); } if (input_files.Count == 0) { System.Console.WriteLine("No input files specified"); dump_opts(); return(-1); } /* Load up each input file in turn */ var ifiles = new List <binary_library.IBinaryFile>(); foreach (var ifname in input_files) { var ifinfo = new System.IO.FileInfo(ifname); if (!ifinfo.Exists) { throw new System.IO.FileNotFoundException("Cannot find: " + ifname); } /* Determine file type from extension */ binary_library.IBinaryFile ifobj = null; if (ifinfo.Extension == ".o" || ifinfo.Extension == ".obj") { ifobj = new binary_library.elf.ElfFile(); } if (ifobj == null) { ifobj = binary_library.BinaryFile.CreateBinaryFile(ifinfo.Extension); } if (ifobj == null) { throw new Exception("Unsupported file type: " + ifinfo.FullName); } /* Load up the particular file */ ifobj.Filename = ifinfo.FullName; ifobj.Read(); ifiles.Add(ifobj); } /* Get a list of all defined symbols */ var def_syms = new Dictionary <string, binary_library.ISymbol>(); foreach (var file in ifiles) { var sym_count = file.GetSymbolCount(); for (int i = 0; i < sym_count; i++) { var sym = file.GetSymbol(i); if (sym.DefinedIn != null && sym.Type != binary_library.SymbolType.Undefined) { def_syms[sym.Name] = sym; } } } /* Get a list of those relocations which are missing */ var missing = new Dictionary <string, binary_library.ISymbol>(); foreach (var file in ifiles) { var reloc_count = file.GetRelocationCount(); for (int i = 0; i < reloc_count; i++) { var reloc = file.GetRelocation(i); if (reloc.References != null && !def_syms.ContainsKey(reloc.References.Name)) { if (reloc.References.Name == "_Zu1O_7#2Ector_Rv_P1u1t") { System.Diagnostics.Debugger.Break(); } missing[reloc.References.Name] = reloc.References; } } } /* Generate an output object */ var o = new binary_library.elf.ElfFile(ifiles[0].Bitness); o.Init(); o.Architecture = arch; o.Filename = output_name; /* Generate dummy module */ var ofi = new System.IO.FileInfo(output_name); var ms = new metadata.MetadataStream(ofi.Name.Substring(0, ofi.Name.Length - ofi.Extension.Length)); ms.al = new libtysila5.libtysila.AssemblyLoader(new tysila4.FileSystemFileLoader()); ms.LoadBuiltinTypes(); /* Load up assembler target */ var t = libtysila5.target.Target.targets[arch]; var fsi = new System.IO.FileInfo(output_name); var s = new libtysila5.TysilaState(); s.st = new libtysila5.StringTable(fsi.Name.Substring(0, fsi.Name.Length - fsi.Extension.Length), ms.al, t); /* Generate signature of missing_function(string) to call */ var special_c = new libtysila5.Code { ms = new metadata.MethodSpec { m = ms } }; var special = special_c.special_meths; var missing_msig = special.CreateMethodSignature(null, new metadata.TypeSpec[] { ms.SystemString }); /* Generate stub functions for missing methods */ var m = missing.Keys; var missing_types = new List <string>(); var other_missing = new List <string>(); foreach (var str in m) { try { if (ms.IsMangledMethod(str)) { GenerateMissingMethod(str, ms, t, missing_msig, o, s); } else { ms.IsMangledMethod(str); missing_types.Add(str); } } catch (ArgumentException) { other_missing.Add(str); } } /* Write out */ s.st.WriteToOutput(o, ms, t); o.Write(); /* Dump missing types */ if (missing_types.Count > 0) { Console.WriteLine("Warning: the following missing types were also found:"); foreach (var mt in missing_types) { Console.WriteLine(" " + mt); } } return(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); } }