//-------------------------------------------------------------------------- static ea_t get_segea(const GEOSappheader &ah, const ulong *segea, ushort s) { if ( s >= ah.numseg ) { ask_for_feedback("Bad segment number %d", s); return BADADDR; } return segea[s] == ulong(BADADDR) ? BADADDR : segea[s]; }
//------------------------------------------------------------------------ inline bool pe64_to_pe(peheader_t &pe, const peheader64_t &pe64, bool silent) { bool ok = true; switch ( pe64.magic ) { default: if ( !silent ) { ask_for_feedback("The input file has non-standard magic number (%x)", pe64.magic); } ok = false; /* no break */ case MAGIC_P32: case MAGIC_ROM: memcpy(&pe, &pe64, sizeof(pe)); break; case MAGIC_P32_PLUS: memcpy(&pe, &pe64, offsetof(peheader_t, stackres)); memcpy(&pe.loaderflags, &pe64.loaderflags, sizeof(pe) - qoffsetof(peheader_t, loaderflags)); pe.stackres = low(pe64.stackres); pe.stackcom = low(pe64.stackcom); pe.heapres = low(pe64.heapres); pe.heapcom = low(pe64.heapcom); break; } // do various checks if ( !pe.is_efi() && (pe.objalign < pe.filealign || pe.filealign !=0 && (pe.filealign & (pe.filealign-1) ) != 0 // check for power of 2 || pe.objalign !=0 && (pe.objalign & (pe.objalign -1) ) != 0) ) // check for power of 2 { if ( !silent ) pe_failure("Invalid file: bad alignment value specified (section alignment: %08X, file alignment: %08X)", pe.objalign, pe.filealign); } if ( pe.imagesize > 0x77000000 || pe.imagesize < pe.allhdrsize ) { if ( !silent ) pe_failure("Invalid file: bad ImageSize value %x", pe.imagesize); } if ( pe.nrvas && pe.nrvas < total_rvatab_count ) memset(&pe.expdir+pe.nrvas, 0, total_rvatab_size-pe.nrvas*sizeof(petab_t)); return ok; }
//----------------------------------------------------------------------- static void read_fixup(linput_t *li) { fixup fix; const int size = offsetof(fixup, fixups); lread(li, &fix, size); uint32 fptr = qltell(li); ea_t sea = getsea(fix.where_IN); if ( sea != BADADDR ) { uchar *b = qnewarray(uchar, fix.length); if ( b == NULL ) nomem("read_fixup"); lread(li, b, fix.length); // show_hex(b, fix.length, "\nFIXUP SEG %04X, %04X BYTES, KIND %02X\n", // fix.where_IN, // fix.length, // b[0]); const uchar *ptr = b; const uchar *end = b + fix.length; while ( ptr < end ) { fixup_data_t fd; uint32 where_offset = 0; uint32 what_offset = 0; ushort what_in = 9; bool selfrel = false; bool isfar = false; fd.type = FIXUP_OFF32; switch ( *ptr++ ) { case 0x2C: // GEN isfar = true; ask_for_feedback("Untested relocation type"); case 0x24: // GEN where_offset = readdw(ptr, false); what_offset = readdw(ptr, false); what_in = (ushort)readdw(ptr, false); break; case 0x2D: isfar = true; case 0x25: // INTRA where_offset = readdw(ptr, false); what_offset = readdw(ptr, false); what_in = fix.where_IN; break; case 0x2A: // CALL where_offset = readdw(ptr, false); what_offset = 0; what_in = (ushort)readdw(ptr, false); selfrel = true; break; case 0x2E: // OFF32? isfar = true; case 0x26: where_offset = readdw(ptr, false); what_offset = 0; what_in = (ushort)readdw(ptr, false); break; default: ask_for_feedback("Unknown relocation type %02X", ptr[-1]); add_pgm_cmt("!!! Unknown relocation type %02X", ptr[-1]); break; } ea_t source = sea + where_offset; ea_t target = BADADDR; switch ( what_in >> 12 ) { case 0x02: // segments target = getsea(what_in); break; case 0x06: // externs target = xea + 4 * ((what_in & 0xFFF) - 1); fd.type |= FIXUP_EXTDEF; break; default: ask_for_feedback("Unknown relocation target %04X", what_in); add_pgm_cmt("!!! Unknown relocation target %04X", what_in); break; } segment_t *ts = getseg(target); fd.sel = ts ? (ushort)ts->sel : 0; if ( (fd.type & FIXUP_EXTDEF) == 0 ) { target += what_offset; what_offset = 0; } fd.off = target; fd.displacement = what_offset; target += what_offset; if ( selfrel ) { fd.type |= FIXUP_SELFREL; target -= source + 4; } set_fixup(source, &fd); put_long(source, target); if ( isfar ) { fd.type = FIXUP_SEG16; set_fixup(source+4, &fd); put_word(source+4, fd.sel); } } qfree(b); }