diff options
Diffstat (limited to 'fixgnuasobj.icl')
-rw-r--r-- | fixgnuasobj.icl | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/fixgnuasobj.icl b/fixgnuasobj.icl new file mode 100644 index 0000000..fc3a9ff --- /dev/null +++ b/fixgnuasobj.icl @@ -0,0 +1,153 @@ +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; |