summaryrefslogtreecommitdiffstats
path: root/private/crt32/tools/i386mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/tools/i386mips.c')
-rw-r--r--private/crt32/tools/i386mips.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/private/crt32/tools/i386mips.c b/private/crt32/tools/i386mips.c
new file mode 100644
index 000000000..3ad3875d7
--- /dev/null
+++ b/private/crt32/tools/i386mips.c
@@ -0,0 +1,368 @@
+/*
+** I386MIPS - change the machine ID on a COFF object from I386 to R3000
+** Steve Salisbury, 03/24/1992
+*/
+
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <nt.h>
+
+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] <objectfile> ...\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 ;
+}