FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

グローバル変数にアクセスしたときのアクセス情報をログに表示する

bfdのシンボルには、BSF_GLOBALとBSF_LOCALという、変数やセクション、各種定数を格納するためのセクションがある。 この中で、BSF_GLOBALはグローバル変数の情報が格納されており、取り扱うには一番簡単っぽいので試してみた。

関数のシンボルテーブルを作成したときと同じように、bfdからシンボル一覧をロードして、std::vectorに格納しておく。

void EnvBase::LoadGVariableTable (bfd *abfd)
{
    long      storage_needed;
    asymbol **symbol_table;
    long      number_of_symbols;

    storage_needed = bfd_get_symtab_upper_bound (abfd);
    if (storage_needed < 0) {
        std::cerr << "Error storage_needed < 0\n";
        exit (EXIT_FAILURE);
    }
    if (storage_needed == 0) {
        std::cerr << "Error storage_needed == 0\n";
        exit (EXIT_FAILURE);
    }

    symbol_table = (asymbol **) malloc (storage_needed);

    number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);

    if (number_of_symbols < 0) {
        std::cerr << "Error: number_of_symbols < 0\n";
        exit (EXIT_FAILURE);
    }
    for (int i = 0; i < number_of_symbols; i++) {

        //  fprintf (stdout, "SymbolName=%s : ", bfd_asymbol_name (symbol_table[i]));
        if ((symbol_table[i]->flags & BSF_FUNCTION) != 0x00) {
            // fprintf (stdout, "BSF_Function ");

        } else if ((symbol_table[i]->flags & BSF_LOCAL) != 0x00) {
            // fprintf (stdout, "BSF_Local %s %08x\n",

        } else if ((symbol_table[i]->flags & BSF_GLOBAL) != 0x00) {
            // fprintf (stdout, "BSF_Global %s %08x\n",
            //          bfd_asymbol_name(symbol_table[i]),
            //          bfd_asymbol_value (symbol_table[i]));
            FunctionInfo *p_gvar_info = new FunctionInfo ();
            p_gvar_info->symbol = bfd_asymbol_name(symbol_table[i]);
            p_gvar_info->addr   = bfd_asymbol_value (symbol_table[i]);
            // Insert new function table
            m_gvar_table->push_back (p_gvar_info);

        } else {
            // fprintf (stdout, "BSF_others ");
        }
    }

    DebugPrint ("<Finish loading global variable table>\n");
}

m_gvar_tableにグローバル変数とそのアドレス情報をペアで格納しておき、メモリアクセスが発生したときに探索する。

ロード命令の場合は以下だ。FindGVariable関数を実装しておき、ヒットすると、デバッグ情報を表示する。

/*!
 * Load Data from Memory
 */
MemResult EnvBase::LoadMemory (Addr_t addr, Size_t size, Word_t *data)
{
    MemResult res;

    switch (size) {
    case Size_Byte: {
        Byte_t byte;
        res = LoadMemByte  (addr, &byte);
        *data = static_cast<Word_t>(byte);
        m_trace->RecordTraceMemRead (addr, *data, size);
        break;
    }
    case Size_HWord: {
        HWord_t hword;
        res = LoadMemHWord (addr, &hword);
        *data = static_cast<Word_t>(hword);
        m_trace->RecordTraceMemRead (addr, *data, size);
        break;
    }
    case Size_Word:
        res = LoadMemWord (addr, data);
        m_trace->RecordTraceMemRead (addr, *data, size);
        break;
    default:
        fprintf (m_dbgfp, "<Internal Error: Illegal size of LoadMemory : %d>\n", size);
        exit (EXIT_FAILURE);
        break;
    }

    std::string gvar_symbol;
    if (IsDebugGVar () &&
        (FindGVariable (addr, &gvar_symbol) == true)) {
        DebugPrint ("<GlobalVar: %s=>%08x>\n", gvar_symbol.c_str(), *data);
    }

    return res;
}

これらを利用するためには、--debug_gvarオプションを利用するか、Luaインタフェースからは、debug("gvar")を追記しておくことで利用できる。 下記のように、関数のジャンプ情報と、グローバル変数のアクセス情報を表示できるようになった。

        78 : [800016c0] 00f50533 : add        r10,r10,r15          r10=>00000008 r15=>80002aa0 r10<=80002aa8
        79 : [800016c4] 00052783 : lw         r15,r10,0x000        r10=>80002aa8 (80002aa8)=>800016dc r15<=800016dc
        80 : [800016c8] 00078067 : jalr       r00,r15,r103         r15=>800016dc pc<=800016dc
<GlobalVar: seed2_volatile=>00000000>
        81 : [800016dc] 7e41a503 : lw         r10,r03,0x7e4        r03=>7f000010 (7f0007f4)=>00000000 r10<=00000000
        82 : [800016e0] 00008067 : jalr       r00,r01,r103         r01=>80002348 pc<=80002348
        83 : [80002348] 00a11723 : sh         r02,r10,0x00|r14     r02=>7f003f78 r10=>00000000 (7f003f86)<=00000000
        84 : [8000234c] 00300513 : addi       r10,r00,0x003        r00=>00000000 r10<=00000003
        85 : [80002350] b5cff0ef : jal        r01,0xb5cff          r01<=80002354 pc<=800016ac
<Func: get_seed_32>
        86 : [800016ac] 00500793 : addi       r15,r00,0x005        r00=>00000000 r15<=00000005
        87 : [800016b0] 04a7e263 : bltu       r15,r10,0x02         r15=>00000005 r10=>00000003
        88 : [800016b4] 800037b7 : lui        r15,0x80003          r15<=80003000
        89 : [800016b8] aa078793 : addi       r15,r15,0xaa0        r15=>80003000 r15<=80002aa0
        90 : [800016bc] 00251513 : slli       r10,r10,r02          r10=>00000003 r10<=0000000c
        91 : [800016c0] 00f50533 : add        r10,r10,r15          r10=>0000000c r15=>80002aa0 r10<=80002aac
        92 : [800016c4] 00052783 : lw         r15,r10,0x000        r10=>80002aac (80002aac)=>800016e4 r15<=800016e4
        93 : [800016c8] 00078067 : jalr       r00,r15,r103         r15=>800016e4 pc<=800016e4
<GlobalVar: seed3_volatile=>00000066>
        94 : [800016e4] 0041a503 : lw         r10,r03,0x004        r03=>7f000010 (7f000014)=>00000066 r10<=00000066
        95 : [800016e8] 00008067 : jalr       r00,r01,r103         r01=>80002354 pc<=80002354
        96 : [80002354] 00a11823 : sh         r02,r10,0x00|r16     r02=>7f003f78 r10=>00000066 (7f003f88)<=00000066
        97 : [80002358] 00400513 : addi       r10,r00,0x004        r00=>00000000 r10<=00000004
        98 : [8000235c] b50ff0ef : jal        r01,0xb50ff          r01<=80002360 pc<=800016ac
<Func: get_seed_32>
        99 : [800016ac] 00500793 : addi       r15,r00,0x005        r00=>00000000 r15<=00000005
       100 : [800016b0] 04a7e263 : bltu       r15,r10,0x02         r15=>00000005 r10=>00000004