Bfd, Luaといろいろ道具は揃ってきたので、いろんな便利機能を実装してみよう。
まずは、関数の先頭にジャンプしたときに、その関数名を表示するように変更する。 この機能は、Lua側からだと、debug("func")を追加するか、 引数だと、--debug_func で有効にできる。
./swimmer_riscv --max 1000000 --out debug.log --binfile ~/benchmarks/coremark_v1.0/coremark.bin --script init.lua --debug_func ... 31 : [0000017c] 00000f33 : add r30,r00,r00 r00=>00000000 r00=>00000000 r30<=00000000 32 : [00000180] 00000fb3 : add r31,r00,r00 r00=>00000000 r00=>00000000 r31<=00000000 33 : [00000184] 80002417 : auipc r08,0x80002 r08<=80002184 34 : [00000188] 16440413 : addi r08,r08,0x164 r08=>80002184 r08<=800022e8 35 : [0000018c] 000400e7 : jalr r01,r08,r231 r08=>800022e8 r01<=00000190 pc<=800022e8 <Func: main> 36 : [800022e8] f7010113 : addi r02,r02,0xf70 r02=>7f004008 r02<=7f003f78 37 : [800022ec] 00810613 : addi r12,r02,0x008 r02=>7f003f78 r12<=7f003f80 38 : [800022f0] 00410593 : addi r11,r02,0x004 r02=>7f003f78 r11<=7f003f7c 39 : [800022f4] 04e10513 : addi r10,r02,0x04e r02=>7f003f78 r10<=7f003fc6 40 : [800022f8] 08112623 : sw r02,r01,0x04|r12 r02=>7f003f78 r01=>00000190 (7f004004)<=00000190 41 : [800022fc] 08812423 : sw r02,r08,0x04|r08 r02=>7f003f78 r08=>800022e8 (7f004000)<=800022e8 42 : [80002300] 08912223 : sw r02,r09,0x04|r04 r02=>7f003f78 r09=>00000000 (7f003ffc)<=00000000 43 : [80002304] 09212023 : sw r02,r18,0x04|r00 r02=>7f003f78 r18=>00000000 (7f003ff8)<=00000000 44 : [80002308] 07312e23 : sw r02,r19,0x03|r28 r02=>7f003f78 r19=>00000000 (7f003ff4)<=00000000 45 : [8000230c] 07412c23 : sw r02,r20,0x03|r24 r02=>7f003f78 r20=>00000000 (7f003ff0)<=00000000 46 : [80002310] 07512a23 : sw r02,r21,0x03|r20 r02=>7f003f78 r21=>00000000 (7f003fec)<=00000000 ...
こんな感じで、関数の先頭にジャンプしたときに、関数の名前を表示するようにする。
これを実装するために、Bfdでバイナリをロードするときに、関数のシンボル名とアドレスのペアをベクタとして格納しておいた。
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 "); FunctionInfo *p_func_info = new FunctionInfo (); p_func_info->symbol = bfd_asymbol_name(symbol_table[i]); p_func_info->addr = bfd_asymbol_value (symbol_table[i]); // Insert new function table m_func_table->push_back (p_func_info); ...
こんな感じで、bfdから情報を取り出して、envのメンバ変数であるm_func_table(関数名とアドレスのペアがベクタになって格納されている)に格納しておき、フェッチする度にサーチする、という形式にした。
fetch_res = FetchMemory (fetch_pc, &inst_hex); if (fetch_res == -1) { GenerateException (Except_InstAddrMisalign); return; } std::string func_symbol; if ((IsDebugFunc () == true) && (FindSymbol (fetch_pc, &func_symbol) == true)) { DebugPrint ("<Func: %s>\n", func_symbol.c_str()); }
FindSymbolで関数名にヒットすれば、そこで情報を表示する。
bool EnvBase::FindSymbol (Addr_t addr, std::string *symbol) { FunctionTable::iterator it = m_func_table->begin (); while (it != m_func_table->end ()) { Addr_t symbol_addr = (*it)->addr; if (symbol_addr == addr) { *symbol = (*it)->symbol; return true; } it++; } return false; }