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 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); }