private ushort GetOperand(ParsedInstruction currentLine, out Error error) { if (currentLine.operandExpression == null) { error = Error.None; return(currentLine.operandValue.Value); } if (currentLine.operandExpression != null) { StringSection expression = currentLine.operandExpression; var result = Assembler.Evaluator.EvaluateExpression(ref expression, currentLine.sourceLine, out error).Value; if (error.Code != ErrorCode.None) { error = new Error(error, currentLine.sourceLine); return(0); } else if (!expression.IsNullOrEmpty) { error = new Error(ErrorCode.Invalid_Expression, Error.Msg_InvalidExpression, currentLine.sourceLine); return(0); } return(result); } error = new Error(ErrorCode.Engine_Error, "Instruction required an operand, but none was present. Instruction may have been mis-parsed.", currentLine.sourceLine); return(0); }
public Script(Resource res, bool translated) { Resource = res; _translated = translated; SourceData = res.GetContent(translated); ushort i = 0; while (i < SourceData.Length) { SectionType type = (SectionType)Helpers.GetUShortBE(SourceData, i); if (type == SectionType.None) { break; } ushort size = (ushort)(Helpers.GetUShortBE(SourceData, i + 2) - 4); i += 4; Section sec = Section.Create(this, type, SourceData, i, size); Sections.Add(sec); i += size; if (sec is StringSection) { _strings = (StringSection)sec; } } foreach (var sec in Sections) { sec.SetupByOffset(); } }
public IList <StringSection> ProcessString(string rawText) { const string spanPattern = @"(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+"; MatchCollection collection = Regex.Matches(rawText, spanPattern, RegexOptions.None); var sections = new List <StringSection>(); foreach (Match item in collection) { var lastIndex = 0; var foundText = item.Value; var tt = rawText.Substring(lastIndex); var index = tt.IndexOf(foundText); if (lastIndex != index) { var tmpSS = new StringSection() { Text = rawText.Substring(lastIndex, index - lastIndex) }; sections.Add(tmpSS); lastIndex = lastIndex + item.Length + index; } var ss = new StringSection() { Text = rawText.Substring(index, item.Length), Link = item.Value }; sections.Add(ss); rawText = rawText.Substring(lastIndex); } return(sections); }
public override void Process(Pass pass, out Error error) { error = Error.None; LiteralValue value; if (Address.IsExpression) { StringSection exp = Address.Expression; value = pass.Assembler.Evaluator.EvaluateExpression(ref exp, SourceLine, out error); if (error.Code == ErrorCode.None) { if (exp.Length != 0) { error = new Error(ErrorCode.Unexpected_Text, Error.Msg_InvalidExpression, SourceLine); return; } } else { return; } } else { value = Address.Literal; } pass.SetAddress(value.Value); }
/// <summary> /// Returns a symbol name, or a zero-length string of no symbol was found. /// </summary> /// <param name="exp"></param> /// <returns></returns> private StringSection GetSymbol(StringSection exp) { // Check for special '$' variable if (exp.Length > 0 && exp[0] == '$' && !char.IsLetter(exp[0]) && !char.IsDigit(exp[0])) { return("$"); } if (exp.Length == 0) { return(StringSection.Empty); } if (!char.IsLetter(exp[0]) && exp[0] != '@') { return(StringSection.Empty); } int i = 1; while (i < exp.Length) { char c = exp[i]; if (char.IsLetter(c) | char.IsDigit(c) | c == '_') { i++; } else { var result = exp.Substring(0, i); return(result); } } return(exp); }
private Span CreateSpan(StringSection section) { var text = section.Text.StripHtml()?.Trim(); if (string.IsNullOrEmpty(text)) { return(null); } text = Regex.Replace(section.Text, "<br.*?>|<.?p>", "\n") .StripHtml(); var span = new Span { Text = text }; if (!string.IsNullOrEmpty(section.Link)) { span.GestureRecognizers.Add(new TapGestureRecognizer() { Command = new Command <string>(OpenLink), CommandParameter = section.Link }); span.TextColor = Color.FromHex("#0072bc"); span.TextDecorations = TextDecorations.Underline; } return(span); }
private Span CreateSpan(StringSection section) { var span = new Span() { Text = section.Text }; switch (section.CommandType) { case CommandType.Url: span.GestureRecognizers.Add(new TapGestureRecognizer() { Command = openUrlCommand, CommandParameter = section.Parameter }); span.TextColor = (Color)App.Current.Resources["LinkTextColor"]; break; case CommandType.Group: span.GestureRecognizers.Add(new TapGestureRecognizer() { Command = openGroupCommand, CommandParameter = section.Parameter }); span.TextColor = (Color)App.Current.Resources["LinkTextColor"]; break; } return(span); }
private bool IsDirective(StringSection directiveName) { int listStart = 0; int listEnd = directiveNames.Length / 2; // Exclusive int listCount = listEnd - listStart; while (listCount > 1) { // first item of second half int split = listStart + listCount / 2; var splitText = directiveNames[split]; var compare = StringSection.Compare(directiveName, splitText, true); if (compare == 0) { return(true); } if (compare > 0) // directiveName > splitText { listStart = split; } else { listEnd = split; } listCount = listEnd - listStart; } return(StringSection.Compare(directiveName, directiveNames[listStart], true) == 0); }
private void ParsePlusOrMinusLabel(ref StringSection line, char labelChar, int iInstruction, int iSourceLine) { int charCount = 1; // Number of times the label char (+ or -) appears while (charCount < line.Length && line[charCount] == labelChar) { charCount++; } if (labelChar == '+') { assembly.AnonymousLabels.AddPlusLabel(charCount, iSourceLine); } else if (labelChar == '-') { assembly.AnonymousLabels.AddMinusLabel(charCount, iSourceLine); } else { throw new ArgumentException("Invalid label character for +/- label.", "labelChar"); } assembly.TagAnonLabel(iInstruction, iSourceLine); line = line.Substring(charCount).Trim(); // Remove colon if present if (line.Length > 0 && line[0] == ':') { line = line.Substring(1).TrimLeft(); } }
public Assignment(int instructionIndex, int sourceLine, StringSection variable, bool isLabel, AsmValue value) : base(instructionIndex, sourceLine) { this.Variable = variable; this.Value = value; this.IsLabel = isLabel; }
private void RemoveComments(ref StringSection line) { // ; denotes a comment, except within a string bool inString = false; for (int i = 0; i < line.Length; i++) { if (inString) { if (line[i] == '\"') // End of string // unless it is preceeded by a backslash (then it's as escaped quote) { if (i == 0 || line[i - 1] != '\\') { inString = false; } } } else { if (line[i] == ';') // Comment { line = line.Substring(0, i); return; } else if (line[i] == '\"') // Start of string { inString = true; } } } }
private void StoreEditList() { if (treeSections.SelectedNode != null && _targetStrings != null && _modifiedSection) { if (_targetSection >= 0) { StringSection section = _targetStrings._sections[_targetSection]; section._localizedStrings = new List <StringLocalized>(); foreach (StringLocalized newString in _editList.Values) { section.LocalizedStrings.Add(newString); } } else { StringSection section = new StringSection(); section._name = _defaultStrings._sections[_currentSection].SectionName; section._localizedStrings = new List <StringLocalized>(); foreach (StringLocalized newString in _editList.Values) { section.LocalizedStrings.Add(newString); } _targetStrings.Sections.Add(section); } _modifiedSection = false; } }
private void Write(StringSection ss) { sb.AppendLine($"[String section]"); foreach (var s in ss.Strings) { sb.AppendLine($"{s.Address:x4} = '{s.GetStringEscape()}'"); } }
private static void StripComments(ref StringSection line) { int iComment = line.IndexOf(';'); if (iComment >= 0) { line = line.Substring(0, iComment); } line = line.Trim(); }
private StringSection ParseDirectiveName(StringSection text) { int i = 0; while (i < text.Length && Char.IsLetter(text[i])) { i++; } return(text.Substring(0, i)); }
public IncBinDirective(int instructionIndex, int sourceLine, StringSection file) : base(instructionIndex, sourceLine) { file = file.Trim(); if (file.Length > 1 && file[0] == '\"' && file[file.Length - 1] == '\"') { file = file.Substring(1, file.Length - 2); } this.Filename = file.ToString(); }
private bool ParseNamedLabels(ref StringSection line, int iParsedLine, int iSourceLine) { int iColon = line.IndexOf(':'); if (iColon < 0) { return(false); } if ((line.Length - 1 > iColon) && (line[iColon + 1] == '=')) { // := is not a label return(false); } var labelName = line.Substring(0, iColon).Trim(); // Todo: should be able to validate via a 'parse symbol' func // Check for nonzero length and that label starts with letter or @ if (labelName.Length == 0) { return(false); } if (!char.IsLetter(labelName[0]) && labelName[0] != '@') { return(false); } for (int i = 1; i < labelName.Length; i++) // i = 1 because we've already checked zero { if (!char.IsLetter(labelName[i]) && !char.IsDigit(labelName[i]) && labelName[i] != '_') { return(false); } } if (labelName[0] == '@') // Local label { labelName = labelName.Substring(1); // Remove @ string fullName = mostRecentNamedLabel + "." + labelName.ToString(); // example: SomeFunction.LoopTop assembly.Labels.Add(new Label(fullName, iParsedLine, iSourceLine, true)); } else // Normal label { var sLabelName = labelName.ToString(); mostRecentNamedLabel = sLabelName; assembly.Labels.Add(new Label(sLabelName, iParsedLine, iSourceLine, false)); } line = line.Substring(iColon + 1).TrimLeft(); return(true); }
private void ProcessDirective(StringSection directiveName, StringSection directiveText) { string directive = directiveName.ToString().ToUpper(); switch (directive) { case "ORG": default: break; } }
public void Process(StringSection source, List <StringSection> output, IFileSystem files) { bool moreLines = !source.IsNullOrEmpty; while (moreLines) { int iLineBreak = source.IndexOfAny(lineBreaks); StringSection line; if (iLineBreak == -1) { // Last line line = source; source = StringSection.Empty; moreLines = false; } else { line = source.Substring(0, iLineBreak); bool isCRLF = (source[iLineBreak] == '\r') && (source.Length > iLineBreak + 1) && (source[iLineBreak + 1] == '\n'); if (isCRLF) { source = source.Substring(iLineBreak + 2); } else { source = source.Substring(iLineBreak + 1); } } if (IsIncludeLine(line)) { string includeFile = line.Substring(includeDirective.Length).Trim().ToString(); // Need to remove optional quotes if (includeFile.Length >= 2 && includeFile[0] == '\"' && includeFile[includeFile.Length - 1] == '\"') { includeFile = includeFile.Substring(1, includeFile.Length - 2).Trim(); } if (assembler.FileSystem.FileExists(includeFile)) { ProcessInclude(output, files, includeFile); } else { assembler.AddError(new Error(ErrorCode.File_Error, string.Format(Error.Msg_FileNotFound_name, includeFile), output.Count)); } } else { output.Add(line); } } }
/// <summary> /// Returns a value between 0 and 255, or -1 if no opcode was found, or -2 if the addressing mode is not available for the instruction.. /// </summary> /// <param name="instruction"></param> /// <param name="addressing"></param> /// <returns></returns> private int FindOpcode(StringSection instruction, Opcode.addressing addressing) { var ops = Opcode.allOps; bool instructionFound = false; bool foundInstructionInvalid = false; for (int i = 0; i < Opcode.allOps.Length; i++) { if (StringEquals(ops[i].name, instruction, true)) { // Note that the instruction exists. We need to tell the user whether // an instruction does not exist or the desired addressing mode is not available. instructionFound = true; var addrMode = ops[i].addressing; // Branch instructions will be treated as absolute until they are actually encoded. if (addrMode == Opcode.addressing.relative) { addrMode = Opcode.addressing.absolute; } if (addressing == addrMode) { if (ops[i].valid | Assembler.AllowInvalidOpcodes) { return(i); } else { foundInstructionInvalid = true; } } } } if (instructionFound) { if (foundInstructionInvalid) { return((int)OpcodeError.InvalidOpcode); } else { return((int)OpcodeError.InvalidAddressing); } } else { return((int)OpcodeError.UnknownInstruction); } }
private void WriteStrings(StringSection section) { sb.AppendLine("(string"); if (section != null) { foreach (var str in section.Strings) { sb.AppendFormat(" string_{0:x4} \"{1}\"", str.Address, str.Value).AppendLine(); } } sb.AppendLine(")"); sb.AppendLine(); }
private void tvSections_AfterSelect(object sender, TreeViewEventArgs e) { _currentSection = tvSections.SelectedNode.Index; StringSection section = _defaultStrings._sections[_currentSection]; lvStrings.Items.Clear(); foreach (StringLocalized defaultString in section.LocalizedStrings) { ListViewItem stringItem = new ListViewItem(defaultString.StringName); stringItem.SubItems.Add(defaultString.Text); lvStrings.Items.Add(stringItem); } }
private bool IsIncludeLine(StringSection line) { if (line.Length < includeDirective.Length) { return(false); } var lineStart = line.Substring(0, includeDirective.Length); if (StringSection.Compare(lineStart, includeDirective, true) == 0) { return(true); } return(false); }
/// <summary> /// Returns a char array containing all the characters from a string. Escapes are processed. The specified string /// should not include the opening quote. The parsed string will be removed from the string passed in. The closing /// quote will not be removed, so that the caller can examine it and verify that there was a closing quote. /// </summary> /// <param name="section"></param> /// <returns></returns> public static char[] ParseString(ref StringSection str, out ErrorCode error) { error = ErrorCode.None; // Only one thread can run this method at a time lock (ParseLock) { charBuilder.Clear(); while (str.Length > 0) { char c = str[0]; if (c == '\"') { return(charBuilder.ToArray()); } else if (c == '\\') { str = str.Substring(1); if (str.Length > 0) { c = str[0]; int escapeIndex = Array.IndexOf(escapeCodes, c); if (escapeIndex < 0) { error = ErrorCode.Invalid_Escape; return(null); } else { charBuilder.Add(escapeValues[escapeIndex]); } } else { error = ErrorCode.Invalid_Escape; return(null); } } else { charBuilder.Add(c); } str = str.Substring(1); } return(charBuilder.ToArray()); } }
bool EndsWith(StringSection text, string ending) { int diff = text.Length - ending.Length; if (diff < 0) { return(false); } for (int i = 0; i < ending.Length; i++) { if (text[i + diff] != ending[i]) { return(false); } } return(true); }
private void lvCreateStrings_AfterLabelEdit(object sender, LabelEditEventArgs e) { if (e.Label == null) { return; } StringSection stringSection = (StringSection)tvCreateSections.SelectedNode.Tag; foreach (StringLocalized str in stringSection.LocalizedStrings) { if (str.StringName == lvCreateStrings.Items[e.Item].SubItems[1].Text) { str._text = e.Label; } } btnSaveNewStrings.Enabled = true; }
public override void Process(Pass pass, out Error error) { error = Error.None; if (Value.IsLiteral) { pass.Assembler.Values.SetValue(Variable, Value.Literal, IsLabel, out error); if (error.IsError) // Add source line { error = new Error(error, SourceLine); } if (IsLabel) { int bank = pass.Bank; pass.Assembler.AddDebugLabel(bank, Value.Literal.Value, Variable.ToString()); } } else { StringSection exp = Value.Expression; var expressionValue = pass.Assembler.Evaluator.EvaluateExpression(ref exp, int.MinValue, out error); if (!error.IsError) { pass.Assembler.Values.SetValue(Variable, expressionValue, IsLabel, out error); } if (error.IsError) // Add source line { error = new Error(error, SourceLine); } else if (IsLabel) { int bank = pass.Bank; if (bank < 0) { bank = 0; } pass.Assembler.AddDebugLabel(bank, expressionValue.Value, Variable.ToString()); } if (!exp.IsNullOrEmpty) { error = new Error(ErrorCode.Invalid_Expression, Error.Msg_InvalidExpression, SourceLine); } } }
private void btnAddSection_Click(object sender, EventArgs e) { if (!_defaultStrings.IsSection(_textBoxNewSection.Text) && _textBoxNewSection.Text != String.Empty) { StringSection section = new StringSection(); section._localizedStrings = new List <StringLocalized>(); section._name = _textBoxNewSection.Text; // section.isNew = true; _defaultStrings.Sections.Add(section); _textBoxNewSection.Text = string.Empty; btnSaveNewStrings.Enabled = true; DrawCreateSectionsTreeView(); } else { MessageBox.Show("A Section with the same name already exists", "Section Name", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } }
protected override void ProcessCurrentInstruction() { var currentLine = Assembly.ParsedInstructions[iCurrentInstruction]; var opcode = Opcode.allOps[currentLine.opcode]; bool SingleByteOperand = false; if (currentLine.operandExpression != null) { // If an AsmValue has not been resolved to a literal value yet, it is because it references a label, and thus must be 16-bit Error error; StringSection expression = currentLine.operandExpression; SingleByteOperand = Assembler.Evaluator.EvaluateExpression(ref expression, currentLine.sourceLine, out error).IsByte; if (error.Code != ErrorCode.None) { AddError(new Error(error, currentLine.sourceLine)); } else if (!expression.IsNullOrEmpty) { AddError(new Error(ErrorCode.Invalid_Expression, Error.Msg_InvalidExpression, currentLine.sourceLine)); } } else if (currentLine.operandValue.IsByte) { SingleByteOperand = true; } if (SingleByteOperand) { // Todo: Consider moving TryToConvertToZeroPage to more appropriate class if (Assembler.Parser.TryToConvertToZeroPage(ref currentLine)) { // If the instruction can be coded as zero-page, update it Assembly.ParsedInstructions[iCurrentInstruction] = currentLine; // Todo: consider method such as UpdateParsedInstruction } } var instructionLen = Opcode.GetParamBytes(currentLine.opcode) + 1; CurrentOutputOffset += instructionLen; CurrentAddress += instructionLen; }
protected override void Render(ConsoleRenderContext context, StringSection text) { switch (text.SectionType) { case StringSectionType.Normal: Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.Black; break; case StringSectionType.Error: Console.ForegroundColor = ConsoleColor.Red; Console.BackgroundColor = ConsoleColor.Black; break; case StringSectionType.Fatal: Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.Red; break; case StringSectionType.Highlighted: Console.ForegroundColor = ConsoleColor.Yellow; Console.BackgroundColor = ConsoleColor.Black; break; } if (text.IsMultiLine) { Console.WriteLine(); foreach (var item in text.Lines) { Console.Write("\t"); Console.WriteLine(item); } Console.WriteLine(); } else { Console.Write(text.Text); } Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.Black; }
private void StoreEditList() { if (treeSections.SelectedNode != null && _targetStrings != null && _modifiedSection) { if (_targetSection >= 0) { StringSection section = _targetStrings._sections[_targetSection]; section._localizedStrings = new List<StringLocalized>(); foreach (StringLocalized newString in _editList.Values) { section.LocalizedStrings.Add(newString); } } else { StringSection section = new StringSection(); section._name = _defaultStrings._sections[_currentSection].SectionName; section._localizedStrings = new List<StringLocalized>(); foreach (StringLocalized newString in _editList.Values) { section.LocalizedStrings.Add(newString); } _targetStrings.Sections.Add(section); } _modifiedSection = false; } }
private void btnAddSection_Click(object sender, EventArgs e) { if (!_defaultStrings.IsSection(_textBoxNewSection.Text) && _textBoxNewSection.Text!=String.Empty) { StringSection section = new StringSection(); section._localizedStrings = new List<StringLocalized>(); section._name = _textBoxNewSection.Text; // section.isNew = true; _defaultStrings.Sections.Add(section); _textBoxNewSection.Text = string.Empty; btnSaveNewStrings.Enabled = true; DrawCreateSectionsTreeView(); } else { MessageBox.Show("A Section with the same name already exists", "Section Name", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } }
private void AddSymbol(ISymbol sym, StringSection strtab, List<ElfSymbol> osyms, Dictionary<ISymbol, int> sym_map, Dictionary<ISection, int> sect_map) { ElfSymbol esym = new ElfSymbol(); esym.Name = sym.Name; esym.st_name = AllocateString(sym.Name, strtab); esym.st_value = sym.Offset; if (IsExecutable && sym.DefinedIn != null) esym.st_value += sym.DefinedIn.LoadAddress; esym.st_size = sym.Size; esym.st_bind = 0; switch(sym.Type) { case SymbolType.Global: esym.st_bind = 1; break; case SymbolType.Weak: esym.st_bind = 2; break; } esym.st_type = 0; switch (sym.ObjectType) { case SymbolObjectType.Object: esym.st_type = 1; break; case SymbolObjectType.Function: esym.st_type = 2; break; } esym.st_shndx = sect_map[sym.DefinedIn]; sym_map[sym] = osyms.Count; osyms.Add(esym); }
private static int AllocateString(string name, StringSection 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; }
protected override void Write(System.IO.BinaryWriter w) { Init(); // First, build a list of output sections List<SectionHeader> osects = new List<SectionHeader>(); Dictionary<ISection, int> osect_map = new Dictionary<ISection, int>(); osects.Add(new NullSection()); StringSection strtab = new StringSection(); StringSection shstrtab = new StringSection(); foreach(var sect in sections) { SectionHeader sh = new SectionHeader(); sh.sh_name = AllocateString(sect.Name, shstrtab); if (sect.HasData) sh.sh_type = 1; else sh.sh_type = 8; sh.sh_flags = 0; if (sect.IsWriteable) sh.sh_flags |= 0x1; if (sect.IsAlloc) sh.sh_flags |= 0x2; if (sect.IsExecutable) sh.sh_flags |= 0x4; sh.sh_addr = sect.LoadAddress; sh.sh_size = sect.Length; sh.sh_link = 0; sh.sh_info = 0; sh.sh_addralign = sect.AddrAlign; sh.sh_entsize = 0; osect_map[sect] = osects.Count; osects.Add(sh); } strtab.sh_name = AllocateString(".strtab", shstrtab); int strtab_idx = osects.Count; osects.Add(strtab); shstrtab.sh_name = AllocateString(".shstrtab", shstrtab); int shstrtab_idx = osects.Count; e_shstrndx = shstrtab_idx; osects.Add(shstrtab); SectionHeader symtab = new SectionHeader(); symtab.sh_name = AllocateString(".symtab", shstrtab); symtab.sh_link = strtab_idx; symtab.sh_type = 2; int symtab_idx = osects.Count; osects.Add(symtab); // Build symbol table List<ElfSymbol> osyms = new List<ElfSymbol>(); osyms.Add(new ElfSymbol()); Dictionary<ISymbol, int> sym_map = new Dictionary<ISymbol, int>(); // Add local symbols first foreach(var sym in symbols) { if (sym.Type == SymbolType.Local) AddSymbol(sym, strtab, osyms, sym_map, osect_map); } int last_local = osyms.Count; foreach(var sym in symbols) { if (sym.Type != SymbolType.Local) AddSymbol(sym, strtab, osyms, sym_map, osect_map); } symtab.sh_info = last_local; // Write out file header // e_ident w.Write((byte)0x7f); w.Write((byte)'E'); w.Write((byte)'L'); w.Write((byte)'F'); w.Write((byte)ec); w.Write((byte)ed); w.Write((byte)1); for (int i = 0; i < 9; i++) w.Write((byte)0); // store fh_start because we will re-write the header later int fh_start = (int)w.BaseStream.Position; switch(ec) { case ElfClass.ELFCLASS32: WriteElf32FileHeader(w); break; case ElfClass.ELFCLASS64: WriteElf64FileHeader(w); break; default: throw new Exception("Invalid ELF class"); } // Now write out the section data foreach(var s in sections) { // align up to addralign var sh = osects[osect_map[s]]; if (sh.sh_addralign != 0) { while ((w.BaseStream.Position % sh.sh_addralign) != 0) w.Write((byte)0); } sh.sh_offset = w.BaseStream.Position; if (s.HasData == false) continue; // write out data foreach (byte b in s.Data) w.Write(b); } // Write out string tables while ((w.BaseStream.Position % 16) != 0) w.Write((byte)0); strtab.sh_offset = w.BaseStream.Position; foreach (byte b in strtab.oput) w.Write(b); strtab.sh_size = strtab.oput.Count; while ((w.BaseStream.Position % 16) != 0) w.Write((byte)0); shstrtab.sh_offset = w.BaseStream.Position; foreach (byte b in shstrtab.oput) w.Write(b); shstrtab.sh_size = shstrtab.oput.Count; // Write out symbol table while ((w.BaseStream.Position % 16) != 0) w.Write((byte)0); symtab.sh_offset = w.BaseStream.Position; foreach (var sym in osyms) { switch (ec) { case ElfClass.ELFCLASS32: WriteElf32Symbol(sym, w); break; case ElfClass.ELFCLASS64: WriteElf64Symbol(sym, w); break; } } // Fill in file type specific details in various structures switch(ec) { case ElfClass.ELFCLASS32: symtab.sh_entsize = 16; symtab.sh_size = osyms.Count * symtab.sh_entsize; e_shentsize = 40; e_phentsize = 32; break; case ElfClass.ELFCLASS64: throw new NotImplementedException(); } // Write out section header table while ((w.BaseStream.Position % 16) != 0) w.Write((byte)0); e_shoff = w.BaseStream.Position; foreach(var sect in osects) { switch(ec) { case ElfClass.ELFCLASS32: WriteElf32Section(sect, w); break; case ElfClass.ELFCLASS64: WriteElf64Section(sect, w); break; } } // Write program headers e_phnum = 0; if (IsExecutable) { while ((w.BaseStream.Position % 16) != 0) w.Write((byte)0); e_phoff = w.BaseStream.Position; foreach (var sect in sections) { ElfProgramHeader ph = new ElfProgramHeader(); ph.p_type = ElfProgramHeader.PT_LOAD; ph.p_offset = (ulong)osects[osect_map[sect]].sh_offset; ph.p_vaddr = sect.LoadAddress; ph.p_paddr = 0; ph.p_filesz = sect.HasData ? (ulong)sect.Data.Count : 0UL; ph.p_memsz = (ulong)sect.Length; ph.p_flags = 0; if (sect.IsExecutable) ph.p_flags |= ElfProgramHeader.PF_X; if (sect.IsWriteable) ph.p_flags |= ElfProgramHeader.PF_W; ph.p_flags |= ElfProgramHeader.PF_R; ph.p_align = (ulong)sect.AddrAlign; if (ph.p_memsz != 0) { switch (ec) { case ElfClass.ELFCLASS32: WriteElf32Segment(ph, w); break; case ElfClass.ELFCLASS64: WriteElf64Segment(ph, w); break; } e_phnum++; } } } if (e_phnum == 0) e_phoff = 0; // Rewrite file header e_shnum = osects.Count; if (is_exec) e_type = 2; else e_type = 1; if(EntryPoint != null && IsExecutable) { var s = FindSymbol(EntryPoint); if (s != null && s.DefinedIn != null) e_entry = s.Offset + s.DefinedIn.LoadAddress; else { // default to offset 0x0 in text var sect = FindSection(".text"); if(sect == null) { // default to 0x0 Console.WriteLine("Entry point " + EntryPoint + " not found, defaulting to 0x0"); e_entry = 0; } else { Console.WriteLine("Entry point " + EntryPoint + " not found, defaulting to 0x" + sect.LoadAddress.ToString("X")); e_entry = sect.LoadAddress; } } } int cur_pos = (int)w.BaseStream.Position; w.Seek(fh_start, System.IO.SeekOrigin.Begin); switch(ec) { case ElfClass.ELFCLASS32: WriteElf32FileHeader(w); break; case ElfClass.ELFCLASS64: WriteElf64FileHeader(w); break; } w.Seek(cur_pos, System.IO.SeekOrigin.Begin); }