コンパイルリスト(.lst)の読み方

コンパイルリストはコンパイラが生成するテキストファイルで、ソースに最も近い情報を含んでいます。残っている場合は最初に確認してください。

主要な情報は以下の通りです。

セクション内容分析への活用
展開済みソース COPY 文が展開された後の完全なソースコード コピーブックが失われていても内容を復元できる
シンボルクロスリファレンス 変数・段落名と定義行・参照行の対応表 データ名の再現・CALL 先の特定
エラー・警告メッセージ コンパイル時の問題箇所 ビルド条件の確認・問題点の把握
PROGRAM-ID と ENTRY 文一覧 モジュール内に定義されたプログラム名・エントリ名 モジュール境界の特定に直結する
Shell — コンパイルリストから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

リンカーマップからのエントリポイント特定

リンカーマップはリンク時に生成されるテキストで、各セクションのアドレスとシンボルの対応が記録されています。

Shell — リンカーマップからエントリポイント抽出(GnuCOBOL)
# 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 / 実行バイナリ)では以下のコマンドでシンボルを確認できます。

Shell — ELFシンボル抽出
# グローバルシンボル一覧(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 ユーティリティを使ってロードモジュールの内容を解析します。

JCL — 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 先のモジュール名を洗い出したら、依存関係グラフを作成します。グラフを見ることで分離の単位と順序が明確になります。

Shell — 複数リストファイルからCALL依存関係をCSV出力
#!/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 では、リストファイルだけでは情報が得られない場合に使う「ツールを使った構造解析」(静的解析・逆コンパイル・実行時トレース)を解説します。

→ PART 05 — ツールを使った構造解析へ