Exemplo n.º 1
0
        static internal void RegisterSection(string name, string flags, string type, string flag_specific_arguments)
        {
            if (sections.ContainsKey(name))
                return;

            GetKnownSectionType(name, ref flags, ref type, ref flag_specific_arguments);

            Section s = new Section();
            s.name = name;
            if (flags == null)
                flags = "";
            if (type == null)
                type = "";
            if (flag_specific_arguments == null)
                flag_specific_arguments = "";

            // Default if flags is null is for not loaded or writeable
            if (flags == "")
            {
                s.Alloc = false;
                s.Write = false;
                s.Exec = false;
            }

            foreach(char c in flags)
            {
                switch(c)
                {
                    case 'a':
                        s.Alloc = true;
                        break;
                    case 'w':
                        s.Write = true;
                        s.Alloc = true;
                        break;
                    case 'x':
                        s.Exec = true;
                        s.Alloc = true;
                        break;
                }
            }

            // Default type is data (ProgBits)
            s.SectionType = Section.SectType.ProgBits;
            if (type == "progbits")
                s.SectionType = Section.SectType.ProgBits;
            else if (type == "nobits")
                s.SectionType = Section.SectType.NoBits;
            else if (type == "note")
                s.SectionType = Section.SectType.Note;
            else
                s.SectionType = Section.SectType.Unknown;

            sections[s.name] = s;
        }
Exemplo n.º 2
0
 internal MakeState(Dictionary<string, LabelOffset> label_offsets, Section cur_sect)
 { lo = label_offsets; cs = cur_sect; }
Exemplo n.º 3
0
Arquivo: Elf.cs Projeto: jncronin/jca
        private static int AllocateString(string name, Section strtab)
        {
            if (strtab.StringCache == null)
                strtab.StringCache = new Dictionary<string, int>();
            else if (strtab.StringCache.ContainsKey(name))
                return strtab.StringCache[name];

            if(strtab.cur_offset == 0)
            {
                strtab.oput.Add(0);
                strtab.cur_offset++;
            }

            int ret = strtab.cur_offset;
            foreach(char c in name)
            {
                strtab.oput.Add((byte)c);
                strtab.cur_offset++;
            }
            strtab.oput.Add(0);
            strtab.cur_offset++;

            strtab.StringCache[name] = ret;
            return ret;
        }
Exemplo n.º 4
0
        private static Expression EvaluateOperand(Expression src, Dictionary<string, LabelOffset> label_offsets,
            Section cur_section)
        {
            if (src == null)
                return null;
            MakeState s = new MakeState(label_offsets, cur_section);

            // ExpandComplex already uses operands
            if (src is Operand)
                return src;

            var v = src.Evaluate(s);
            switch(v.Type)
            {
                case Expression.EvalResult.ResultType.Register:
                    return new RegisterOperand { val = v.strval };
                case Expression.EvalResult.ResultType.Int:
                    return new IntegerOperand { val = v.intval };
                case Expression.EvalResult.ResultType.Relocation:
                    return v.relocval;
                default:
                    throw new NotImplementedException();
            }
        }
Exemplo n.º 5
0
Arquivo: Elf.cs Projeto: jncronin/jca
		static internal void GenerateELF(System.IO.BinaryWriter w)
		{
            /* First, build the section table.  We only include those
			sections that have some data defined.

			Section 0 is the null section.  We also include sections for
			the string and symbol tables
			*/

            MakeState ms = new MakeState(Program.los, null);

            List<Section> sects = new List<Section>();
            sects.Add(null);
            int cur_sect = 1;
            foreach(var s in Program.sections)
            {
                if (s.Value.cur_offset == 0)
                    continue;
                if (s.Value.SectionType == Section.SectType.Unknown)
                    continue;

                s.Value.SectionIdx = cur_sect++;
                sects.Add(s.Value);

                Section s_reloc = new Section();
                foreach(var r in Program.relocs)
                {
                    if(r.SourceSection == s.Value)
                        s_reloc.relocs.Add(r);
                }

                if(s_reloc.relocs.Count > 0)
                {
                    s_reloc.name = s.Value.name + ".rela";
                    s_reloc.SectionType = Section.SectType.Rela;
                    s_reloc.SectionIdx = cur_sect++;
                    s.Value.RelocSectionIdx = s_reloc.SectionIdx;
                    s_reloc.RelocSectionIdx = s.Value.SectionIdx;
                    sects.Add(s_reloc);
                }
            }

            // Add symbol, symbol string and section header string tables
            Section symtab = new Section();
            symtab.name = ".symtab";
            symtab.SectionIdx = cur_sect++;
            symtab.SectionType = Section.SectType.SymTab;
            sects.Add(symtab);

            Section strtab = new Section();
            strtab.name = ".strtab";
            strtab.SectionIdx = cur_sect++;
            strtab.SectionType = Section.SectType.StrTab;
            sects.Add(strtab);

            Section shstrtab = new Section();
            shstrtab.name = ".shstrtab";
            shstrtab.SectionIdx = cur_sect++;
            shstrtab.SectionType = Section.SectType.StrTab;
            sects.Add(shstrtab);

            // Add strings to section string table
            foreach(Section s in sects)
            {
                if (s == null)
                    continue;
                s.ShStrNdx = AllocateString(s.name, shstrtab);
            }

            // Build symbol table
            Dictionary<string, Symbol> syms = new Dictionary<string, Symbol>();
            foreach(var v in Program.los)
            {
                Symbol newsym = new Symbol();
                newsym.name = v.Key;
                newsym.StrNdx = AllocateString(newsym.name, strtab);
                newsym.Section = v.Value.Section;
                newsym.Offset = v.Value.Offset;

                if(Program.comm_objs.ContainsKey(newsym.name))
                {
                    newsym.IsCommon = true;
                    newsym.Offset = Program.comm_objs[newsym.name].Align.Evaluate(ms).AsInt;
                    newsym.Size = Program.comm_objs[newsym.name].Size.Evaluate(ms).AsInt;
                }

                if(Program.obj_sizes.ContainsKey(newsym.name))
                {
                    newsym.Size = Program.obj_sizes[newsym.name].Evaluate(ms).AsInt;
                }

                if(Program.obj_types.ContainsKey(newsym.name))
                {
                    string t = Program.obj_types[newsym.name];
                    if (t == "function")
                        newsym.Type = 2;
                    else if (t == "object")
                        newsym.Type = 1;
                }

                if(Program.global_objs.ContainsKey(newsym.name))
                {
                    newsym.IsGlobal = true;
                }

                syms[newsym.name] = newsym;
            }
            foreach(var v in Program.comm_objs)
            {
                if (syms.ContainsKey(v.Key))
                    continue;

                Symbol newsym = new Symbol();
                newsym.name = v.Key;
                newsym.StrNdx = AllocateString(newsym.name, strtab);
                newsym.IsCommon = true;

                if(Program.global_objs.ContainsKey(newsym.name))
                    newsym.IsGlobal = true;
                if (Program.obj_types.ContainsKey(newsym.name))
                {
                    string t = Program.obj_types[newsym.name];
                    if (t == "function")
                        newsym.Type = 2;
                    else if (t == "object")
                        newsym.Type = 1;
                }

                newsym.Size = Program.comm_objs[newsym.name].Size.Evaluate(ms).AsInt;
                newsym.Offset = Program.comm_objs[newsym.name].Align.Evaluate(ms).AsInt;

                syms[newsym.name] = newsym;
            }
            foreach(var v in Program.relocs)
            {
                if (syms.ContainsKey(v.TargetName))
                    continue;

                Symbol newsym = new Symbol();
                newsym.name = v.TargetName;
                newsym.StrNdx = AllocateString(newsym.name, strtab);
                newsym.IsGlobal = true;
                newsym.Section = null;

                syms[newsym.name] = newsym;
            }

            // Symbols start with a null symbol, then all local symbols,
            //  then global ones.
            List<Symbol> sym_list = new List<Symbol>();
            sym_list.Add(null);

            // Add symbols for each section
            foreach(Section s in sects)
            {
                if (s == null)
                    continue;
                Symbol sect_sym = new Symbol();
                sect_sym.name = s.name;
                sect_sym.StrNdx = AllocateString(sect_sym.name, strtab);
                sect_sym.Index = sym_list.Count;
                sect_sym.Type = 3;
                sect_sym.Section = s;
                sect_sym.Offset = 0;
                sect_sym.Size = s.oput.Count;
                sym_list.Add(sect_sym);
            }

            // Now iterate through looking for local symbols
            foreach(var v in syms)
            {
                if (v.Value.IsGlobal)
                    continue;
                v.Value.Index = sym_list.Count();
                sym_list.Add(v.Value);
            }

            int max_local = sym_list.Count();

            // Now add global symbols
            foreach(var v in syms)
            {
                if (!v.Value.IsGlobal)
                    continue;
                v.Value.Index = sym_list.Count();
                sym_list.Add(v.Value);
            }

            // Extract a list of symbol indices
            Dictionary<string, int> sym_idx = new Dictionary<string, int>();
            foreach(var v in sym_list)
            {
                if (v == null)
                    continue;
                sym_idx[v.name] = v.Index;
            }

            // Begin writing out the elf file header
            w.Write((byte)0x7f);
            w.Write((byte)'E');
            w.Write((byte)'L');
            w.Write((byte)'F');
            w.Write((byte)1);
            w.Write((byte)1);
            w.Write((byte)1);
            for (int i = 0; i < 9; i++)
                w.Write((byte)0);

            w.Write((ushort)1);     // relocatable
            w.Write((byte)'J');     // Machine type 'J', 'C'
            w.Write((byte)'C');

            w.Write((uint)1);       // version
            w.Write((uint)0);       // e_entry
            w.Write((uint)0);       // e_phoff

            long e_shoff_offset = w.BaseStream.Position;
            w.Write((uint)0);       // e_shoff

            w.Write((uint)0);       // e_flags
            w.Write((ushort)52);      // e_ehsize
            w.Write((ushort)0);     // e_phentsize
            w.Write((ushort)0);     // e_phnum
            w.Write((ushort)40);    // e_shentsize
            w.Write((ushort)cur_sect);  // e_shnum
            w.Write((ushort)shstrtab.SectionIdx);   // e_shstrndx

            // Now write out the section data
            foreach(Section s in sects)
            {
                if (s == null)
                    continue;

                // align up to a multiple of 16
                while ((w.BaseStream.Position & 0xf) != 0)
                    w.Write((byte)0);

                switch(s.SectionType)
                {
                    case Section.SectType.NoBits:
                        s.SectionSize = s.cur_offset;
                        break;

                    case Section.SectType.ProgBits:
                    case Section.SectType.Note:
                    case Section.SectType.StrTab:
                        s.FileOffset = (int)w.BaseStream.Position;
                        foreach (byte b in s.oput)
                            w.Write(b);
                        s.SectionSize = (int)w.BaseStream.Position - s.FileOffset;
                        break;

                    case Section.SectType.SymTab:
                        s.FileOffset = (int)w.BaseStream.Position;

                        foreach(var sym in sym_list)
                        {
                            if(sym == null)
                            {
                                w.Write((uint)0);
                                w.Write((uint)0);
                                w.Write((uint)0);
                                w.Write((uint)0);
                            }
                            else
                            {
                                w.Write(sym.StrNdx);
                                w.Write(sym.Offset);
                                w.Write(sym.Size);

                                uint st_info = 0;
                                if (sym.IsWeak)
                                    st_info |= 0x20;
                                else if (sym.IsGlobal)
                                    st_info |= 0x10;
                                st_info |= (uint)sym.Type;

                                w.Write((byte)st_info);
                                w.Write((byte)0);

                                if (sym.IsCommon)
                                    w.Write((ushort)0xfff2);
                                else if (sym.Section == null)
                                    w.Write((ushort)0x0);
                                else
                                    w.Write((ushort)sym.Section.SectionIdx);
                            }
                        }

                        s.SectionSize = (int)w.BaseStream.Position - s.FileOffset;
                        break;

                    case Section.SectType.Rela:
                        s.FileOffset = (int)w.BaseStream.Position;

                        foreach(var r in s.relocs)
                        {
                            if (r == null)
                            {
                                w.Write((uint)0);
                                w.Write((uint)0);
                                w.Write((uint)0);
                            }
                            else
                            {
                                w.Write(r.SourceOffset);

                                uint sym_tab_idx = (uint)sym_idx[r.TargetName];
                                uint r_info = sym_tab_idx << 8;
                                r_info |= (uint)r.Type;
                                w.Write(r_info);

                                w.Write(r.Addend);
                            }
                        }

                        s.SectionSize = (int)w.BaseStream.Position - s.FileOffset;
                        break;
                }
            }

            // Align up to a multiple of 16
            while ((w.BaseStream.Position & 0xf) != 0)
                w.Write((byte)0);

            // Store section table offset back in the file header
            long shoff = w.BaseStream.Position;
            w.Seek((int)e_shoff_offset, System.IO.SeekOrigin.Begin);
            w.Write((uint)shoff);
            w.Seek((int)shoff, System.IO.SeekOrigin.Begin);

            // Write out section table
            foreach(var s in sects)
            {
                if(s == null)
                {
                    for (int i = 0; i < 10; i++)
                        w.Write((uint)0);
                }
                else
                {
                    w.Write((uint)s.ShStrNdx);

                    switch(s.SectionType)
                    {
                        case Section.SectType.NoBits:
                            w.Write((uint)8);
                            break;
                        case Section.SectType.Note:
                            w.Write((uint)7);
                            break;
                        case Section.SectType.ProgBits:
                            w.Write((uint)1);
                            break;
                        case Section.SectType.Rela:
                            w.Write((uint)4);
                            break;
                        case Section.SectType.StrTab:
                            w.Write((uint)3);
                            break;
                        case Section.SectType.SymTab:
                            w.Write((uint)2);
                            break;
                        case Section.SectType.Unknown:
                            w.Write((uint)0);
                            break;
                    }

                    uint sh_flags = 0;
                    if (s.Alloc)
                        sh_flags |= 0x2;
                    if (s.Write)
                        sh_flags |= 0x1;
                    if (s.Exec)
                        sh_flags |= 0x4;
                    w.Write(sh_flags);

                    w.Write((uint)0);   // sh_addr

                    w.Write((uint)s.FileOffset);
                    w.Write((uint)s.SectionSize);

                    switch(s.SectionType)
                    {
                        case Section.SectType.Rela:
                            w.Write((uint)symtab.SectionIdx);
                            w.Write((uint)s.RelocSectionIdx);
                            break;
                        case Section.SectType.SymTab:
                            w.Write((uint)strtab.SectionIdx);
                            w.Write((uint)max_local);
                            break;
                        default:
                            w.Write((uint)0);
                            w.Write((uint)0);
                            break;
                    }

                    w.Write((uint)4);       // sh_addralign

                    switch(s.SectionType)
                    {
                        case Section.SectType.Rela:
                            w.Write((uint)12);
                            break;
                        case Section.SectType.SymTab:
                            w.Write((uint)16);
                            break;
                        default:
                            w.Write((uint)0);
                            break;
                    }
                }
            }			
		}