예제 #1
0
 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);
     }
 }
예제 #2
0
 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();
     }
 }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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;
        }
예제 #5
0
 public AsmParser(AsmContext context)
 {
     _context = context;
     _calculator = new ExpressionCalculator(context);
 }
예제 #6
0
 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);
     }
 }
예제 #7
0
 public void SaveElf(AsmContext context, Stream stream)
 {
     new ElfBuilder().Save(context, stream);
 }
예제 #8
0
 private static bool TheSame(AsmContext prev, AsmContext current)
 {
     if (prev == null) return false;
     return current.CodeSection.TheSame(prev.CodeSection);
 }
예제 #9
0
 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();
     }
 }
예제 #10
0
        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);
        }
예제 #11
0
 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;
 }
예제 #12
0
 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;
 }
예제 #13
0
        private static void AssemblePass(AsmContext context, AsmParser parser)
        {
            while (context.Queue.Count > 0) {
                SkipEmptyLines(context);
                if (context.Queue.Count == 0) break;

                AssembleLine(context, parser);
            }
        }
예제 #14
0
        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);
            }
        }