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()); }
public override EvalResult Evaluate(MakeState s) { return new EvalResult(val); }
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); }*/ }
public override EvalResult Evaluate(MakeState s) { return e; }
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(); } }
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; } } } }