//- reading in ---------------------------------------------------------------- public static CoffSection readSection(BinaryIn source) { string name = source.getAsciiString(8); CoffSection sec = new CoffSection(name); sec.memSize = source.getFour(); sec.memPos = source.getFour(); sec.fileSize = source.getFour(); sec.filePos = source.getFour(); sec.relocTblPos = source.getFour(); uint skip1 = source.getFour(); //line numbers are deprecated sec.relocTblCount = source.getTwo(); uint skip2 = source.getTwo(); uint flagval = source.getFour(); sec.settings = SectionSettings.decodeFlags(flagval); uint mark = source.getPos(); source.seek(sec.filePos); byte[] secdata = source.getRange(sec.fileSize); sec.data = new List <byte>(secdata); source.seek(mark); return(sec); }
public CoffSymbol(String _name) { name = _name; bind = SYMBIND.NONE; typ = SYMTYPE.NONE; section = null; ofs = 0; size = 0; }
private void loadSections(BinaryIn source, uint secCount) { for (int i = 0; i < secCount; i++) { CoffSection sec = CoffSection.readSection(source); sec.owner = this; sec.secNum = i + 1; sections.Add(sec); } }
//----------------------------------------------------------------------------- public CoffSection findSection(String name) { CoffSection sec = null; if (secNames.ContainsKey(name)) { sec = secNames[name]; } return(sec); }
public void buildSectionTable() { //uint secStart = sizeOfHeaders; for (int i = 0; i < sections.Count; i++) { CoffSection sec = sections[i]; //file pos- if file size != 0, use that instead of data count sec.filePos = filepos; uint datasize = (uint)sec.data.Count; if (sec.fileSize > 0) { datasize = sec.fileSize; } sec.fileSize = (datasize + (fileAlignment - 1)) & ~(fileAlignment - 1); filepos += sec.fileSize; uint msize = (sec.memSize + fileAlignment - 1) & ~(fileAlignment - 1); if (sec.settings.hasCode) { sizeOfCode += msize; if (baseOfCode == 0) { baseOfCode = sec.memPos; } } if (sec.settings.hasInitData) { sizeOfInitializedData += msize; if (baseOfData == 0) { baseOfData = sec.memPos; } } if (sec.settings.hasUninitData) { sizeOfUninitializedData += msize; } uint memsize = (sec.memSize + memAlignment - 1) & ~(memAlignment - 1); mempos += memsize; } }
public static void loadRelocations(BinaryIn source, CoffSection sec, Win32Obj objfile) { source.seek(sec.relocTblPos); for (int i = 0; i < sec.relocTblCount; i++) { uint addr = source.getFour(); int symidx = (int)source.getFour(); uint reloctype = source.getTwo(); CoffRelocation.Reloctype reltype = CoffRelocation.Reloctype.NONE; switch (reloctype) { case 06: reltype = CoffRelocation.Reloctype.ABSOLUTE; //IMAGE_REL_I386_DIR32 break; case 07: reltype = CoffRelocation.Reloctype.RVA; //IMAGE_REL_I386_DIR32NB break; case 11: reltype = CoffRelocation.Reloctype.SECREL32; //IMAGE_REL_I386_SECREL break; case 20: reltype = CoffRelocation.Reloctype.RELATIVE; //IMAGE_REL_I386_REL32 break; default: break; } CoffSymbol sym = objfile.symbols[symidx]; CoffRelocation reloc = new CoffRelocation(addr - sec.memPos, sym, reltype); sec.relocations.Add(reloc); } }
public void buildRelocSection() { relocList.Sort(); BinaryOut relData = new BinaryOut(); uint basepage = relocList[0].addr & 0xFFFFF000; uint blocksize = 8; relData.putFour(basepage); uint blockstart = relData.getPos(); relData.putFour(0); foreach (CoffRelocationEntry rel in relocList) { uint page = rel.addr & 0xFFFFF000; if (page != basepage) { if (blocksize % 4 != 0) { relData.putTwo(0); blocksize += 2; } uint blockend = relData.getPos(); relData.seek(blockstart); relData.putFour(blocksize); relData.seek(blockend); basepage = page; blocksize = 8; relData.putFour(basepage); blockstart = relData.getPos(); relData.putFour(0); } uint ofs = rel.addr % 0x1000; ofs += 0x3000; relData.putTwo(ofs); blocksize += 2; } if (blocksize % 4 != 0) { relData.putTwo(0); blocksize += 2; } relData.seek(blockstart); relData.putFour(blocksize); relocSec = new CoffSection(".reloc"); relocSec.data = new List <byte>(relData.getData()); uint datasize = (uint)relocSec.data.Count; relocSec.filePos = filepos; relocSec.fileSize = (datasize + (fileAlignment - 1)) & ~(fileAlignment - 1); filepos += relocSec.fileSize; relocSec.memPos = mempos; relocSec.memSize = datasize; mempos += (datasize + (memAlignment - 1)) & ~(memAlignment - 1); relocSec.settings.canRead = true; relocSec.settings.hasInitData = true; relocSec.settings.canDiscard = true; uint msize = (relocSec.memSize + fileAlignment - 1) & ~(fileAlignment - 1); sizeOfInitializedData += msize; sections.Add(relocSec); baseRelocationTable.rva = relocSec.memPos; baseRelocationTable.size = relocSec.memSize; }
//standard sections public void buildExportSection() { uint ordinalBase = 1; BinaryOut expData = new BinaryOut(); expData.putFour(0); expData.putFour((uint)getTimestamp()); expData.putTwo(1); expData.putTwo(0); expData.putFour(0); //filename addr expData.putFour(ordinalBase); expData.putFour((uint)exportList.Count); expData.putFour((uint)exportList.Count); expData.putFour(0x28 + mempos); uint expnametbl = 0x28 + 4 * (uint)exportList.Count; expData.putFour(expnametbl + mempos); uint ordtbl = expnametbl + 4 * (uint)exportList.Count; expData.putFour(ordtbl + mempos); //export addr tbl foreach (CoffExportEntry exp in exportList) { expData.putFour(exp.addr); } //export name tbl expData.skip(4 * (uint)exportList.Count); //ordinal number tbl foreach (CoffExportEntry exp in exportList) { expData.putTwo(exp.ord - ordinalBase); } uint faddr = expData.getPos() + mempos; expData.putString(filename); List <uint> nameaddrs = new List <uint>(); foreach (CoffExportEntry exp in exportList) { nameaddrs.Add(expData.getPos() + mempos); expData.putString(exp.name); } expData.seek(0xc); expData.putFour(faddr); expData.seek(expnametbl); foreach (uint nameaddr in nameaddrs) { expData.putFour(nameaddr); } exportSec = new CoffSection(".edata"); exportSec.data = new List <byte>(expData.getData()); uint datasize = (uint)exportSec.data.Count; exportSec.filePos = filepos; exportSec.fileSize = (datasize + (fileAlignment - 1)) & ~(fileAlignment - 1); filepos += exportSec.fileSize; exportSec.memPos = mempos; exportSec.memSize = datasize; mempos += (datasize + (memAlignment - 1)) & ~(memAlignment - 1); exportSec.settings.canRead = true; exportSec.settings.hasInitData = true; uint msize = (exportSec.memSize + fileAlignment - 1) & ~(fileAlignment - 1); sizeOfInitializedData += msize; sections.Add(exportSec); dExportTable.rva = exportSec.memPos; dExportTable.size = exportSec.memSize; }
public Win32Exe() { filename = null; isDLL = false; mempos = 0; filepos = 0; dosHeader = null; //coff header fields machine = MachineType.IMAGE_FILE_MACHINE_I386; timeStamp = DateTime.Now; characteristics = new Characteristics(); //optional header fields magicNum = 0x010b; //PE32 executable majorLinkerVersion = 0; minorLinkerVersion = 1; sizeOfCode = 0; sizeOfInitializedData = 0; sizeOfUninitializedData = 0; addressOfEntryPoint = 0; baseOfCode = 0; baseOfData = 0; imageBase = 0x400000; //exe default image base memAlignment = 0x1000; fileAlignment = 0x200; majorOSVersion = 5; minorOSVersion = 1; majorImageVersion = 0; minorImageVersion = 0; majorSubsystemVersion = 5; minorSubsystemVersion = 1; win32VersionValue = 0; //reserved, must be zero sizeOfImage = 0; sizeOfHeaders = 0; checksum = 0; subsystem = 2; dLLCharacteristics = 0x140; sizeOfStackReserve = 0x100000; sizeOfStackCommit = 0x1000; sizeOfHeapReserve = 0x100000; sizeOfHeapCommit = 0x1000; loaderFlags = 0; //reserved, must be zero numberOfRvaAndSizes = 0x10; //"not fixed" but the PE format spec only defines 16 of these //data directory dExportTable = new DataDirectory(); dImportTable = new DataDirectory(); dResourceTable = new DataDirectory(); exceptionTable = new DataDirectory(); certificatesTable = new DataDirectory(); baseRelocationTable = new DataDirectory(); debugTable = new DataDirectory(); architecture = new DataDirectory(); globalPtr = new DataDirectory(); threadLocalStorageTable = new DataDirectory(); loadConfigurationTable = new DataDirectory(); boundImportTable = new DataDirectory(); importAddressTable = new DataDirectory(); delayImportDescriptor = new DataDirectory(); CLRRuntimeHeader = new DataDirectory(); reserved = new DataDirectory(); sections = new List <CoffSection>(); //standard sections importSec = null; importList = new List <CoffImportEntry>(); exportSec = null; exportList = new List <CoffExportEntry>(); resourceSec = null; resourceList = new List <ResourceData>(); relocSec = null; relocList = new List <CoffRelocationEntry>(); }
public static void loadSymbols(BinaryIn source, uint count, byte[] strtbl, Win32Obj objfile) { for (int i = 0; i < count;) { //get short name or pos in string tbl uint nameloc = source.getPos(); uint namezeros = source.getFour(); String name = ""; if (namezeros == 0) //if first 4 bytes = 0, 2nd 4 bytes = ofs into str tbl { int namepos = (int)source.getFour(); name = readString(strtbl, namepos); } else { source.seek(nameloc); name = source.getAsciiString(8); } //read rest of sym entry uint val = source.getFour(); uint secval = source.getTwo(); uint type = source.getTwo(); CoffStorageClass storage = (CoffStorageClass)source.getOne(); uint aux = source.getOne(); CoffSymbol sym = null; CoffSymbol.SYMBIND bind = CoffSymbol.SYMBIND.EXTERNAL; uint size = 0; uint addr = 0; CoffSection sec = null; switch (storage) { case CoffStorageClass.IMAGE_SYM_CLASS_EXTERNAL: if (secval == 0) { if (val == 0) { bind = CoffSymbol.SYMBIND.EXTERNAL; } else { bind = CoffSymbol.SYMBIND.COMMON; size = val; } } else { bind = CoffSymbol.SYMBIND.GLOBAL; sec = objfile.sections[(int)secval - 1]; if (val >= sec.memPos) { addr = val - sec.memPos; } } sym = new CoffSymbol(name); sym.bind = bind; sym.typ = CoffSymbol.SYMTYPE.FUNCTION; sym.section = sec; sym.ofs = addr; sym.size = size; break; case CoffStorageClass.IMAGE_SYM_CLASS_STATIC: case CoffStorageClass.IMAGE_SYM_CLASS_LABEL: if (secval != 0xffff) { sec = objfile.sections[(int)secval - 1]; if (val >= sec.memPos) { addr = val - sec.memPos; } sym = new CoffSymbol(name); sym.bind = CoffSymbol.SYMBIND.LOCAL; sym.typ = CoffSymbol.SYMTYPE.FUNCTION; sym.section = sec; sym.ofs = addr; sym.size = size; } break; case CoffStorageClass.IMAGE_SYM_CLASS_SECTION: sec = objfile.sections[(int)secval - 1]; sym = new CoffSymbol(name); sym.bind = CoffSymbol.SYMBIND.LOCAL; sym.typ = CoffSymbol.SYMTYPE.FUNCTION; sym.section = sec; sym.ofs = addr; sym.size = size; break; case CoffStorageClass.IMAGE_SYM_CLASS_FUNCTION: case CoffStorageClass.IMAGE_SYM_CLASS_FILE: break; default: break; } i++; objfile.symbols.Add(sym); if (sym != null) { objfile.symNames[sym.name] = sym; } //skip any aux sym entries for (int j = 0; j < aux; j++) { source.skip(CoffSymbol.SYMTBLENTRYSIZE); objfile.symbols.Add(null); i++; } } }
public static Win32Obj readFromFile(String filename) { Win32Obj objfile = new Win32Obj(filename); BinaryIn source = new BinaryIn(filename); //coff header objfile.machine = (MachineType)source.getTwo(); uint sectionCount = source.getTwo(); objfile.timeStamp = source.getFour(); uint symbolTblAddr = source.getFour(); uint symbolCount = source.getFour(); uint optionalHdrSize = source.getTwo(); objfile.characteristics = (int)source.getTwo(); //string tbl - follows symbol tbl uint strtblpos = symbolTblAddr + symbolCount * CoffSymbol.SYMTBLENTRYSIZE; source.seek(strtblpos); byte[] strtbl = null; uint len = source.getFour(); if (len > 4) { source.seek(strtblpos); strtbl = source.getRange(len); } //section tbl source.seek(COFFHDRSIZE); for (int i = 0; i < sectionCount; i++) { //if section name is stored in string tbl, we read in index & let caller deref the actual name String secname = source.getAsciiString(8); if (secname[0] == '/') { int stridx = Int32.Parse(secname.Substring(1)); secname = readString(strtbl, stridx); } //read section hdr field uint memSize = source.getFour(); //don't use - 0 in object files uint memPos = source.getFour(); uint fileSize = source.getFour(); uint filePos = source.getFour(); uint relocPos = source.getFour(); uint lineNumPos = source.getFour(); //don't use - deprecated uint relocCount = source.getTwo(); uint lineNumCount = source.getTwo(); //don't use uint flagval = source.getFour(); SectionSettings settings = SectionSettings.decodeFlags(flagval); CoffSection section = new CoffSection(secname, settings); section.owner = objfile; section.secNum = i + 1; section.memPos = memPos; section.fileSize = fileSize; section.filePos = filePos; section.relocTblPos = relocPos; section.relocTblCount = relocCount; objfile.sections.Add(section); objfile.secNames[section.name] = section; } //load symbols source.seek(symbolTblAddr); loadSymbols(source, symbolCount, strtbl, objfile); foreach (CoffSection section in objfile.sections) { //load section data section.data = new List <Byte>(source.getRange(section.filePos, section.fileSize)); //load sectionrelocs loadRelocations(source, section, objfile); } return(objfile); }