/* ** I386MIPS - change the machine ID on a COFF object from I386 to R3000 ** Steve Salisbury, 03/24/1992 */ #include #include #include #include int main(int argc, char **argv); IMAGE_FILE_HEADER ifh ; IMAGE_SECTION_HEADER ish ; IMAGE_RELOCATION reloc ; const char * RelocName ( int reloctype ) ; int main(int argc, char **argv) { FILE *fileptr; char * name ; char * cp ; int errors = 0 ; int WriteFlag = 0 ; -- argc , ++ argv ; if ( setvbuf ( stderr , NULL , _IONBF , 0 ) ) { printf ( "setvbuf error\n" ) ; exit ( 1 ) ; } if ( argc == 0 || ( cp = * argv ) && * cp == '-' && ( * cp == 'h' || * cp == 'H' || * cp == '?' ) ) { fprintf ( stderr , "usage: i386mips [-w] ...\n" "each object file listed is converted from I386 to MIPS\n" "-w specifies that i386 objects should be changed to MIPS objects\n" "NOTE: This only works for files containing data but no code!\n" ); exit ( 1 ) ; } if ( argc > 1 && ! strcmp ( "-w" , * argv ) ) { -- argc , ++ argv ; WriteFlag = 1 ; } for ( ; * argv ; ) { char * name ; int sect ; name = * argv ++ ; ++ errors ; /* increment on principle */ if ( WriteFlag ) { if ( ( fileptr = fopen ( name , "r+b" ) ) == NULL ) { fprintf ( stderr , "i386mips: cannot open \"%s\" for modification\n" , name ) ; continue ; } } else { if ( ( fileptr = fopen ( name , "rb" ) ) == NULL ) { fprintf ( stderr , "i386mips: cannot open \"%s\" for reading\n" , name ) ; continue ; } } if ( 1 != fread ( & ifh , sizeof ( ifh ) , 1 , fileptr ) ) { fprintf ( stderr , "i386mips: cannot read first %d bytes from \"%s\"\n" , sizeof ( ifh ) , name ) ; fclose ( fileptr ) ; continue ; } printf ( "Machine ID = 0x%X (%s)\n" , ifh.Machine , ifh.Machine == IMAGE_FILE_MACHINE_I386 ? "i386" : ifh.Machine == IMAGE_FILE_MACHINE_R3000 ? "MIPS" : "?Unknown?" ) ; printf ( "%d Sections, TimeDate=%08lX, SizeOptHdr=%u, Flags=0x%X" , ifh.NumberOfSections, ifh.TimeDateStamp, ifh.SizeOfOptionalHeader , ifh.Characteristics); if ( ifh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED ) printf ( " NoRelocs" ) ; if ( ifh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE ) printf ( " EXECUTABLE" ) ; if ( ifh.Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED ) printf ( " NoLineNums" ) ; if ( ifh.Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED ) printf ( " NoLocalSyms" ) ; printf ( "\n" ) ; printf ( "\n" ) ; if ( WriteFlag ) { if ( ifh.Machine != IMAGE_FILE_MACHINE_I386 ) { if ( ifh.Machine == IMAGE_FILE_MACHINE_R3000 ) fprintf ( stderr , "i386mips: \"%s\" is already a MIPS COFF file (machine type = 0x%X)\n" , name , ifh.Machine ) ; else fprintf ( stderr , "i386mips: \"%s\" is not an i386 COFF file (machine type = 0x%X)\n" , name , ifh.Machine ) ; fclose ( fileptr ) ; continue ; } if ( fseek ( fileptr , 0L , SEEK_SET ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\"\n" , name ) ; fclose ( fileptr ) ; continue ; } ifh.Machine = IMAGE_FILE_MACHINE_R3000 ; if ( 1 != fwrite ( & ifh.Machine , sizeof ( ifh.Machine ) , 1 , fileptr ) ) { fprintf ( stderr , "i386mips: cannot re-write first %d bytes of \"%s\"\n" , sizeof ( ifh.Machine ) , name ) ; fclose ( fileptr ) ; continue ; } printf ( "Machine ID on \"%s\" changed from 0x%X (i386) to 0x%X (MIPS)\n" , name , IMAGE_FILE_MACHINE_I386 , IMAGE_FILE_MACHINE_R3000 ) ; if ( fseek ( fileptr , (long) sizeof ( ifh ) , SEEK_SET ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\" (@%ld)\n" , name , sizeof ( ifh ) ) ; fclose ( fileptr ) ; continue ; } } for ( sect = 1 ; sect <= ifh.NumberOfSections ; ++ sect ) { int s ; long savedpos ; if ( 1 != fread ( & ish , sizeof ( ish ) , 1 , fileptr ) ) { fprintf ( stderr , "i386mips: cannot read section header %d from \"%s\"\n" , sect , name ) ; fclose ( fileptr ) ; continue ; } printf ( "Section %d: \"%s\": VirtSize=0x%lX, VirtAdddr=0x%lX\n" , sect , ish.Name , ish.Misc.VirtualSize, ish.VirtualAddress); printf ( "PtrRawData=0x%lX, PtrRelocs=0x%lX, PtrLineNums=0x%lX\n" , ish.PointerToRawData, ish.PointerToRelocations, ish.PointerToLinenumbers ) ; printf ( "#Relocs=%u, #LineNums=%u, Flags=0x%lX" , ish.NumberOfRelocations, ish.NumberOfLinenumbers, ish.Characteristics); if ( ish.Characteristics & IMAGE_SCN_CNT_CODE ) printf ( " Text" ) ; if ( ish.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA ) printf ( " Data" ) ; if ( ish.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ) printf ( " BSS" ) ; printf ( "\n" ) ; printf ( "\n" ) ; savedpos = 0 ; if ( ish.PointerToRawData ) { int b ; savedpos = ftell ( fileptr ) ; if ( fseek ( fileptr , ish.PointerToRawData , SEEK_SET ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\" (Raw Data at 0x%lX)\n" , name , ish.PointerToRawData ) ; fclose ( fileptr ) ; continue ; } printf ( "Raw Data for Section %d: " , sect ) ; for ( b = 0 ; b < ish.Misc.VirtualSize ; ++ b ) printf ( " %02X" , getc ( fileptr ) ) ; printf ( "\n\n" ) ; } if ( ish.NumberOfRelocations ) { int r ; if ( ! savedpos ) savedpos = ftell ( fileptr ) ; if ( fseek ( fileptr , ish.PointerToRelocations , SEEK_SET ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\" (Relocs at 0x%lX)\n" , name , ish.PointerToRelocations ) ; fclose ( fileptr ) ; continue ; } for ( r = 1 ; r <= ish.NumberOfRelocations ; ++ r ) { if ( 1 != fread ( & reloc , sizeof ( reloc ) , 1 , fileptr ) ) { fprintf ( stderr , "i386mips: cannot read relocation %d in section %d from \"%s\"\n" , r , sect , name ) ; fclose ( fileptr ) ; continue ; } printf ( "Relocation %d: Addr=0x%lX, Symbol=%ld, Type=0x%X %s\n" , r , reloc.VirtualAddress , reloc.SymbolTableIndex , reloc.Type , RelocName ( reloc.Type ) ) ; if ( WriteFlag && reloc.Type == IMAGE_REL_I386_DIR32 ) { if ( fseek ( fileptr , ish.PointerToRelocations , SEEK_SET ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\" (Reloc %d in Section %d at 0x%lX)\n" , name , sect , r , ish.PointerToRelocations ) ; fclose ( fileptr ) ; continue ; } reloc.Type = IMAGE_REL_MIPS_REFWORD ; if ( 1 != fwrite ( & reloc , sizeof ( reloc ) , 1 , fileptr ) ) { fprintf ( stderr , "i386mips: cannot re-write relocation %d in section %d from \"%s\"\n" , r , sect , name ) ; fclose ( fileptr ) ; continue ; } if ( fseek ( fileptr , 0L , SEEK_CUR ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\" (after Reloc %d in Section %d at 0x%lX)\n" , name , sect , r , ish.PointerToRelocations ) ; fclose ( fileptr ) ; continue ; } printf ( "===> relocation changed to type %d (%s)\n" , reloc.Type , RelocName ( reloc.Type ) ) ; } } printf ( "\n" ) ; } printf ( "\n" ) ; if ( ! savedpos ) savedpos = ftell ( fileptr ) ; if ( savedpos && fseek ( fileptr , savedpos , SEEK_SET ) ) { fprintf ( stderr , "i386mips: fseek() error on \"%s\" (return to 0x%lX)\n" , name , savedpos ) ; fclose ( fileptr ) ; continue ; } } if ( fclose ( fileptr ) ) { fprintf ( stderr , "i386mips: fclose () error on \"%s\"\n" , name ) ; continue ; } -- errors ; /* undo increment on principle */ } return errors ; } const char * RelocName ( int reloctype ) { char * name ; switch ( reloctype ) { case 0 : name = "Absolute" ; break ; case 1 : name = "I386_DIR16 / MIPS_REFHALF" ; break ; case 2 : name = "I386_REL16 / MIPS_REFWORD" ; break ; case 3 : name = "MIPS_JMPADDR" ; break ; case 4 : name = "MIPS_REFHI" ; break ; case 5 : name = "MIPS_REFLO" ; break ; case 6 : name = "I386_DIR32 / MIPS_GPREL" ; break ; case 7 : name = "I386_DIR32NB / MIPS_LITERAL" ; break ; case 011 : name = "I386_SEG12" ; break ; case 024 : name = "I386_REL32" ; break ; case 042 : name = "MIPS_REFWORDNB" ; break ; case 045 : name = "MIPS_PAIR" ; break ; default : name = "*** ??? ***" ; } return name ; }