ð TOP / èªè§£æŒç¿ Step 9
ã³ãŒãèªè§£æŒç¿ Step 9ããã³ãéèãïŒã¯ã©ãã·ã¥ãã³ããšéã¢ã»ã³ãã©èªè§£ïŒMiniDumpè§£æïŒ
æé©åãã«ãïŒ-O2ïŒã§çãè¡çªå·ãçªç ŽïŒMiniDump ãš CPUã¬ãžã¹ã¿ïŒRAX/RSPïŒããã¯ã©ãã·ã¥çŸå Žãç¹å®ããæè¡
ãéçºç°å¢ïŒDebugãã«ãïŒã§ã¯çµ¶å¯Ÿã«åçŸããªãã®ã«ããªãªãŒã¹çã§ã客ããã®PCã§ã®ã¿ã¯ã©ãã·ã¥ãããããããã¬ãã¢ã¿ããããç¬éãã¿ã€ãã³ã°ãå€ãã£ãŠãã°ãæ¶ããïŒãã€ãŒã³ãã°ïŒãââããã®éçºçŸå Žã§æãé£åºŠã®é«ããã©ãã«ãæ¬çªã¯ã©ãã·ã¥ã§ããæ¬ç« ã§ã¯ãWindows MiniDump ã Linux Core Dump ãçšããŠã¯ã©ãã·ã¥ç¬éã®CPUã¬ãžã¹ã¿ãšã¡ã¢ãªç¶æ
ã埩å
ããæé©åïŒ-O2 / -O3ïŒã«ãã£ãŠã€ã³ã©ã€ã³åã»äžŠã¹æ¿ããããã¢ã»ã³ããªåœä»€ã®éåŒãããçã®ã¯ã©ãã·ã¥åå ãç¹å®ããçŸå ŽéèçŒãäœåŸããŸãã
9.1 ãæå
ã§åçŸããªãïŒãæ¬çªã¯ã©ãã·ã¥ãæããã MiniDump ãš PDB
ã¯ã©ãã·ã¥ããç¬éã®ããã»ã¹ãåçµä¿åãããã³ããã¡ã€ã«ãéçºè
ã®æå
ãžäºæ
çŸå Žãå®å
šèŒžéããä»çµã¿ã
ð§ ãã³ã®ã³å
茩
ã·ãã¯ãå
çïŒãªãªãŒã¹ããã²ãŒã ããã¬ã€ããŠãããŠãŒã¶ãŒããããã3æéãããéãã§ãããçªç¶ç»é¢ãæ¶ããŠãã¹ã¯ãããã«æ»ã£ãããšåãåãããæ¥ãŸããïŒç§ã®éçºPCã§åãæäœãããŠãå
šãèœã¡ãªããã§ãâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ãµãã£ãµãã£ãµãïŒãããããã€ãŒã³ãã°ïŒèгå¯ããããšãããšæ¶ãããã°ïŒãã®å
žåäŸãããªïŒReleaseãã«ãã¯æé©åãå¹ããŠããããã¡ã¢ãªé
眮ãDebugçãšã¯å
šãç°ãªããæå
ã®åã§çŽãããšããã®ã¯æéã§éãæ¢ããããªãã®ããïŒ
ð§ ãã³ã®ã³å
茩
ãããããŠãŒã¶ãŒããã®PCã§äœãèµ·ããŠããã®ããã©ããã£ãŠèª¿ã¹ãã°ãããã§ããïŒ
ð»ââïž ã·ãã¯ãå
ç
ããã§æŽ»èºããã®ããã¯ã©ãã·ã¥ãã³ãïŒMiniDumpïŒ.dmpïŒããšããããã°ã·ã³ãã«ïŒPDBïŒãããïŒOSãã¯ã©ãã·ã¥ããç¬éã®CPUã¬ãžã¹ã¿ãã¹ã¿ãã¯ã¡ã¢ãªãã¹ã¬ããç¶æ
ããã¡ã€ã«ã«æžãåºããŠéã£ãŠãããã®ãããïŒ
### MiniDump ãš PDB ã·ã³ãã«ã®é¢ä¿ æ¬çªç°å¢ã®å®è¡å¯èœãã¡ã€ã«ïŒ.exe / .dllïŒã«ã¯ãå®è¡é床ãšãã¡ã€ã«ãµã€ãºåæžã®ããã颿°åããœãŒã¹ã³ãŒãã®è¡çªå·æ
å ±ãå«ãŸããŠããŸããã 1. **ã¯ã©ãã·ã¥ãã³ã (.dmp)**: - ã¯ã©ãã·ã¥ç¬éã®ãCPUã¬ãžã¹ã¿å€ïŒRAX, RSP, RIPçïŒããšãã¹ã¿ãã¯ã¡ã¢ãªã®çãã€ããªããèšé²ããã¹ãããã·ã§ããã 2. **ãããã°ã·ã³ãã« (.pdb / DWARF)**: - ãã«ãæã«çæããããæ©æ¢°èªã¢ãã¬ã¹ïŒäŸ: 0x00401A20ïŒãšãœãŒã¹ã³ãŒãïŒäŸ: Player.cpp ã® 142è¡ç®ïŒãã®å¯Ÿå¿èŸæžã ãã®2ã€ãéçºè
ã®PCäžã§åäœãããããšã§ã**ããŠãŒã¶ãŒã®PCã§ã¯ã©ãã·ã¥ããç¬éã®ã³ãŒã«ã¹ã¿ãã¯ã**ãæ°åããé¢ããæå
ã®IDEäžã§é®®ããã«åçŸãããŸãã **â ïž ããã®éå**: ãªãªãŒã¹ãã«ããè¡ãéãçæãããã.pdbããã¡ã€ã«ã¯çµ¶å¯Ÿã«ç Žæ£ãããããŒãžã§ã³ããšã«ç€Ÿå
ã·ã³ãã«ãµãŒããŒçãžæ°žä¹
ä¿ç®¡ããªããã°ãªããŸãããPDBã1æåã§ããã«ãæãšãºã¬ããšããã³ãã®è¡çªå·ã¯äºåºŠãšåŸ©å
ã§ããªããªããŸãã
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
MiniDump ïŒ PDB ïŒ äºæ
çŸå Žã®ã¿ã€ã ãã©ãã« : ãŠãŒã¶ãŒç°å¢ã®ã¯ã©ãã·ã¥ã¯ãçãã³ããšå¯Ÿå¿ããããŒãžã§ã³ã®PDBã·ã³ãã«ãçªãåãããããšã§åããŠè§£æå¯èœã«ãªããŸãã
9.2 æé©åïŒ-O2ïŒã®çœ ïŒæ¶ããã³ãŒã«ã¹ã¿ãã¯ãšãºã¬ãè¡çªå·
ãªããªãªãŒã¹çã®ãããã°ã¯äžççžã§ãããªãã®ãïŒ ã³ã³ãã€ã©æé©åã®éè¡ãè§£ãæãããŸãã
ð§ ãã³ã®ã³å
茩
ãã³ããVisual Studioã§éããŠã¿ãŸããïŒã³ãŒã«ã¹ã¿ãã¯ã衚瀺ããããã§ããâŠèœã¡ãè¡çªå·ãšããŠè¡šç€ºãããŠããã®ã空è¡ãæ³¢æ¬åŒ§ã}ãã ã£ããã絶察ã«åŒãã§ããã¯ãã® getEnemy() 颿°ãã¹ã¿ãã¯ã«ååšããªããã§ãâŠãããã¬ãå£ããŠãããã§ããããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãããã¬ã¯æ£åžžããïŒããããããã³ã³ãã€ã©æé©åïŒOptimizationïŒãã®ä»æ¥ãªããããïŒ
### æé©åããããã3倧ãããã°é£é¢ C++ã³ã³ãã€ã©ïŒMSVC, GCC, ClangïŒã¯ãã-O2ããã/O2ããæå®ããããšã人éãæžããã³ãŒãã®æ§é ã倧å¹
ã«çµã¿æ¿ããŸãïŒ 1. **ã€ã³ã©ã€ã³å±éïŒInliningïŒ**: - å°ããªé¢æ°ã¯é¢æ°åŒã³åºãïŒCALLåœä»€ïŒãè¡ãããåŒã³åºãå
ã®ã³ãŒãã®äžã«çŽæ¥åã蟌ãŸããŸãããã®ãããã³ãŒã«ã¹ã¿ãã¯ãã颿°åã綺éºã«æ¶ãå»ããŸãã 2. **æ«å°ŸåŒã³åºãæé©åïŒTail Call Optimization: TCOïŒ**: - 颿°ã®æ«å°Ÿã§ã®ãªã¿ãŒã³åŒã³åºãã¯ãã¹ã¿ãã¯ãã¬ãŒã ãç Žæ£ããŠãžã£ã³ãïŒJMPïŒåœä»€ã«å€æããããããäžéã®ã¹ã¿ãã¯ãã¬ãŒã ãæ¶å€±ããŸãã 3. **åœä»€ã®äžŠã¹æ¿ãïŒInstruction ReorderingïŒ**: - CPUãã€ãã©ã€ã³ã®å¹çåã®ãããç¡é¢ä¿ãªæŒç®ã®é çªãååŸããŸããããã«ããããããã¬ã®çŸåšè¡ãã€ã©ã€ããšå®éã«å®è¡ãããŠããåœä»€ã«ãºã¬ãçããŸãã ãã®ããããªãªãŒã¹çã®çå ç©¶æã«ã¯**ããœãŒã¹ã³ãŒãã®è¡çªå·ãç²ä¿¡ããã®ã§ã¯ãªããéã¢ã»ã³ãã©ïŒAssemblyïŒãçŽæ¥éèããåã**ãå¿
é ãšãªããŸãã
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
æé©åãã«ãã§ã¯è¡çªå·ãçããã¢ã»ã³ããªåœä»€ãä¿¡ãã : ã€ã³ã©ã€ã³å±éãåœä»€äžŠã¹æ¿ãã«ããè¡çªå·è¡šç€ºããºã¬ããããã¯ã©ãã·ã¥ã¢ãã¬ã¹ã®çŽåã®æ©æ¢°èªåœä»€ã確èªããã®ã確å®ã§ãã
9.3 éã¢ã»ã³ãã©éèè¡ïŒã¬ãžã¹ã¿å€ããçç¯äººãéç®ãã
ã¯ã©ãã·ã¥çŸå Žã® x86-64 ã¢ã»ã³ããªåœä»€ãèªã¿è§£ããAccess Violation ã®çã®åŒãéãç¹å®ããŸãã
### å®äŸïŒã¢ã¯ã»ã¹éåïŒAccess Violation 0xC0000005ïŒã®çŸå Ž ãã³ããéããéãã¯ã©ãã·ã¥çŸå Žã®ã¢ã»ã³ããªåœä»€ã以äžã®ããã«ãªã£ãŠãããšããŸãïŒ ãåœä»€ã00007FF7B4201A34: mov rax, qword ptr [rcx+18h] <-- ããã§ã¢ã¯ã»ã¹éåïŒ ãåœä»€ã00007FF7B4201A38: mov edx, dword ptr [rax+8] ãåœä»€ã00007FF7B4201A3B: call Player::takeDamage åæã«ããããã¬ã®ã¬ãžã¹ã¿ãŠã£ã³ããŠã«ã¯ä»¥äžã®å€ãèšé²ãããŠããŸããïŒ - **RCX**: 0x0000000000000000 - **RDX**: 0x0000000000000014 - **RSP**: 0x00000058F31DF680 #### ãéèã®ã¹ãããã 1. **åé¡ã®åœä»€ãèªã**: - ãmov rax, qword ptr [rcx+18h]ãã¯ããRCX ã®æãã¢ãã¬ã¹ãã 0x18ïŒ24ãã€ãïŒé²ãã å Žæã«ãããã€ã³ã¿ã RAX ã«èªã¿èŸŒãããšããæå³ã§ãã 2. **ã¬ãžã¹ã¿ã確èªãã**: - ãªããš **RCX ã 0x0ïŒnullptrïŒ** ã§ãïŒ - ã€ãŸããã¢ãã¬ã¹ã0x0 + 0x18 = 0x0000000000000018ããšããç¡å¹ãªã¡ã¢ãªé åãèªã¿èŸŒãããšããŠãOSã«ãã£ãŠå³åº§ã«æå¢ãããããšãåãããŸãã 3. **C++ã®æèãžéç®ãã**: - x64ã®åŒåºèŠçŽïŒMicrosoft x64 ABIïŒã§ã¯ã**第1åŒæ°ïŒã¡ã³ã颿°ã«ããã this ãã€ã³ã¿ïŒã¯ RCX ã¬ãžã¹ã¿** ã«æ ŒçŽãããŸãã - ã€ãŸãã**ããã«ãã€ã³ã¿ïŒnullptrïŒã®ãªããžã§ã¯ãã«å¯ŸããŠã¡ã³ã颿°ãåŒã³åºãããããthis->member ã«ã¢ã¯ã»ã¹ããç¬éã«çæ»ããã** ãšããçå®ãäžç¬ã§æµ®ã圫ãã«ãªããŸãïŒ - **ð¡ çŸå Žã®è¶
éèŠç¥èïŒOSã«ããåŒåºèŠçŽã®å·®åïŒ**: Windowsç°å¢ïŒMicrosoft x64 ABIïŒã§ã¯åŒæ°ã¯ `RCX, RDX, R8, R9` ã®é ã«æž¡ãããŸãããLinux ã macOSïŒSystem V AMD64 ABIïŒã§ã¯ **`RDI, RSI, RDX, RCX, R8, R9`** ã®é ã§æž¡ãããŸãããã®ãããLinuxã²ãŒã ãµãŒããŒãçµèŸŒã¿Linuxç°å¢ã®ã³ã¢ãã³ãéèã§ã¯ã**ãRDI ã 0x0 (nullptr) ã«ãªã£ãŠããªããã** ãçã£å
ã«ç¢ºèªããã®ãããã®éåã§ãïŒ
ð CrashForensicsExample.cpp
struct Shield {
int defensePower; // offset: 0x8
};
struct Player {
Shield* pShield; // offset: 0x18 (24ãã€ãç®)
void takeDamage(int rawDmg) {
// ãã this (RCX) ã nullptr ã ã£ãå Žåã
// pShield (this + 0x18) ãåç
§ããããšããç¬éã«ã¯ã©ãã·ã¥ïŒ
int finalDmg = rawDmg - this->pShield->defensePower;
}
};
// éèã®çµæå€æãããã°ã®æž©åºïŒ
void onEnemyHit(Player* pTarget) {
// pTarget ã nullptr ãã©ããã®äºåãã§ãã¯ãæããŠããïŒ
// if (pTarget != nullptr) ãå¿
èŠïŒ
pTarget->takeDamage(20);
}
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
RCX + 0xXX ã®ã¢ã¯ã»ã¹éåã¯ãthis ã nullptrãã®ä»£åè© : x64ç°å¢ã§ãªãã»ããæ°åãã€ããžã®ã¢ã¯ã»ã¹éåãèµ·ããå Žåãã»ãŒäŸå€ãªã this ãã€ã³ã¿ïŒRCXïŒã nullptr ã®ãŸãŸã¡ã³ããè§Šã£ãããšãåå ã§ãã
ð ç解床ãã§ãã¯ã¯ã€ãº
Q1. ãŠãŒã¶ãŒç°å¢ã§ã¯ã©ãã·ã¥ããããã»ã¹ã® MiniDumpïŒ.dmpïŒãè§£æããéãéçºè
ã®æå
ã«çµ¶å¯Ÿã«å¿
èŠãšãªããã¡ã€ã«ã¯äœã§ããïŒ
1. ãŠãŒã¶ãŒã®Webãã©ãŠã¶ã®ãã£ãã·ã¥ 2. ãã«ãæã«ãã®å®è¡ãã¡ã€ã«ïŒ.exeïŒãšåæã«çæããããããã°ã·ã³ãã«ãã¡ã€ã«ïŒ.pdbïŒ 3. PCã®ã°ã©ãã£ãã¯ããŒããã©ã€ã 4. ã²ãŒã ã®é³å£°ãã¡ã€ã«ïŒ.wavïŒ
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒãã«ãæã«ãã®å®è¡ãã¡ã€ã«ïŒ.exeïŒãšåæã«çæããããããã°ã·ã³ãã«ãã¡ã€ã«ïŒ.pdbïŒ
MiniDumpå
ã®æ©æ¢°èªã¢ãã¬ã¹ãšãœãŒã¹ã³ãŒãã®ãã¡ã€ã«åã»è¡çªå·ã埩å
ããã«ã¯ããã«ãæã«çæãããåäžããã·ã¥ã®ãããã°ã·ã³ãã«ïŒ.pdbïŒãå¿
é ã§ãã
Q2. æé©åãã«ãïŒ-O2ïŒã®ã¯ã©ãã·ã¥ãã³ãã§ãåŒã³åºããã¯ãã®é¢æ°ãã³ãŒã«ã¹ã¿ãã¯ã«è¡šç€ºãããªãäž»ãªåå ã¯äœã§ããïŒ
1. ã³ã³ãã€ã©ã颿°ãåé€ããŠã²ãŒã ã軜éåãããã 2. ã€ã³ã©ã€ã³å±éïŒInliningïŒã«ããã颿°ã®ã³ãŒããåŒã³åºãå
ã«çŽæ¥åã蟌ãŸãCALLåœä»€ãæ¶å€±ãããã 3. ã¡ã¢ãªãè¶³ããªããŠé¢æ°åãä¿åã§ããªãã£ããã 4. ã¢ãã¿ãŒã®è§£å床ãäœããã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒã€ã³ã©ã€ã³å±éïŒInliningïŒã«ããã颿°ã®ã³ãŒããåŒã³åºãå
ã«çŽæ¥åã蟌ãŸãCALLåœä»€ãæ¶å€±ãããã
ã€ã³ã©ã€ã³å±éããããšé¢æ°åŒã³åºããªãŒããŒãããããªããªã代ããã«ç¬ç«ããã¹ã¿ãã¯ãã¬ãŒã ãçæãããªããããã³ãŒã«ã¹ã¿ãã¯ãã颿°åãæ¶ããŸãã
Q3. x64ç°å¢ã§ mov rax, [rcx + 0x18] ã®åœä»€ã§ã¢ã¯ã»ã¹éåãçºçããRCXã¬ãžã¹ã¿ã 0x00000000 ã ã£ãå ŽåãC++ã³ãŒãã¬ãã«ã§äœãèµ·ããŠããŸããïŒ
1. ã¡ã¢ãªãããŒããã£ã¹ã¯ã«æžã蟌ãŸãã 2. nullptr ã§ãããªããžã§ã¯ãïŒthisïŒã®ã¡ã³ã倿°ãžã¢ã¯ã»ã¹ããããšããïŒNull Pointer DereferenceïŒ 3. é
åã®ã€ã³ããã¯ã¹ã100äžãè¶
ãã 4. ãã«ãã¹ã¬ããã®ãããããã¯ãçºçãã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒnullptr ã§ãããªããžã§ã¯ãïŒthisïŒã®ã¡ã³ã倿°ãžã¢ã¯ã»ã¹ããããšããïŒNull Pointer DereferenceïŒ
x64åŒã³åºãèŠçŽã§ã¯ã¡ã³ã颿°ã® this ãã€ã³ã¿ã¯ RCX ã«å
¥ããããRCX=0 ã®ç¶æ
ã§ãªãã»ãã0x18ãèªã¿èŸŒãã®ã¯ nullptr->member ãåç
§ããå
žåçãªãã«ã峿»ã§ãã
Q4. ãããã¬ãã¢ã¿ããããŠèª¿æ»ããããšãããšã¿ã€ãã³ã°ãã¡ã¢ãªé
眮ãå€åããŠçºçããªããªããã°ã®éç§°ã¯äœã§ããïŒ
1. ãªãŒã ã®æ³å 2. ãã€ãŒã³ãã°ïŒHeisenbugïŒ 3. ã·ã¥ã¬ãã£ã³ã¬ãŒã®ç« 4. ã ãŒã¢ã®æ³å
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒãã€ãŒã³ãã°ïŒHeisenbugïŒ
ç©çåŠè
ãã€ãŒã³ãã«ã¯ã®äžç¢ºå®æ§åçã«ã¡ãªã¿ã芳å¯ïŒãããã¬æ¥ç¶ããã°åºåïŒããããšãããšæåãå€ãã£ããåçŸããªããªããã°ããã€ãŒã³ãã°ãšåŒã³ãŸãã
ð»ââïž ã·ãã¯ãC++ã©ã ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ã·ã¹ãã
ãã©ãŠã¶ã§JavaScriptãæå¹ã«ãããšããã©ãŠã¶å
ã€ã³ããŒããŒã²ãŒã ãšãã¥ã¬ãŒã¿ãã¡ã¢ãªãããå¯èŠåãUMLã¯ã©ã¹å³ã察話å解説ãç解床ã¯ã€ãºãèµ·åããŸãã
ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ãéå§ãã â