SSブログ

a.out → simh バイナリ変換ツール

PDP-11のgccクロスコンパイル環境を構築したのはいいが、ビルドされたa.outバイナリは
simhエミュでそのまま実行できなくて、simhのバイナリ形式に変換する必要がある。
(simhでUNIX V6を走らせたら別だと思うが、まだ試していない)

これまで下記ブログのbin2loadツールを使っていた。

上記ツールでは、出力するsimhバイナリのセクションとセクション間の開始アドレスを、0100バイトのアライメントでそろえている。これに合わせて、リンカースクリプト側の記述も同じアライメントにする必要がある。

a.outのバイナリ形式は単純で、ヘッダー情報のあとは単にtext領域、data領域、bss領域、、、と詰めて並んでいる。また、text領域のentry point以外は、それぞれの領域の開始アドレスの情報は持っていない。

一方で、data領域、bss領域に格納される変数のメモリ上のアドレスは、
リンカースクリプトで指定されたアドレス情報をベースを、リンカーが計算して決めている。

このアドレスはどこで効いてくるかというと、アセンブラ命令のメモリアクセスのアドレスとして効いてくる。(相対アドレスの場合はその相対値)

つまり、a.outに情報がないだけで、変数の格納アドレスはリンカースクリプトの情報を使っている。

なので、理想的なのは、bin2loadツールがリンカスクリプトを読んでアライメントの幅を決めてくれることだ。
でもまあ、そんな複雑なことをしなくても、要は用が足せればいいので、ツールはシンプルな方がいい。

件のbin2loadで十分な訳だが、勉強がてらRubyに書き直してみた。
いやあ、Ruby楽しす。

#!/usr/bin/ruby

(ARGV[0] && ARGV[1]) || abort("usage: ruby bin2load.rb <a.out> <outfile>")

class LdaFile < File
def write_dat(data)
cksum = 0
data.each do |d|
write [d].pack("C")
cksum += d
end
return cksum
end
def write_sec(saddr, data)
return if data == nil || data.size <= 0
write_sec_h saddr, data
end
def write_sec_h(saddr, data=[])
cksum = write_dat [1,0]
cksum += write_dat [data.size+6].pack("v").unpack("C*")
cksum += write_dat [saddr].pack("v").unpack("C*")
cksum += write_dat data if data.size > 0
cksum = -(cksum & 0xff)
write [cksum].pack("C")
end
end

fin = File.open(ARGV[0],"r")
fout = LdaFile.open(ARGV[1], "w")

magic, text_sz, data_sz, bss_sz, syms_sz, entry_adr, unused, flag =
fin.read(2*8).unpack("S*")

fout.write_sec entry_adr, fin.read(text_sz).unpack("C*")
fout.write_sec entry_adr+text_sz, fin.read(data_sz).unpack("C*")
fout.write_sec entry_adr+text_sz+data_sz, Array.new(bss_sz, 0)
fout.write_sec_h entry_adr

fin.close
fout.close

※上記はセクション間のアライメントは入れてない。


以上。




nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。