module fixgnuasobj; import StdInt,StdChar,StdString,StdBool,StdFile,StdArray,StdMisc,StdClass; import ArgEnv; /* swap_bytes i = ((i>>24) bitand 0xff) bitor ((i>>8) bitand 0xff00) bitor ((i<<8) bitand 0xff0000) bitor (i<<24); Freadi :: !*File -> (!Bool,!Int,!*File); Freadi f0 = (b,swap_bytes i,f1); { (b,i,f1)=freadi f0; } Fwritei i f :== fwritei (swap_bytes i) f; */ Freadi f:==freadi f; Fwritei i f:==fwritei i f; read_little_endian_word_at offset f0 | ok1 && ok2 = (i,f2); {}{ (ok2,i,f2)=Freadi f1; (ok1,f1)=fseek f0 offset FSeekSet; } copy_to_offset current_offset offset i0 o0 | offset>=current_offset = (offset,i1,o1); {}{ (i1,o1)=copy_bytes (offset-current_offset) i0 o0; } copy_bytes n_bytes i0 o0 | size bytes==n_bytes = (i1,fwrites bytes o0); {}{ (bytes,i1)=freads i0 n_bytes; } replace_long offset v i0 o0 | ok = (offset+4,i1,Fwritei v o0); {}{ (ok,_,i1)=freadi i0; } copy_and_fix_data_relocations 0 data_addr offset i0 o0 = (offset,i0,o0); copy_and_fix_data_relocations n data_addr offset i0 o0 | ok1 && size bytes==6 = copy_and_fix_data_relocations (n-1) data_addr (offset+10) i2 o1; {}{ o1=fwrites bytes (Fwritei new_relocation_offset o0); new_relocation_offset=relocation_offset-data_addr; (bytes,i2)=freads i1 6; (ok1,relocation_offset,i1)=Freadi i0; } (BYTE) string i :== toInt (string.[i]); (IWORD) string i = (string BYTE (i+1)<<8) bitor (string BYTE i); (ILONG) string i = (string BYTE (i+3)<<24) bitor (string BYTE (i+2)<<16) bitor (string BYTE (i+1)<<8) bitor (string BYTE i); copy_and_fix_symbols 0 data_addr offset0 i0 o0 = (offset0,i0,o0); copy_and_fix_symbols n data_addr offset0 i0 o0 | size bytes<>18 = abort "copy_and_fix_symbols: read error\n"; | section_n<>2 = copy_and_fix_symbols (n-1-n_aux) data_addr offset1 i2 o2; { (offset1,i2,o2)=copy_aux n_aux (offset0+18) i1 o1; o1=fwrites bytes o0; } = copy_and_fix_symbols (n-1-n_aux) data_addr offset1 i2 o4; { (offset1,i2,o4)=copy_aux n_aux (offset0+18) i1 o3; o3=fwrites (bytes % (12,17)) o2; o2=Fwritei (value-data_addr) o1; o1=fwrites (bytes % (0,7)) o0; value=bytes ILONG 8; } { (bytes,i1)=freads i0 18; n_aux=bytes BYTE 17; section_n=bytes IWORD 12; } copy_aux 0 offset i0 o0 = (offset,i0,o0); copy_aux n offset i0 o0 | size bytes==aux_size = (offset+aux_size,i1,o1); {}{ o1=fwrites bytes o0; (bytes,i1)=freads i0 aux_size; aux_size=n*18; } copy_rest_of_file i0 o0 | size bytes<16384 = (i1,fwrites bytes o0); = copy_rest_of_file i1 (fwrites bytes o0); {}{ (bytes,i1)=freads i0 16384; } //input_file_name:=="_startup1.o"; //output_file_name:=="_startup1.obj"; Start w0 # command_line=getCommandLine; | size command_line<>3 = abort "input file name and output file name expected"; # input_file_name = command_line.[1]; output_file_name = command_line.[2]; files0=w0; (open_ok1,f0,files1)=fopen input_file_name FReadData files0; (symbol_table_offset,f1)=read_little_endian_word_at 0x8 f0; (n_symbols,f2)=read_little_endian_word_at 0xc f1; (data_addr,f3)=read_little_endian_word_at 0x44 f2; (data_addr_,f4)=read_little_endian_word_at 0x48 f3; (data_relocation_table_offset,f5)=read_little_endian_word_at 0x54 f4; (n_relocations,f6)=read_little_endian_word_at 0x5c f5; (seek_ok,i0) = fseek f6 0 FSeekSet; (open_ok2,o0,files2)=fopen output_file_name FWriteData files1; (new_offset0,i1,o1)=copy_to_offset 0 0x44 i0 o0; (new_offset1,i2,o2)=replace_long new_offset0 0 i1 o1; (new_offset2,i3,o3)=replace_long new_offset1 0 i2 o2; (new_offset4,i5,o5) = f; with { f | n_relocations==0 = (new_offset2,i3,o3); = copy_and_fix_data_relocations n_relocations data_addr new_offset3 i4 o4; { (new_offset3,i4,o4)=copy_to_offset new_offset2 data_relocation_table_offset i3 o3; } } (new_offset5,i6,o6)=copy_to_offset new_offset4 symbol_table_offset i5 o5; (new_offset6,i7,o7)=copy_and_fix_symbols n_symbols data_addr new_offset5 i6 o6; (i8,o8)=copy_rest_of_file i7 o7; (close_ok1,files4)=fclose o8 files2; | open_ok1 && data_addr==data_addr_ && seek_ok && open_ok2 && close_ok1 = (symbol_table_offset,n_symbols,data_addr,data_relocation_table_offset,n_relocations,files4); // # (stdout,files) = stdio files4; // = stdout <<< symbol_table_offset <<< ' ' <<< n_symbols <<< ' ' <<< data_addr <<< ' ' <<< data_relocation_table_offset <<< ' ' <<< n_relocations;