コンパイルリスト(.lst)の読み方
コンパイルリストはコンパイラが生成するテキストファイルで、ソースに最も近い情報を含んでいます。残っている場合は最初に確認してください。
主要な情報は以下の通りです。
| セクション | 内容 | 分析への活用 |
|---|---|---|
| 展開済みソース | COPY 文が展開された後の完全なソースコード | コピーブックが失われていても内容を復元できる |
| シンボルクロスリファレンス | 変数・段落名と定義行・参照行の対応表 | データ名の再現・CALL 先の特定 |
| エラー・警告メッセージ | コンパイル時の問題箇所 | ビルド条件の確認・問題点の把握 |
| PROGRAM-ID と ENTRY 文一覧 | モジュール内に定義されたプログラム名・エントリ名 | モジュール境界の特定に直結する |
# PROGRAM-ID の一覧
grep -i "PROGRAM-ID" module.lst
# ENTRY 文の一覧
grep -i "^\s*ENTRY\b" module.lst
# CALL 文の一覧(静的 CALL)
grep -iE "^\s*CALL\s+'[A-Z0-9-]+'" module.lst
# CALL 文の一覧(動的 CALL、変数呼び出し)
grep -iE "^\s*CALL\s+[A-Z][A-Z0-9-]*\b" module.lst
リンカーマップからのエントリポイント特定
リンカーマップはリンク時に生成されるテキストで、各セクションのアドレスとシンボルの対応が記録されています。
# GnuCOBOL でリンカーマップを生成してコンパイル
cobc -x -Wl,-Map=output.map main.cbl
# エントリポイントシンボルを抽出(COBOL プログラム名は先頭が数字になることがある)
grep -E "^\s+0x[0-9a-f]+" output.map | grep -i "cob_"
# エントリポイントに絞り込む(GLOBAL シンボル)
nm -g --defined-only output.so | grep " T "
シンボル情報の抽出コマンド(GnuCOBOL/Linux)
ELF 形式のロードモジュール(.so / 実行バイナリ)では以下のコマンドでシンボルを確認できます。
# グローバルシンボル一覧(T=テキストセクション関数)
nm -g --defined-only libmodule.so
# 全シンボル(未定義含む)
nm -a libmodule.so
# セクション情報とシンボルサイズ
objdump -t libmodule.so | grep -v "^0\{16\}"
# 文字列の検索(コンパイラ情報・PROGRAM-ID 残存確認)
strings libmodule.so | grep -i "cobol\|gnucobol\|program\|version"
# 依存ライブラリの確認
readelf -d libmodule.so | grep NEEDED
💡 COBOL シンボル名の変換規則
GnuCOBOL では PROGRAM-ID. MYPROG のシンボル名は C 側で myprog_ のように変換されます(ハイフン→アンダースコア、末尾アンダースコア付与)。nm の出力からプログラム名を逆引きする際はこの変換を念頭に置いてください。
メインフレーム(z/OS)の場合 — AMBLIST
z/OS では AMBLIST ユーティリティを使ってロードモジュールの内容を解析します。
//AMBLIST JOB CLASS=A,MSGCLASS=X
//STEP1 EXEC PGM=AMBLIST
//SYSPRINT DD SYSOUT=*
//SYSLIB DD DSN=YOUR.LOADLIB,DISP=SHR
//SYSIN DD *
LISTLOAD OUTPUT=XREF,MEMBER=YOURMOD
/*
AMBLIST の出力には以下の情報が含まれます。
| 出力セクション | 内容 |
|---|---|
| MODULE SUMMARY | モジュール名・サイズ・エントリポイントのアドレス |
| CSECT SUMMARY | 各制御セクション(CSECT)の名前・長さ・配置アドレス |
| EXTERNAL SYMBOL DICTIONARY (ESD) | 公開シンボル・ENTRY 名の一覧 |
| CROSS REFERENCE | シンボルの参照・定義関係 |
CALL 文の洗い出しと依存関係グラフの作成
CALL 先のモジュール名を洗い出したら、依存関係グラフを作成します。グラフを見ることで分離の単位と順序が明確になります。
#!/bin/bash
# 各 .lst ファイルから PROGRAM-ID → CALL 先の関係を抽出してCSV出力
echo "caller,callee"
for lst in *.lst; do
# PROGRAM-ID を取得
caller=$(grep -i "PROGRAM-ID" "$lst" | head -1 | grep -oiE "[A-Z0-9-]{2,30}" | tail -1)
# 静的 CALL の CALLEE を取得
grep -iE "CALL\s+'([A-Z0-9-]+)'" "$lst" \
| grep -oiE "'[A-Z0-9-]+'" \
| tr -d "'" \
| sort -u \
| while read callee; do
echo "$caller,$callee"
done
done
✅ 次の章では…
PART 05 では、リストファイルだけでは情報が得られない場合に使う「ツールを使った構造解析」(静的解析・逆コンパイル・実行時トレース)を解説します。