Beispiel #1
0
        protected override AssemblerState CreateAssemblerState(binary_library.IBinaryFile file)
        {
            AssemblerState ret = base.CreateAssemblerState(file);

            ret.cur_bitness = binary_library.Bitness.Bits32;
            return(ret);
        }
Beispiel #2
0
        public void WriteToOutput(binary_library.IBinaryFile of,
                                  metadata.MetadataStream ms, target.Target t,
                                  binary_library.ISection rd = null)
        {
            if (str_tab.Count == 0)
            {
                return;
            }

            if (rd == null)
            {
                rd = of.GetRDataSection();
            }
            rd.Align(t.GetCTSize(ir.Opcode.ct_object));

            var stab_lab = of.CreateSymbol();

            stab_lab.Name       = Label;
            stab_lab.ObjectType = binary_library.SymbolObjectType.Object;
            stab_lab.Offset     = (ulong)rd.Data.Count;
            stab_lab.Type       = binary_library.SymbolType.Weak;
            rd.AddSymbol(stab_lab);

            int stab_base = rd.Data.Count;

            foreach (byte b in str_tab)
            {
                rd.Data.Add(b);
            }

            foreach (var kvp in sig_metadata_addrs)
            {
                var reloc = of.CreateRelocation();
                reloc.DefinedIn = rd;
                reloc.Type      = t.GetDataToDataReloc();
                reloc.Addend    = 0;

                if (sig_metadata_addends.ContainsKey(kvp.Key))
                {
                    reloc.Addend = sig_metadata_addends[kvp.Key];
                }

                var md_lab = of.CreateSymbol();
                md_lab.Name       = kvp.Value;
                md_lab.ObjectType = binary_library.SymbolObjectType.Object;

                reloc.References = md_lab;
                reloc.Offset     = (ulong)(kvp.Key + stab_base);
                of.AddRelocation(reloc);
            }

            stab_lab.Size = rd.Data.Count - (int)stab_lab.Offset;
        }
Beispiel #3
0
 public binary_library.ISymbol GetStringTableSymbol(binary_library.IBinaryFile of)
 {
     binary_library.ISymbol sym;
     if (st_cache.TryGetValue(of, out sym))
     {
         return(sym);
     }
     else
     {
         sym          = of.CreateSymbol();
         st_cache[of] = sym;
         return(sym);
     }
 }
Beispiel #4
0
        public DwarfSections(binary_library.IBinaryFile _bf)
        {
            bf = _bf;

            abbrev = CreateDwarfSection("abbrev");
            //aranges = CreateDwarfSection("aranges");
            frame = CreateDwarfSection("frame");
            info  = CreateDwarfSection("info");
            line  = CreateDwarfSection("line");
            //loc = CreateDwarfSection("loc");
            //macinfo = CreateDwarfSection("macinfo");
            pubnames = CreateDwarfSection("pubnames");
            pubtypes = CreateDwarfSection("pubtypes");
            //ranges = CreateDwarfSection("ranges");
            str = CreateDwarfSection("str");
            //types = CreateDwarfSection("types");
        }
Beispiel #5
0
        static void Main(string[] args)
        {
            // Load a test file
            string       test_file = "..\\..\\..\\libsupcs\\x86_64_cpu.asm";
            FileStream   fs        = new FileStream(test_file, FileMode.Open, FileAccess.Read);
            StreamReader sr        = new StreamReader(fs);
            string       file      = sr.ReadToEnd();

            // Tokenize and parse
            List <Tokenizer.TokenDefinition> tokens = Tokenizer.Tokenize(file, Tokenizer.CAsmTokenGrammar, Tokenizer.NasmPreprocessorOptions);

            AsmParser.ParseOutput parsed = AsmParser.Parse(tokens);

            // Create an output file
            binary_library.IBinaryFile output_file = binary_library.BinaryFile.CreateBinaryFile("elf");

            // Assemble to the output file
            Assembler ass = new x86_Assembler();

            ass.Assemble(parsed, output_file);
        }
Beispiel #6
0
        public void WriteToOutput(binary_library.IBinaryFile of,
                                  metadata.MetadataStream ms, target.Target t)
        {
            var rd = of.GetRDataSection();

            rd.Align(t.GetCTSize(ir.Opcode.ct_object));

            var stab_lab = GetStringTableSymbol(of);

            stab_lab.Name       = Label;
            stab_lab.ObjectType = binary_library.SymbolObjectType.Object;
            stab_lab.Offset     = (ulong)rd.Data.Count;
            stab_lab.Type       = binary_library.SymbolType.Global;
            rd.AddSymbol(stab_lab);

            int stab_base = rd.Data.Count;

            foreach (byte b in str_tab)
            {
                rd.Data.Add(b);
            }

            var str_lab = of.CreateSymbol();

            str_lab.Name       = StringObject.m.MangleType(StringObject);
            str_lab.ObjectType = binary_library.SymbolObjectType.Object;

            foreach (var str_addr in str_addrs.Values)
            {
                var reloc = of.CreateRelocation();
                reloc.DefinedIn  = rd;
                reloc.Type       = t.GetDataToDataReloc();
                reloc.Addend     = 0;
                reloc.References = str_lab;
                reloc.Offset     = (ulong)(str_addr + stab_base);
                of.AddRelocation(reloc);
            }

            stab_lab.Size = rd.Data.Count - (int)stab_lab.Offset;
        }
Beispiel #7
0
        public static bool AssembleBoxedMethod(metadata.MethodSpec ms,
                                               binary_library.IBinaryFile bf, target.Target t,
                                               TysilaState s,
                                               StringBuilder debug_passes = null,
                                               binary_library.ISection ts = null)
        {
            if (ts == null)
            {
                ts = bf.GetTextSection();
            }
            s.bf           = bf;
            s.text_section = ts;

            // Symbol
            List <binary_library.ISymbol> meth_syms = new List <binary_library.ISymbol>();
            var mangled_name = ms.MangleMethod();
            var meth_sym     = bf.CreateSymbol();

            meth_sym.Name       = mangled_name;
            meth_sym.ObjectType = binary_library.SymbolObjectType.Function;
            meth_sym.Offset     = (ulong)ts.Data.Count;
            meth_sym.Type       = binary_library.SymbolType.Weak;
            ts.AddSymbol(meth_sym);
            meth_syms.Add(meth_sym);

            Code c = ms.ret_type_needs_boxing ? t.AssembleBoxRetTypeMethod(ms, s) : t.AssembleBoxedMethod(ms, s);

            c.t = t;
            t.AssemblePass(c);

            foreach (var sym in meth_syms)
            {
                sym.Size = ts.Data.Count - (int)sym.Offset;
            }

            DumpDebug(debug_passes, meth_syms, c);

            return(true);
        }
Beispiel #8
0
        // Build the hash table
        List <int>[] BuildHashTable(binary_library.IBinaryFile f)
        {
            int sc = f.GetSymbolCount();
            int bc = CalculateBucketCount(sc);

            List <int>[] ht = new List <int> [bc];

            for (int i = 1; i < sc; i++)
            {
                binary_library.ISymbol sym = f.GetSymbol(i);
                uint hash      = HashFunction(sym.Name);
                int  bucket_no = (int)(hash % (uint)bc);

                if (ht[bucket_no] == null)
                {
                    ht[bucket_no] = new List <int>();
                }
                ht[bucket_no].Add(i);
            }

            return(ht);
        }
Beispiel #9
0
        public void Assemble(AsmParser.ParseOutput input, binary_library.IBinaryFile output)
        {
            AssemblerState state = CreateAssemblerState(output);

            if (input.Type != AsmParser.ParseOutput.OutputType.Block)
            {
                throw new Exception("Expected Block");
            }

            foreach (AsmParser.ParseOutput line in input.Children)
            {
                if (line.Type != AsmParser.ParseOutput.OutputType.Line)
                {
                    throw new Exception("Expected Line");
                }

                foreach (AsmParser.ParseOutput line_entry in line.Children)
                {
                    switch (line_entry.Type)
                    {
                    case AsmParser.ParseOutput.OutputType.DirectiveCommand:
                        AssembleDirective(line_entry, state);
                        break;

                    case AsmParser.ParseOutput.OutputType.OpCommand:
                        AssembleOperation(line_entry, state);
                        break;

                    case AsmParser.ParseOutput.OutputType.Label:
                        AssembleLabel(line_entry, state);
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
            }
        }
Beispiel #10
0
 public abstract bool AssembleJitStub(metadata.MethodSpec ms, libtysila5.target.Target t,
                                      binary_library.IBinaryFile bf, libtysila5.TysilaState s);
Beispiel #11
0
 public AssemblerState(binary_library.IBinaryFile binary_file)
 {
     file = binary_file; SelectSection(".text");
 }
Beispiel #12
0
 protected virtual AssemblerState CreateAssemblerState(binary_library.IBinaryFile file)
 {
     return(new AssemblerState(file));
 }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        public static bool AssembleMethod(metadata.MethodSpec ms,
                                          binary_library.IBinaryFile bf, target.Target t,
                                          TysilaState s,
                                          StringBuilder debug_passes        = null,
                                          MetadataStream base_m             = null,
                                          Code code_override                = null,
                                          binary_library.ISection ts        = null,
                                          binary_library.ISection data_sect = null,
                                          dwarf.DwarfCU dcu = null)
        {
            if (ms.ret_type_needs_boxing)
            {
                throw new Exception("AssembleMethod called for box rettype stub - use AssembleBoxedMethod instead");
            }
            if (ms.is_boxed)
            {
                throw new Exception("AssembleMethod called for boxed method - use AssembleBoxedMethod instead");
            }

            if (ts == null)
            {
                ts = bf.GetTextSection();
            }
            s.bf           = bf;
            s.text_section = ts;
            binary_library.SymbolType sym_st = binary_library.SymbolType.Global;

            var csite = ms.msig;
            var mdef  = ms.mdrow;
            var m     = ms.m;

            /* Don't compile if not for this architecture */
            if (!t.IsMethodValid(ms))
            {
                return(false);
            }

            // Get method RVA, don't compile if no body
            var rva = m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                    mdef, 0);

            // New signature table
            s.sigt = new SignatureTable(ms.MangleMethod());

            /* Is this an array method? */
            if (rva == 0 &&
                ms.type != null &&
                ms.type.stype == TypeSpec.SpecialType.Array &&
                code_override == null)
            {
                if (ms.name_override == "Get")
                {
                    code_override = ir.ConvertToIR.CreateArrayGet(ms, t, s);
                }
                else if (ms.name_override == ".ctor")
                {
                    // there are two constructors, choose the correct one
                    var pcount = ms.m.GetMethodDefSigParamCount(ms.msig);

                    if (pcount == ms.type.arr_rank)
                    {
                        code_override = ir.ConvertToIR.CreateArrayCtor1(ms, t, s);
                    }
                    else if (pcount == 2 * ms.type.arr_rank)
                    {
                        code_override = ir.ConvertToIR.CreateArrayCtor2(ms, t, s);
                    }
                    else
                    {
                        throw new NotSupportedException("Invalid number of parameters to " + ms.MangleMethod() + " for array of rank " + ms.type.arr_rank.ToString());
                    }
                }
                else if (ms.name_override == "Set")
                {
                    code_override = ir.ConvertToIR.CreateArraySet(ms, t, s);
                }
                else if (ms.name_override == "Address")
                {
                    code_override = ir.ConvertToIR.CreateArrayAddress(ms, t, s);
                }
                else
                {
                    throw new NotImplementedException(ms.name_override);
                }

                sym_st = binary_library.SymbolType.Weak;
            }

            /* Is this a vector method? */
            if (rva == 0 &&
                ms.type != null &&
                ms.type.stype == TypeSpec.SpecialType.SzArray &&
                code_override == null)
            {
                if (ms.Name == "IndexOf")
                {
                    code_override = ir.ConvertToIR.CreateVectorIndexOf(ms, t, s);
                }
                else if (ms.Name == "Insert")
                {
                    code_override = ir.ConvertToIR.CreateVectorInsert(ms, t, s);
                }
                else if (ms.Name == "RemoveAt")
                {
                    code_override = ir.ConvertToIR.CreateVectorRemoveAt(ms, t, s);
                }
                else if (ms.Name == "get_Item")
                {
                    code_override = ir.ConvertToIR.CreateVectorget_Item(ms, t, s);
                }
                else if (ms.Name == "set_Item")
                {
                    code_override = ir.ConvertToIR.CreateVectorset_Item(ms, t, s);
                }
                else if (ms.Name == "get_Count")
                {
                    code_override = ir.ConvertToIR.CreateVectorget_Count(ms, t, s);
                }
                else if (ms.Name == "CopyTo")
                {
                    code_override = ir.ConvertToIR.CreateVectorCopyTo(ms, t, s);
                }

                /*else if (ms.Name == "GetEnumerator")
                 *  code_override = ir.ConvertToIR.CreateVectorGetEnumerator(ms, t);*/
                else if (ms.Name == "Add" ||
                         ms.Name == "Clear" ||
                         ms.Name == "Contains" ||
                         ms.Name == "Remove" ||
                         ms.Name == "get_IsReadOnly" ||
                         ms.Name == "get_IsSynchronized" ||
                         ms.Name == "get_SyncRoot" ||
                         ms.Name == "get_IsFixedSize" ||
                         ms.Name == "Clone" ||
                         ms.Name == "CompareTo" ||
                         ms.Name == "GetHashCode" ||
                         ms.Name == "Equals")
                {
                    code_override = ir.ConvertToIR.CreateVectorUnimplemented(ms, t, s);
                }
                else
                {
                    return(false);
                }

                sym_st = binary_library.SymbolType.Weak;
            }

            if (rva == 0 && code_override == null)
            {
                return(false);
            }

            // Get mangled name for defining a symbol
            List <binary_library.ISymbol> meth_syms = new List <binary_library.ISymbol>();
            var mangled_name = m.MangleMethod(ms);
            var meth_sym     = bf.CreateSymbol();

            meth_sym.Name       = mangled_name;
            meth_sym.ObjectType = binary_library.SymbolObjectType.Function;
            meth_sym.Offset     = (ulong)ts.Data.Count;
            meth_sym.Type       = binary_library.SymbolType.Global;
            ts.AddSymbol(meth_sym);
            meth_syms.Add(meth_sym);

            foreach (var alias in ms.MethodAliases)
            {
                var alias_sym = bf.CreateSymbol();
                alias_sym.Name       = alias;
                alias_sym.ObjectType = binary_library.SymbolObjectType.Function;
                alias_sym.Offset     = (ulong)ts.Data.Count;
                alias_sym.Type       = binary_library.SymbolType.Global;
                ts.AddSymbol(alias_sym);
                meth_syms.Add(alias_sym);
            }

            if (ms.HasCustomAttribute("_ZN14libsupcs#2Edll8libsupcs20WeakLinkageAttribute_7#2Ector_Rv_P1u1t"))
            {
                sym_st = binary_library.SymbolType.Weak;
            }
            if (base_m != null && ms.m != base_m)
            {
                sym_st = binary_library.SymbolType.Weak;
            }
            foreach (var sym in meth_syms)
            {
                sym.Type = sym_st;
            }

            // Get signature if not specified
            if (csite == 0)
            {
                csite = (int)m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                           mdef, 4);
            }

            Code cil;

            if (code_override == null)
            {
                var meth = m.GetRVA(rva);

                var  flags        = meth.ReadByte(0);
                int  max_stack    = 0;
                long code_size    = 0;
                long lvar_sig_tok = 0;
                int  boffset      = 0;
                List <metadata.ExceptionHeader> ehdrs = null;
                bool has_exceptions = false;

                if ((flags & 0x3) == 0x2)
                {
                    // Tiny header
                    code_size = flags >> 2;
                    max_stack = 8;
                    boffset   = 1;
                }
                else if ((flags & 0x3) == 0x3)
                {
                    // Fat header
                    uint fat_flags   = meth.ReadUShort(0) & 0xfffU;
                    int  fat_hdr_len = (meth.ReadUShort(0) >> 12) * 4;
                    max_stack    = meth.ReadUShort(2);
                    code_size    = meth.ReadUInt(4);
                    lvar_sig_tok = meth.ReadUInt(8);
                    boffset      = fat_hdr_len;

                    if ((flags & 0x8) == 0x8)
                    {
                        has_exceptions = true;

                        ehdrs = new List <metadata.ExceptionHeader>();

                        int ehdr_offset = boffset + (int)code_size;
                        ehdr_offset = util.util.align(ehdr_offset, 4);

                        while (true)
                        {
                            int kind = meth.ReadByte(ehdr_offset);

                            if ((kind & 0x1) != 0x1)
                            {
                                throw new Exception("Invalid exception header");
                            }

                            bool is_fat = false;
                            if ((kind & 0x40) == 0x40)
                            {
                                is_fat = true;
                            }

                            int data_size = meth.ReadInt(ehdr_offset);
                            data_size >>= 8;
                            if (is_fat)
                            {
                                data_size &= 0xffffff;
                            }
                            else
                            {
                                data_size &= 0xff;
                            }

                            int clause_count;
                            if (is_fat)
                            {
                                clause_count = (data_size - 4) / 24;
                            }
                            else
                            {
                                clause_count = (data_size - 4) / 12;
                            }

                            ehdr_offset += 4;
                            for (int i = 0; i < clause_count; i++)
                            {
                                var ehdr = ParseExceptionHeader(meth,
                                                                ref ehdr_offset, is_fat, ms);
                                ehdr.EhdrIdx = i;
                                ehdrs.Add(ehdr);
                            }

                            if ((kind & 0x80) != 0x80)
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    throw new Exception("Invalid method header flags");
                }

                /* Parse CIL code */
                cil = libtysila5.cil.CilParser.ParseCIL(meth,
                                                        ms, boffset, (int)code_size, lvar_sig_tok,
                                                        has_exceptions, ehdrs);
                cil.s = s;

                /* Allocate local vars and args */
                t.AllocateLocalVarsArgs(cil);

                /* Convert to IR */
                cil.t = t;
                ir.ConvertToIR.DoConversion(cil);
            }
            else
            {
                cil = code_override;
            }


            /* Allocate registers */
            ir.AllocRegs.DoAllocation(cil);


            /* Choose instructions */
            target.ChooseInstructions.DoChoosing(cil);
            t.AssemblePass(cil);
            //((target.x86.x86_Assembler)cil.t).AssemblePass(cil);

            foreach (var sym in meth_syms)
            {
                sym.Size = ts.Data.Count - (int)sym.Offset;
            }

            foreach (var extra_sym in cil.extra_labels)
            {
                var esym = bf.CreateSymbol();
                esym.Name       = extra_sym.Name;
                esym.ObjectType = binary_library.SymbolObjectType.Function;
                esym.Offset     = (ulong)extra_sym.Offset;
                esym.Type       = sym_st;
                ts.AddSymbol(esym);
            }

            /* Dump debug */
            DumpDebug(debug_passes, meth_syms, cil);

            /* Signature table */
            if (data_sect == null)
            {
                data_sect = bf.GetDataSection();
            }
            s.sigt.WriteToOutput(bf, ms.m, t, data_sect);

            /* DWARF output */
            if (dcu != null)
            {
                var ddie = dcu.GetMethodDie(ms);
                ddie.sym = meth_syms[0];
                ddie.cil = cil;

                var ddts = dcu.GetTypeDie(ms.type) as dwarf.DwarfParentDIE;
                ddts.Children.Add(ddie);

                if (ms.ReturnType != null)
                {
                    dcu.GetTypeDie(ms.ReturnType);
                    if (ms.ReturnType.stype == TypeSpec.SpecialType.None && !ms.ReturnType.IsValueType)
                    {
                        dcu.GetTypeDie(ms.ReturnType.Pointer);
                    }
                }
                foreach (var la in cil.la_types)
                {
                    dcu.GetTypeDie(la);
                    if (la.stype == TypeSpec.SpecialType.None && !la.IsValueType)
                    {
                        dcu.GetTypeDie(la.Pointer);
                    }
                }
                foreach (var lv in cil.lv_types)
                {
                    dcu.GetTypeDie(lv);
                    if (lv.stype == TypeSpec.SpecialType.None && !lv.IsValueType)
                    {
                        dcu.GetTypeDie(lv.Pointer);
                    }
                }

                if (!ms.IsStatic)
                {
                    dcu.GetTypeDie(ms.type.Pointer);
                }

                // do we have source lines?
                if (ms.m.pdb != null && ms.mdrow > 0)
                {
                    var sps = ms.m.pdb.DebugGetSeqPtForMDRow(ms.mdrow);
                    if (sps != null && cil.cil != null && cil.cil.Count > 0)
                    {
                        /* Start building a Line Number Program
                         *
                         * We follow the example in DWARF4 D.5 (p251), with a few changes
                         *
                         * header - defined per CU
                         *   - add this/these source files to it if necessary
                         *
                         * DW_LNE_set_address - psize 0s, reloc to mangled name
                         * DW_LNS_advance_pc - mc_offset of first cil instruction
                         * DW_LNS_set_prologue_end
                         * DW_LNS_set_file - source file
                         * SPECIAL(0,0) - add first opcode
                         * SPECIAL(x,y) - add rest of opcodes
                         * DW_LNE_end_sequence
                         *
                         */

                        string cur_file = null;
                        int    cur_line = 1;
                        int    cur_mc   = 0;
                        int    cur_col  = 0;

                        var lnp = dcu.lnp;

                        // DW_LNE_set_address
                        lnp.AddRange(new byte[] { 0x00, (byte)(t.psize + 1), 0x02 });
                        dcu.lnp_relocs.Add(lnp.Count, meth_syms[0]);
                        for (int i = 0; i < t.psize; i++)
                        {
                            lnp.Add(0);
                        }

                        // DW_LNS_advance_pc
                        lnp.Add(0x02);
                        dwarf.DwarfDIE.w(lnp, (uint)cil.cil[0].mc_offset);
                        cur_mc = cil.cil[0].mc_offset;

                        // DW_LNS_set_prologue_end
                        lnp.Add(0x0a);

                        foreach (var cn in cil.cil)
                        {
                            var mc_advance = cn.mc_offset - cur_mc;

                            // get current line number
                            MetadataStream.SeqPt csp = null;
                            foreach (var sp in sps)
                            {
                                if (sp.IlOffset == cn.il_offset &
                                    !sp.IsHidden)
                                {
                                    csp = sp;
                                    break;
                                }
                            }
                            if (csp != null)
                            {
                                var line_advance = csp.StartLine - cur_line;

                                if (ddie.StartLine == 0)
                                {
                                    ddie.StartLine = csp.StartLine;
                                }
                                if (ddie.StartColumn == 0)
                                {
                                    ddie.StartColumn = csp.StartCol;
                                }

                                if (csp.DocName != cur_file)
                                {
                                    // DW_LNS_set_file
                                    lnp.Add(0x04);

                                    uint file_no;
                                    if (!dcu.lnp_files.TryGetValue(csp.DocName, out file_no))
                                    {
                                        file_no = (uint)(dcu.lnp_files.Count + 1);
                                        dcu.lnp_files[csp.DocName] = file_no;
                                        dcu.lnp_fnames.Add(csp.DocName);
                                    }
                                    if (ddie.SourceFileId == 0)
                                    {
                                        ddie.SourceFileId = (int)file_no;
                                    }

                                    dwarf.DwarfDIE.w(lnp, file_no);

                                    cur_file = csp.DocName;
                                }

                                if (csp.StartCol != cur_col)
                                {
                                    // DW_LNS_set_column
                                    lnp.Add(0x05);
                                    dwarf.DwarfDIE.w(lnp, (uint)csp.StartCol);
                                    cur_col = csp.StartCol;
                                }

                                /* SPECIAL if possible
                                 *  Use example on DWARF4 p132:
                                 *      opcode_base = 13, line_base = -3, line_range = 12
                                 *
                                 *  Gives a line advance range of [-3,8] and op_advance [0,19]
                                 */

                                if ((line_advance >= dcu.line_base && line_advance < (dcu.line_base + dcu.line_range)) &&
                                    (mc_advance >= 0 && mc_advance < dcu.mc_advance_max))
                                {
                                    var spec_opcode = (line_advance - dcu.line_base) +
                                                      (dcu.line_range * mc_advance) + dcu.opcode_base;
                                    lnp.Add((byte)spec_opcode);
                                }
                                else
                                {
                                    // DW_LNS_advance_pc
                                    lnp.Add(0x02);
                                    dwarf.DwarfDIE.w(lnp, (uint)mc_advance);

                                    // DW_LNS_advance_line
                                    lnp.Add(0x03);
                                    dwarf.DwarfDIE.w(lnp, line_advance);

                                    // SPECIAL(0,0)
                                    var spec_opcode = (0 - dcu.line_base) + dcu.opcode_base;
                                    lnp.Add((byte)spec_opcode);
                                }

                                cur_line += line_advance;
                                cur_mc   += mc_advance;
                            }
                        }

                        // Advance to end
                        var to_advance = (int)meth_syms[0].Size - cur_mc;
                        lnp.Add(0x02);
                        dwarf.DwarfDIE.w(lnp, to_advance);

                        // DW_LNE_end_sequence
                        lnp.Add(0x00);
                        lnp.Add(0x01);
                        lnp.Add(0x01);
                    }
                }
            }

            return(true);
        }
Beispiel #15
0
        static void Main(string[] args)
        {
            if (ParseArgs(args) == false)
            {
                DispUsage();
                return;
            }

            InitMaps();

            // Initialize the default linker scripts
            DefaultScripts.InitScripts();

            // Load the input files
            if (ifiles.Count == 0)
            {
                Console.WriteLine("No input files!");
                return;
            }
            List <binary_library.IBinaryFile> inputs = new List <binary_library.IBinaryFile>();

            foreach (string ifile in ifiles)
            {
                binary_library.elf.ElfFile ef = new binary_library.elf.ElfFile();
                ef.Filename = ifile;
                ef.Read();
                inputs.Add(ef);
            }

            // Determine the architecture
            string cur_arch = null;

            if (options["arch"].Set)
            {
                cur_arch = options["arch"].String;
            }
            foreach (binary_library.IBinaryFile ifile in inputs)
            {
                if (cur_arch == null)
                {
                    cur_arch = ifile.NameTriple;
                }
            }

            string[] ntriple = cur_arch.Split('-');
            if (ntriple.Length != 3)
            {
                Console.WriteLine("Error: invalid architecture: " + cur_arch);
                throw new Exception();
            }

            // Check input files are of the appropriate architecture
            foreach (var ifile in inputs)
            {
                if (ntriple[0] != ifile.Architecture)
                {
                    Console.WriteLine("Error: " + ifile.Filename + " is not built for architecture " + ntriple[0]);
                    throw new Exception();
                }
            }

            // Determine output file type
            string oformat = null;

            binary_library.Bitness bn = binary_library.Bitness.BitsUnknown;
            if (options["oformat"].Set)
            {
                oformat = options["oformat"].String.ToLower();
                if (bitness_map.ContainsKey(oformat))
                {
                    bn = bitness_map[oformat];
                }
                if (oformat == "elf32" || oformat == "elf64")
                {
                    oformat = "elf";
                }
            }
            else if (oformat_map.ContainsKey(ntriple[1]))
            {
                oformat = oformat_map[ntriple[1]];
            }
            else
            {
                oformat = "elf";
            }

            if (bn == binary_library.Bitness.BitsUnknown && bitness_map.ContainsKey(ntriple[0]))
            {
                bn = bitness_map[ntriple[0]];
            }

            // Create an output file
            binary_library.IBinaryFile of = null;

            if (oformat == "elf")
            {
                of = new binary_library.elf.ElfFile(bn);
            }
            else if (oformat == "binary")
            {
                of = new binary_library.binary.FlatBinaryFile();
            }
            else if (oformat == "hex")
            {
                of = new binary_library.binary.HexFile();
            }
            else
            {
                throw new Exception("Unsupported output format: " + oformat);
            }

            if (output_file == null)
            {
                output_file = "a.out";
            }

            of.Init();
            of.Architecture = ntriple[0];
            if (ntriple[1] == "elf" && bn == binary_library.Bitness.Bits64)
            {
                of.BinaryType = "elf64";
            }
            else
            {
                of.BinaryType = ntriple[1];
            }
            of.OS = ntriple[2];

            // Get the linker script
            LinkerScript script = DefaultScripts.GetScript(ntriple);

            // Fill out comment section
            comment += "triple: " + of.Architecture + "-" + of.BinaryType + "-" + of.OS + nl;
            comment += "arch: " + of.Architecture + nl;
            comment += "binarytype: " + of.Architecture + nl;
            comment += "os: " + of.OS + nl;
            comment += "script: " + script.Name + nl;
            comment += "comp-date: " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + nl;
            comment += "endtl" + nl + "\0";

            // Run the script
            script.RunScript(of, inputs);

            // ELF specific options
            if (of is binary_library.elf.ElfFile)
            {
                var ef = of as binary_library.elf.ElfFile;
                ef.CreateHashSection = gen_hash;
            }

            of.Filename = output_file;
            of.Write();
        }
Beispiel #16
0
        // Write out the hash table
        public void Write(BinaryWriter s, binary_library.IBinaryFile f, int ver, int endian, int bitness)
        {
            long offset_to_hash_table = 0;
            long offset_to_file_name  = 0;

            if (ver > 0)
            {
                // Write header
                long header_offset = s.BaseStream.Position;
                s.Write((byte)'T');
                s.Write((byte)'Y');
                s.Write((byte)'H');
                s.Write((byte)'A');
                s.Write((byte)'S');
                s.Write((byte)'H');
                s.Write((byte)' ');
                s.Write((byte)' ');
                s.Write((ushort)ver);
                s.Write((byte)endian);
                s.Write((byte)bitness);

                offset_to_hash_table = s.BaseStream.Position;
                s.Write((int)0);

                offset_to_file_name = s.BaseStream.Position;
                s.Write((int)0);
            }

            // Build hash table
            long hash_table_start = s.BaseStream.Position;

            List <int>[] ht = BuildHashTable(f);
            WriteIntPtr(s, ht.Length, bitness);
            WriteIntPtr(s, f.GetSymbolCount(), bitness);

            // Build arrays to contain the bucket and chains
            long[] buckets = new long[ht.Length];
            long[] chains  = new long[f.GetSymbolCount()];

            // Iterate through each chain
            for (int i = 0; i < ht.Length; i++)
            {
                List <int> bucket = ht[i];
                if (bucket == null)
                {
                    continue;
                }

                for (int j = 0; j < bucket.Count; j++)
                {
                    int chain = bucket[j];

                    // First entry is pointed to by bucket
                    if (j == 0)
                    {
                        buckets[i] = chain;
                    }

                    int next_chain = 0;
                    if (j < (bucket.Count - 1))
                    {
                        next_chain = bucket[j + 1];
                    }

                    chains[chain] = next_chain;
                }
            }

            // Write out
            foreach (long b in buckets)
            {
                WriteIntPtr(s, b, bitness);
            }
            foreach (long c in chains)
            {
                WriteIntPtr(s, c, bitness);
            }

            if (ver > 0)
            {
                // Point the hash table pointer to the hash table
                long cur_pos = s.BaseStream.Position;
                s.BaseStream.Seek(offset_to_hash_table, SeekOrigin.Begin);
                s.Write((int)hash_table_start);

                // Write out the input file name
                s.BaseStream.Seek(offset_to_file_name, SeekOrigin.Begin);
                s.Write((int)cur_pos);
                s.BaseStream.Seek(cur_pos, SeekOrigin.Begin);
                System.IO.FileInfo fi = new FileInfo(f.Filename);
                foreach (char c in fi.Name)
                {
                    s.Write((byte)c);
                }
                s.Write((byte)0);
            }
        }
Beispiel #17
0
        public static void OutputEHdr(MethodSpecWithEhdr ms,
                                      Target t, binary_library.IBinaryFile of,
                                      TysilaState s,
                                      MetadataStream base_m      = null,
                                      binary_library.ISection os = null)
        {
            // Don't compile if not for this architecture
            if (!t.IsMethodValid(ms.ms))
            {
                return;
            }

            if (os == null)
            {
                os = of.GetRDataSection();
            }
            os.Align(t.GetPointerSize());
            var d = os.Data;

            /* Symbol */
            var sym = of.CreateSymbol();

            sym.Name       = ms.ms.MangleMethod() + "EH";
            sym.ObjectType = binary_library.SymbolObjectType.Object;
            sym.Offset     = (ulong)d.Count;
            sym.Type       = binary_library.SymbolType.Global;
            os.AddSymbol(sym);

            if (base_m != null && ms.ms.m != base_m)
            {
                sym.Type = binary_library.SymbolType.Weak;
            }

            foreach (var ehdr in ms.c.ehdrs)
            {
                var v = t.IntPtrArray(BitConverter.GetBytes((int)ehdr.EType));
                foreach (var b in v)
                {
                    d.Add(b);
                }

                /* Handler */
                var hand_sym = of.CreateSymbol();
                hand_sym.Name = ms.ms.MangleMethod() + "EH" + ehdr.EhdrIdx.ToString();

                var hand_reloc = of.CreateRelocation();
                hand_reloc.Addend     = 0;
                hand_reloc.DefinedIn  = os;
                hand_reloc.Offset     = (ulong)d.Count;
                hand_reloc.References = hand_sym;
                hand_reloc.Type       = t.GetDataToCodeReloc();
                of.AddRelocation(hand_reloc);

                for (int i = 0; i < t.GetPointerSize(); i++)
                {
                    d.Add(0);
                }

                /* Catch object */
                if (ehdr.ClassToken != null)
                {
                    var catch_sym = of.CreateSymbol();
                    catch_sym.Name = ehdr.ClassToken.MangleType();

                    var catch_reloc = of.CreateRelocation();
                    catch_reloc.Addend     = 0;
                    catch_reloc.DefinedIn  = os;
                    catch_reloc.Offset     = (ulong)d.Count;
                    catch_reloc.References = catch_sym;
                    catch_reloc.Type       = t.GetDataToDataReloc();
                    of.AddRelocation(catch_reloc);

                    s.r.VTableRequestor.Request(ehdr.ClassToken);
                }
                else if (ehdr.EType == ExceptionHeader.ExceptionHeaderType.Filter)
                {
                    var filt_sym = of.CreateSymbol();
                    filt_sym.Name = ms.ms.MangleMethod() + "EHF" + ehdr.EhdrIdx.ToString();

                    var filt_reloc = of.CreateRelocation();
                    filt_reloc.Addend     = 0;
                    filt_reloc.DefinedIn  = os;
                    filt_reloc.Offset     = (ulong)d.Count;
                    filt_reloc.References = filt_sym;
                    filt_reloc.Type       = t.GetDataToCodeReloc();
                    of.AddRelocation(filt_reloc);
                }
                for (int i = 0; i < t.GetPointerSize(); i++)
                {
                    d.Add(0);
                }
            }

            sym.Size = (long)((ulong)d.Count - sym.Offset);
        }