private void AddCode(ElfFile file, AsmContext context) { if (context.CodeSection.VirtualSize > 0) { file.Sections.Add(new ElfSection { Name = file.Strings.SaveString(".text"), Type = ElfSectionType.ProgBits, Address = 0, Flags = ElfSectionFlags.Alloc | ElfSectionFlags.Executable, Size = (uint)context.CodeSection.BytesCount, Align = 2, Offset = (uint)file.Data.Position }); file.Segments.Add(new ElfSegment { Type = ElfSegmentType.Load, Offset = (uint)file.Data.Position, VirtualAddress = 0, PhysicalAddress = 0, FileSize = (uint)context.CodeSection.BytesCount, MemorySize = (uint)context.CodeSection.VirtualSize, Flags = ElfSegmentFlags.Executable | ElfSegmentFlags.Readable, Align = 1 }); file.Data.Write(context.CodeSection.Content.ToArray(), 0, context.CodeSection.BytesCount); } }
public void SaveElf(AsmContext context, string fileName) { using (var file = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { SaveElf(context, file); file.Flush(); file.Close(); } }
public void Save(AsmContext context, Stream stream) { var file = new ElfFile(); var writer = new BinaryWriter(stream); file.Sections.Add(new ElfSection()); AddCode(file, context); AddData(file, context); AddFlash(file, context); AddDebugLine(file, context); var sectionsStringsIndex = file.AddStringsSection(); const int headerSize = 0x34; const int segmentsOffset = headerSize; const int segmentEntrySize = 0x20; var dataOffset = (uint)(segmentsOffset + file.Segments.Count * segmentEntrySize); var sectionsOffset = dataOffset + file.Data.Length; var header = new ElfHeader { Identification = { Magic = new[] { (char)0x7f, 'E', 'L', 'F' }, FileClass = ElfFileClass.Elf32, DataType = ElfDataType.Lsb, Version = 1, }, Type = ElfType.Executable, Machine = 0x53, Version = 1, Entry = 0x0, ProgramHeaderOffset = segmentsOffset, SectionHeaderOffset = (uint)sectionsOffset, Flags = 0x84, ElfHeaderSize = headerSize, ProgramHeaderEntrySize = segmentEntrySize, ProgramHeaderCount = (ushort)file.Segments.Count, SectionHeaderEntrySize = 0x28, SectionHeaderCount = (ushort)file.Sections.Count, StringSectionIndex = (ushort)sectionsStringsIndex }; writer.WriteElf32(header); foreach (var segment in file.Segments) { var cloned = segment; cloned.Offset += dataOffset; writer.WriteElf32(cloned); } writer.Write(file.Data.ToArray()); foreach (var section in file.Sections) { var cloned = section; if (section.Type != ElfSectionType.Null) { cloned.Offset += dataOffset; } writer.WriteElf32(cloned); } }
public AsmContext Assemble(string content, string fileName = null) { var symbols = new AsmSymbols(); IList<Token> tokens = new List<Token>(); LoadRecursive(content, tokens, fileName); tokens = ProcessSymbolConstants(tokens, symbols); AsmContext last = null; for (var i = 1; i < 10; i++) { var context = new AsmContext { Queue = new TokensQueue(tokens), Symbols = symbols, Pass = i }; var parser = new AsmParser(context); AssemblePass(context, parser); if (TheSame(last, context)) break; last = context; } return last; }
public AsmParser(AsmContext context) { _context = context; _calculator = new ExpressionCalculator(context); }
private void AddDebugLine(ElfFile file, AsmContext context) { var mem = new MemoryStream(); var writer = new BinaryWriter(mem); var hdr = new DebugLineHeader { FileNames = new[] { new DebugLineFile {Name = "test.asm"}, new DebugLineFile {Name = "test2.asm"}, } }; writer.WriteDwarf2(hdr); if (mem.Length > 0) { file.Sections.Add(new ElfSection { Name = file.Strings.SaveString(".debug_line"), Type = ElfSectionType.ProgBits, Address = 0, Flags = ElfSectionFlags.None, Size = (uint)mem.Length, Align = 1, Offset = (uint)file.Data.Position }); file.Data.Write(mem.ToArray(), 0, (int)mem.Length); } }
public void SaveElf(AsmContext context, Stream stream) { new ElfBuilder().Save(context, stream); }
private static bool TheSame(AsmContext prev, AsmContext current) { if (prev == null) return false; return current.CodeSection.TheSame(prev.CodeSection); }
private static void SkipEmptyLines(AsmContext context) { while (context.Queue.Count > 0) { Token token = context.Queue.Peek(); if (token.Type != TokenType.NewLine) return; context.Queue.Read(); } }
private static void ProcessSection(AsmContext context) { var typeToken = context.Queue.Read(); if (typeToken.Type != TokenType.Literal) { throw new TokenException("expected section type", typeToken); } var type = typeToken.ParseSectionType(); if (type == AsmSectionType.None) { throw new TokenException("invalid section type", typeToken); } context.SetSection(type); }
private static bool CheckLabel(Token token, AsmContext context) { if (context.Queue.Count > 0) { var next = context.Queue.Peek(); if (next.Type == TokenType.Colon) { context.Queue.Read(); context.DefineLabel(token); return true; } } return false; }
private static bool CheckData(Token token, AsmContext context, AsmParser parser) { if (IsDataDirective(token)) { ProcessDataDirective(token, parser, context.CurrentSection); return true; } if (!context.Queue.IsEndOfLine) { var preview = context.Queue.Peek(); if (IsDataDirective(preview)) { context.Queue.Read(TokenType.Literal); context.DefineLabel(token); ProcessDataDirective(preview, parser, context.CurrentSection); return true; } } return false; }
private static void AssemblePass(AsmContext context, AsmParser parser) { while (context.Queue.Count > 0) { SkipEmptyLines(context); if (context.Queue.Count == 0) break; AssembleLine(context, parser); } }
private static void AssembleLine(AsmContext context, AsmParser parser) { var token = context.Queue.Read(TokenType.Literal); try { if (CheckLabel(token, context)) { return; } if (CheckData(token, context, parser)) { return; } switch (token.StringValue.ToLower()) { case "section": ProcessSection(context); break; case "org": ProcessOrg(parser, context.CurrentSection); break; default: var opcode = AvrOpcodes.Get(token.StringValue); if (opcode != null) { opcode.Compile(parser, context.CurrentSection); } else { throw new TokenException("Illegal instruction " + token.StringValue, token); } break; } if (context.Queue.Count > 0) { var nl = context.Queue.Peek(); if (nl.Type != TokenType.NewLine) { throw new TokenException("Extra characters on line", nl); } } } catch (PureSectionDataException exc) { throw new PureSectionDataException(exc.Message, token); } }