private void WriteElf64Segment(ElfProgramHeader ph, System.IO.BinaryWriter w) { throw new NotImplementedException(); }
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); }
private void WriteElf32Segment(ElfProgramHeader ph, System.IO.BinaryWriter w) { w.Write((uint)ph.p_type); w.Write((uint)ph.p_offset); w.Write((uint)ph.p_vaddr); w.Write((uint)ph.p_paddr); w.Write((uint)ph.p_filesz); w.Write((uint)ph.p_memsz); w.Write((uint)ph.p_flags); w.Write((uint)ph.p_align); }