本シリーズのトップページ |
---|
https://qiita.com/robozushi10/items/fc185b5da0509b9a631f |
はじめに
本記事の趣旨は「01 概要」に記しているが、
13年前(=2008年) に職場のプログラムの挙動をマネて実装した
「コンソールから関数を呼び出す機構」の振り返りである.
本項では次の (3)(4) について記す.
(3)
*.o
に対してreadelf -s
を実行して公開関数名を抽出する
⬇️
(4) (3) で抽出した公開関数名をヘッダファイルに書き出す
⬇️
詳細
(3) について
下記については次の通りである.
(3)
*.o
に対してreadelf -s
を実行して公開関数名を抽出する
readelf -s
の実行は、mk_sym_tbl.rb で行っている.
わざわざ Ruby を採用した理由は、2008年 当時 Ruby が流行っていたので使ってみたということである.
(当時は職場のビルドシステムの補助ツールは、Perl から Ruby に置き換えられていた)
mk_sym_tbl.rb
#!/usr/bin/ruby
#------------------------------------------
# readelf -s *.o から関数シンボルを抜き出す
#------------------------------------------
def help
printf("%s [input_file]\n", $0)
end
Fn_tbl_file = "cfn.tbl.h"
Ext_dec_file = "cfn.extern.h"
# 引数チェック
if ARGV.length() != 1
help()
end
if File.exists?(Fn_tbl_file) == true then
File.unlink(Fn_tbl_file)
end
if File.exists?(Ext_dec_file) == true then
File.unlink(Ext_dec_file)
end
while filename = ARGV.shift
cmd = sprintf("| readelf -s %s", filename)
f = open(cmd)
while line = f.gets
if((line =~ /\sFUNC\s/) && (line =~ /\sGLOBAL\s/))
if(line =~ /\s*(\w*):(\w*)\s*(\w*)\s(\w*)\s*(\w*)\s*(\w*)\s*(\w*)\s*(\w*)\s*(\w*)\s*(\w*)/)
if($10 != "main")
buf = sprintf("{\"%s\", &%s},\n", $10, $10)
buf2 = sprintf("extern %s;\n", $10)
File.open(Fn_tbl_file, 'a+').write(buf)
File.open(Ext_dec_file, 'a+').write(buf2)
end
end
end
end
end
(4) について
下記については次の通りである.
(4) (3) で抽出した公開関数名をヘッダファイルに書き出す
上記 (3) の mk_sym_tbl.rb を次のように実行する
$ ./mk_sym_tbl.rb test_driver.o
すると、次の 2つのヘッダファイルが生成される
|-- cfn.extern.h .. 上記 mk_sym_tbl.rb から生成された関数の extern宣言.
| コンパイル&リンクエラー回避のために用いる.
`-- cfn.tbl.h .... 上記 mk_sym_tbl.rb から生成された関数名と関数アドレスを定義したヘッダ.