Beispiel #1
0
        public static void OutputStaticFields(metadata.TypeSpec ts,
                                              target.Target t, binary_library.IBinaryFile of,
                                              MetadataStream base_m         = null,
                                              binary_library.ISection os    = null,
                                              binary_library.ISection tlsos = null)
        {
            // Don't compile if not for this architecture
            if (!t.IsTypeValid(ts))
            {
                return;
            }

            int align = 1;

            if (ts.SimpleType == 0)
            {
                align = GetTypeAlignment(ts, t, true);
            }

            if (os == null)
            {
                os = of.GetDataSection();
            }
            os.Align(t.GetPointerSize());
            os.Align(align);

            ulong offset    = (ulong)os.Data.Count;
            ulong tl_offset = 0;

            if (tlsos != null)
            {
                tl_offset = (ulong)tlsos.Data.Count;
            }

            int cur_offset   = 0;
            int cur_tloffset = 0;

            /* is_initialized */
            for (int i = 0; i < t.psize; i++)
            {
                os.Data.Add(0);
            }
            cur_offset += t.psize;

            /* Iterate through methods looking for requested
             *  one */
            var first_fdef = ts.m.GetIntEntry(MetadataStream.tid_TypeDef,
                                              ts.tdrow, 4);
            var last_fdef = ts.m.GetLastFieldDef(ts.tdrow);

            for (uint fdef_row = first_fdef; fdef_row < last_fdef; fdef_row++)
            {
                // Ensure field is static or not as required
                var flags = ts.m.GetIntEntry(MetadataStream.tid_Field,
                                             (int)fdef_row, 0);
                if ((flags & 0x10) == 0x10)
                {
                    // Increment by type size
                    var fsig = (int)ts.m.GetIntEntry(MetadataStream.tid_Field,
                                                     (int)fdef_row, 2);

                    var ft      = ts.m.GetFieldType(ref fsig, ts.gtparams, null);
                    var ft_size = t.GetSize(ft);

                    ft_size = util.util.align(ft_size, align);

                    bool     is_tls = ts.m.thread_local_fields[(int)fdef_row];
                    ISection cur_os = os;
                    if (is_tls)
                    {
                        if (tlsos == null)
                        {
                            throw new NotSupportedException("No thread-local section provided");
                        }
                        cur_os = tlsos;
                    }

                    /* See if there is any data defined as an rva */
                    var rva = ts.m.fieldrvas[(int)fdef_row];
                    if (rva != 0)
                    {
                        var rrva = (int)ts.m.ResolveRVA(rva);
                        for (int i = 0; i < ft_size; i++)
                        {
                            cur_os.Data.Add(ts.m.file.ReadByte(rrva++));
                        }
                    }
                    else
                    {
                        for (int i = 0; i < ft_size; i++)
                        {
                            cur_os.Data.Add(0);
                        }
                    }

                    /* Output any additional defined symbols */
                    foreach (var alias in ts.m.GetFieldAliases((int)fdef_row))
                    {
                        var asym = of.CreateSymbol();
                        asym.Name       = alias;
                        asym.Offset     = offset + (ulong)cur_offset;
                        asym.Type       = binary_library.SymbolType.Global;
                        asym.ObjectType = binary_library.SymbolObjectType.Object;
                        cur_os.AddSymbol(asym);

                        asym.Size = ft_size;

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

                    if (is_tls)
                    {
                        cur_tloffset += ft_size;
                    }
                    else
                    {
                        cur_offset += ft_size;
                    }
                }
            }

            if (cur_offset > 0)
            {
                /* Add symbol */

                var sym = of.CreateSymbol();
                sym.Name       = ts.m.MangleType(ts) + "S";
                sym.Offset     = offset;
                sym.Type       = binary_library.SymbolType.Global;
                sym.ObjectType = binary_library.SymbolObjectType.Object;
                os.AddSymbol(sym);

                sym.Size = os.Data.Count - (int)offset;

                if (base_m != null && ts.m != base_m)
                {
                    sym.Type = binary_library.SymbolType.Weak;
                }
            }
            if (cur_tloffset > 0)
            {
                /* Add thread local symbol */
                var sym = of.CreateSymbol();
                sym.Name       = ts.m.MangleType(ts) + "ST";
                sym.Offset     = tl_offset;
                sym.Type       = binary_library.SymbolType.Global;
                sym.ObjectType = binary_library.SymbolObjectType.Object;
                tlsos.AddSymbol(sym);

                sym.Size = tlsos.Data.Count - (int)tl_offset;

                if (base_m != null && ts.m != base_m)
                {
                    sym.Type = binary_library.SymbolType.Weak;
                }
            }
        }
            public override void DoCommand(binary_library.IBinaryFile output, IList <binary_library.IBinaryFile> inputs, LinkerScriptState state)
            {
                // Generate a list of sections to include
                IList <binary_library.ISection> sections = null;

                switch (selection)
                {
                case InputFileSelection.All:
                    sections = new List <binary_library.ISection>();
                    foreach (binary_library.IBinaryFile ifile in inputs)
                    {
                        binary_library.ISection sect = ifile.FindSection(input_section);
                        if (sect != null)
                        {
                            sections.Add(sect);
                        }
                    }

                    break;

                case InputFileSelection.AllNotSpecified:
                    sections = new List <binary_library.ISection>();
                    foreach (binary_library.IBinaryFile ifile in inputs)
                    {
                        binary_library.ISection sect = ifile.FindSection(input_section);
                        if ((sect != null) && (!state.included_sections.Contains(sect)))
                        {
                            sections.Add(sect);
                        }
                    }
                    break;

                case InputFileSelection.Specific:
                    sections = new List <binary_library.ISection>();
                    foreach (binary_library.IBinaryFile ifile in inputs)
                    {
                        System.IO.FileInfo fi = new System.IO.FileInfo(ifile.Filename);
                        if (fi.Exists && (fi.Name == input_file))
                        {
                            binary_library.ISection sect = ifile.FindSection(input_section);
                            if ((sect != null) && (!state.included_sections.Contains(sect)))
                            {
                                sections.Add(sect);
                            }
                        }
                    }
                    break;
                }

                // Write the sections data to the section cache and its symbols to the output file
                binary_library.ISection osect = state.cur_section;
                foreach (binary_library.ISection sect in sections)
                {
                    // Write the data
                    if (osect.HasData)
                    {
                        if (sect.HasData)
                        {
                            foreach (byte b in sect.Data)
                            {
                                state.data[osect].Add(b);
                            }
                        }
                        else
                        {
                            for (int i = 0; i < sect.Length; i++)
                            {
                                state.data[osect].Add(0);
                            }
                        }
                    }
                    else
                    {
                        osect.Length += sect.Length;
                    }

                    // Write the symbols
                    int sym_count = sect.GetSymbolCount();
                    for (int i = 0; i < sym_count; i++)
                    {
                        ISymbol sym     = sect.GetSymbol(i);
                        ISymbol new_sym = output.CreateSymbol();
                        new_sym.Name       = sym.Name;
                        new_sym.Offset     = state.cur_sect_offset + sym.Offset;
                        new_sym.Size       = sym.Size;
                        new_sym.Type       = sym.Type;
                        new_sym.ObjectType = sym.ObjectType;
                        osect.AddSymbol(new_sym);
                    }

                    // Save where this section is loaded to
                    state.input_section_locations[sect] = new LinkerScriptState.InputSectionLocation {
                        OutputSection = osect, OutputSectionOffset = state.cur_sect_offset
                    };
                    state.cur_sect_offset += (ulong)sect.Length;
                }

                // Add the sections to the list of included sections
                state.included_sections.AddRange(sections);
            }