Пример #1
0
        public virtual EvalResult Evaluate(MakeState s)
        {
            EvalResult ea, eb;

            switch (op)
            {
                case Tokens.NOT:
                    ea = a.Evaluate(s);
                    return new EvalResult(~ea.AsInt);

                case Tokens.LNOT:
                    ea = a.Evaluate(s);
                    if (ea.AsInt == 0)
                        return new EvalResult(1);
                    else
                        return new EvalResult(0);

                case Tokens.LAND:
                    ea = a.Evaluate(s);
                    if (ea.AsInt == 0)
                        return new EvalResult(0);
                    eb = b.Evaluate(s);
                    if (eb.AsInt == 0)
                        return new EvalResult(0);
                    return new EvalResult(1);

                case Tokens.LOR:
                    ea = a.Evaluate(s);
                    if (ea.AsInt != 0)
                        return new EvalResult(1);
                    eb = b.Evaluate(s);
                    if (eb.AsInt != 0)
                        return new EvalResult(1);
                    return new EvalResult(0);

                case Tokens.PLUS:
                    ea = a.Evaluate(s);
                    eb = b.Evaluate(s);

                    if (ea.Type == EvalResult.ResultType.Int && eb.Type == EvalResult.ResultType.Int)
                        return new EvalResult(ea.intval + eb.intval);
                    else if (ea.Type == EvalResult.ResultType.String && eb.Type == EvalResult.ResultType.String)
                        return new EvalResult(ea.strval + eb.strval);
                    else if (ea.Type == EvalResult.ResultType.Void && eb.Type == EvalResult.ResultType.Void)
                        return new EvalResult();
                    else if(ea.Type == EvalResult.ResultType.Relocation && eb.Type == EvalResult.ResultType.Int)
                        return new EvalResult(new Relocation
                        {
                            Addend = ea.relocval.Addend + eb.intval,
                            IsPCRel = ea.relocval.IsPCRel,
                            SourceOffset = ea.relocval.SourceOffset,
                            SourceSection = ea.relocval.SourceSection,
                            TargetName = ea.relocval.TargetName,
                            TargetSection = ea.relocval.TargetSection,
                            Type = ea.relocval.Type
                        });
                    else if(ea.Type == EvalResult.ResultType.Int && eb.Type == EvalResult.ResultType.Relocation)
                        return new EvalResult(new Relocation
                        {
                            Addend = eb.relocval.Addend + ea.intval,
                            IsPCRel = eb.relocval.IsPCRel,
                            SourceOffset = eb.relocval.SourceOffset,
                            SourceSection = eb.relocval.SourceSection,
                            TargetName = eb.relocval.TargetName,
                            TargetSection = eb.relocval.TargetSection,
                            Type = eb.relocval.Type
                        });

                    else
                        throw new Exception("Mismatched arguments to PLUS: " + ea.Type.ToString() + " and " + eb.Type.ToString());

                case Tokens.MUL:
                    ea = a.Evaluate(s);
                    eb = b.Evaluate(s);

                    return new EvalResult(ea.AsInt * eb.AsInt);

                case Tokens.MINUS:
                    ea = a.Evaluate(s);

                    if (b == null)
                    {
                        // unary minus
                        if (ea.Type == EvalResult.ResultType.Void)
                            return ea;
                        if (ea.Type == EvalResult.ResultType.String)
                            throw new Exception("Cannot apply unary minus to type string");
                        return new EvalResult(0 - ea.intval);
                    }
                    else
                    {
                        eb = b.Evaluate(s);

                        if (ea.Type == EvalResult.ResultType.String && (eb.Type == EvalResult.ResultType.Int || eb.Type == EvalResult.ResultType.Void))
                        {
                            int rem_amount = eb.AsInt;
                            if (rem_amount > ea.strval.Length)
                                rem_amount = ea.strval.Length;
                            return new EvalResult(ea.strval.Substring(0, ea.strval.Length - rem_amount));
                        }
                        else if (ea.Type == EvalResult.ResultType.String && eb.Type == EvalResult.ResultType.String)
                        {
                            if (ea.strval.EndsWith(eb.strval))
                                return new EvalResult(ea.strval.Substring(0, ea.strval.Length - eb.strval.Length));
                            else
                                throw new Exception(ea.strval + " does not end with " + eb.strval);
                        }
                        else if (ea.Type == EvalResult.ResultType.Void && eb.Type == EvalResult.ResultType.Void)
                        {
                            return new EvalResult();
                        }
                        else if(ea.Type == EvalResult.ResultType.Relocation && eb.Type == EvalResult.ResultType.Relocation)
                        {
                            if (ea.relocval.TargetSection != null &&
                                ea.relocval.TargetSection == eb.relocval.TargetSection)
                            {
                                return new EvalResult(Program.los[ea.relocval.TargetName].Offset -
                                    Program.los[eb.relocval.TargetName].Offset);
                            }
                            else throw new NotSupportedException();
                        }
                        else
                        {
                            return new EvalResult(ea.AsInt - eb.AsInt);
                        }
                    }

                case Tokens.EQUALS:
                case Tokens.NOTEQUAL:
                    {
                        int _true = 1;
                        int _false = 0;

                        if (op == Tokens.NOTEQUAL)
                        {
                            _true = 0;
                            _false = 1;
                        }

                        ea = a.Evaluate(s);
                        eb = b.Evaluate(s);

                        if (ea.Type == EvalResult.ResultType.String && eb.Type == EvalResult.ResultType.String)
                        {
                            if (ea.strval == null)
                            {
                                if (eb.strval == null)
                                    return new EvalResult(_true);
                                else
                                    return new EvalResult(_false);
                            }
                            if (ea.strval.Equals(eb.strval))
                                return new EvalResult(_true);
                            else
                                return new EvalResult(_false);
                        }
                        else
                        {
                            if (ea.AsInt == eb.AsInt)
                                return new EvalResult(_true);
                            else
                                return new EvalResult(_false);
                        }
                    }

                case Tokens.LT:
                    ea = a.Evaluate(s);
                    eb = b.Evaluate(s);

                    if (ea.AsInt < eb.AsInt)
                        return new EvalResult(1);
                    else
                        return new EvalResult(0);

            }

            throw new NotImplementedException(op.ToString());
        }
Пример #2
0
 public override EvalResult Evaluate(MakeState s)
 {
     return new EvalResult(val);
 }
Пример #3
0
        public override EvalResult Evaluate(MakeState s)
        {
            // Is it a register?
            if(Program.regs.ContainsKey(val.ToUpper()))
            {
                var e = new EvalResult();
                e.strval = val.ToUpper();
                e.intval = Program.regs[e.strval];
                e.Type = EvalResult.ResultType.Register;
                return e;
            }

            string full_name = val;

            // If defined in the current file, say so
            if (s.lo.ContainsKey(val))
            {
                // Yes - emit a relocation to the label
                Relocation r = new Relocation();
                r.TargetName = val;
                r.TargetSection = s.lo[val].Section;
                r.Addend = addend;
                r.SourceSection = s.cs;
                r.IsPCRel = is_pcrel;

                return new EvalResult(r);
            }
            else
            {
                // ld defines all unknown symbols as externals
                Relocation r = new Relocation();
                r.TargetName = val;
                r.TargetSection = null;
                r.Addend = addend;
                r.SourceSection = s.cs;
                r.IsPCRel = is_pcrel;

                return new EvalResult(r);
            }
            
            /*if (s.IsDefined(val) == true)
                 return s.GetDefine(val);
            {
                // Not defined in the current section.  Is it
                //  in another?
                if (s.lo.ContainsKey(val))
                {
                    // Yes - emit a relocation to the label
                    Relocation r = new Relocation();
                    r.TargetName = val;
                    r.TargetSection = s.lo[val].Section;
                    r.Addend = addend;
                    r.SourceSection = s.cs;
                    r.IsPCRel = is_pcrel;

                    return new EvalResult(r);
                }

                // ld defines all unknown symbols as externals
                Relocation rext = new Relocation();
                rext.TargetName = val;
                rext.TargetSection = null;
                rext.Addend = addend;
                rext.SourceSection = s.cs;
                rext.IsPCRel = is_pcrel;

                return new EvalResult(rext);
            }*/
        }
Пример #4
0
 public override EvalResult Evaluate(MakeState s)
 {
     return e;
 }
Пример #5
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();
            }
        }
Пример #6
0
		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;
                    }
                }
            }			
		}