Recent Entries
Archives
Search


Links
Powered by
Movable Type 2.64

2008年04月11日

OpenCOBOLと変数の初期化

OpenCOBOLというとORCA関連の人には有名ですが、一般的には情報は少ないですね(;´Д`)
そもそもどの程度互換性があるかとかこれから踏み込んでみようとする人たちにとっての情報は少ないんじゃないかと思います。いまでもSCREENセクションは?とかFAQにも関わらずあちこちで見かけます(;´Д`)。
# SCREENセクションはまだOpenCOBOLでは実装されていません試してないけどOpenCOBOL 1.0以降にはコードあるから幾らか動作するかも(未確認:20080619)

で、汎用機で使われているところのJCL、メーカーのCOBOLの組み合わせを無謀?にもOpenCOBOLと何か へ持っていく際にどんな地雷があるのか?これもまあ情報は全然ないと思います。ないので踏んで回るしかないのですが、いつものごとく地雷の上を飛び石状態の今日この頃(;´Д`)踏みまくってます。


INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN1-F ASSIGN AICC0160
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS LN010-FSTAT1
LN010-FSTAT2.

まあこんなコードがあって、JCLで外部からAICC0160へ値をASSIGNしてたとします。外部からASSIGN済みですから、このコードを含むCOBOLプログラム中ではAICC0160については何の初期化(後述)もしてないわけです。これをOpenCOBOLでそのままコンパイルして実行すると、長さ0のファイルをIN1-FとしてOpenしてエラーとなります。

そこでAICC0160へなんとかファイル名を引き渡したいのですが、なるべく元のCOBOLのコードは書き換えたくない・・・じゃあどうしよう?(;´Д`)?が今回のお題です。

OpenCOBOLは内部的には、一旦COBOLからC言語へ変換し、gccを使ってobjectを生成します。幸いこのC言語の状態も取り出すことができますので、部分的に切り出してみます。C言語のファイルは2本生成され:


/* PROGRAM-ID : AICM2666 */

static unsigned char b_1[4] __attribute__((aligned)); /* RETURN-CODE */
static unsigned char b_2[4] __attribute__((aligned)); /* SORT-RETURN */
static unsigned char b_3[4] __attribute__((aligned)); /* NUMBER-OF-CALL-PARAMETERS */
static unsigned char b_1466[1002] __attribute__((aligned)); /* AICC0160 */

(略)

static cob_field f_1466 = {1024, b_1466, &a_2}; /* AICC0160 */

(略)

上記のようなコードを含むヘッダファイルと本体のプログラムが生成されます。しかしながら、上記はヘッダファイル(*.h)ではありますが実は以下のようなコードから使用されているため、上記の定義はstaticなローカル変数として取り扱われてしまいます。


(略)
/* functions */

int
AICM2666 ()
{
return AICM2666_ (0);
}

/* end functions */

static int
AICM2666_ (const int entry)
{

#include "AICM2666.c.h" /* local variables */


(略)

ヤバい(;´Д`)関数の「中」でincludeしてるよ。
ローカル変数ですから、他のモジュールから変数領域を参照できないわけです。あわよくば変数領域を(横から)書き換えて対応しようと(いつのまにか)思っていたのにこれではかなり大変です。しかしながら、gccはstaticなローカル変数については律儀にもsymbolは定義してくれています。ただし、他の関数内のローカル変数名と衝突しないように、ポストフィックスを付けています( http://www.google.co.jp/search?hl=ja&q=gcc+variable+symbol+ASM_FORMAT_PRIVATE_NAME&btnG=Google+%E6%A4%9C%E7%B4%A2&lr= : gccの gcc/config/i386/i386.hで定義してある ASM_FORMAT_PRIVATE_NAME マクロにて生成。 f_1466 が f_1466.6233 のような名前になる)。そして、「今のところ」元の変数名がわかる程度の命名ルールでsymbolを作っているため、nmコマンド等で中身をのぞき見て元のsymbolを推測することができます。またこれらのsymbolはdlopen/dlsym等使用してアドレスを吸い上げることもできるのですローカル変数ではできないので別のルートから登坂中(;´Д`)。

とりあえず、Cで吐かせてそのコードを弄る(ヘッダ中で呼び出し1回目(変数アドレスの登録)、2回目(通常実行)するコードを追加)予定。

上記AICM2666を呼び出す

変数アドレスの登録

staticなローカル変数の領域を弄りまくる関数を呼ぶ

上記AICM2666を呼び出す

ヽ(´ー`)ノ

ヽ(´ー`)ノということで、ここから先は実装になるのですがとりあえず時間がないのでここまで。リクエストなどありましたら続き書きます。


しかし(;´Д`)・・・


cob_move (&cob_zero, &f_2641);
memset (b_2642, 48, 36);
memset (b_2649, 48, 3);
memset (b_2653, 32, 1024);
memset (b_2654, 32, 1024);
memset (b_2655, 32, 1024);
memset (b_2656, 32, 1024);
memset (b_2657, 32, 1024);
memset (b_2658, 32, 1024);
memset (b_2659, 32, 1024);

if (!h_IN1_F)

とか内部で独自に初期化しまくってますね。これだと外から変数の値書き換えても(;´Д`)元に戻ってしまいます。幸い、


/* initialize frame stack */
frame_index = 0;
frame_stack[0].perform_through = -1;

/* initialize number of call params */
(*(int *) (b_3)) = cob_call_params;
cob_save_call_params = cob_call_params;

goto l_2;

/* PROCEDURE DIVISION */

とか PROCEDURE DIVISIONの入口がわかるコメントはありますから、この直前あたりに変数の値差し替えるカラクリを忍び込ませればまだ手はあるかもしれません(;´Д`)オオゴトですが。

# ちなみにOpenCOBOLの処理系(cobc)に手を入れてもいいんですが、中はかなり複雑な作りになってますから手を出さないに越したことはないと思うわけです(;´Д`)はい。

Posted by minemaz at 2008年04月11日 15:20
トラックバック
このエントリーのトラックバックURL:
http://www.lancard.com/mt/mt-tb.cgi/435

Comments
Post a comment









Remember personal info?