NT4/private/crt32/tools/i386mips.c
2020-09-30 17:12:29 +02:00

369 lines
8.4 KiB
C

/*
** 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 ;
}