슬라이드는 “NDC2012 덤프 파일을 통한 사후 디버깅 실용 테크닉“에서 볼 수 있음.
넥슨 김이선 님의 발표.
내용 요약:
돈을 벌기 전에는 배포 전 디버깅이 중요하다.
라이브 상황에서는 배포 후 디버깅이 더 중요해진다.
덤프 파일
특정 상황 — 특히 안좋은 상황 — 에서 프로세스 상태를 디버깅 용으로 남기는 것.
풀 메모리 덤프를 남기면 좋지만 커서(…) 미니 덤프를 남긴다.
상용 서비스까지 갔다면 미니덤프를 남기고 이를 수집해서 디버깅하는 시스템은 필수.
하지만 미니 덤프 디버깅의 현실은…
- 덤프 파일을 열었는데 심볼이 없다고 어셈블리 코드가 보이는 경우
- 여기서 죽으면 안되는데 왜 죽었나 싶은 경우?
- 콜스택이 깨졌다거나
- 풀 메모리 덤프를 남겼는데 내가 보려는 객체는 어디에?
덤프 파일과 pdb 파일 연결하기
- 미니덤프 헤더는 RSDS 헤더, GUID, age, pdb-path 등이 들어감
- pdb, exe, minidump는 이 GUID로 연결된다
- 심볼서버는 당연히 써야
- 보안 솔루션 (더미다 류) 을 사용하면 덤프 파일의 GUID가 바뀐다
- 하지만 COFF file format의 링크 시간을 기록한 타임 스탬프는 유지
- 클라이언트 덤프 수집단계에 미니덤프와 해당하는 PDB를 맺어주는 단계를 넣자(클라이언트 버전 정보; 타임 스탬프를 이용해서)
여러 개의 덤프 파일을 분석할 때
일어나지 않을 것 같은 일도 덤프 파일이 많으면 분석할 수 있음 ((이건 이전 회사에 있을 때 내가 포스트모텀 디버깅, 그것도 최대한 많은 수를 수집해야 한다고 주장한 이유와 같음))
- 분류 기준으로 EIP, callstack, 게임에 따른 정보(맵, 장비, …)
- 외부 모듈이나 말이 안되는 곳이면 어떻게하지? 클라는 환경을 통제할 수 없으니 외부 변수를 추적한다
- EIP와 다른 변인 (OS, CPU, GPU) 등을 보면 예상되는 것과 다른 분포인 경우가 있다 (=환경 편재)
- OS라면 드라이버 버그, CPU의 문제 (보통은 mainboard), GPU 문제, 외부 모듈 (보안 프로그램이나 해킹 툴)
사례 분석
- DF의 코드 베이스를 VS 2003에서 VS 2008로 이전함.
- 특정 유저 (소수) 에서 채널 선택하는 순간 HeapAlloc/HeapFree 중에 크래시 하는 버그 발견
- Heap-corruption이라,
- 게임 시작에서 채널 선택하는 부분까지의 코드를 리뷰
- 이 영역에 많은 수의 trap code와 HeapValidate 코드 삽입
- 하지만 문제는 발견되지 않음
- 모듈 목록에 환경 편재가 있음: BFCO0GAF.dll 등의 알파벳/숫자가 섞인 특정 패턴의 모듈 발견
- 해당 dll이 악성 프로그램이 삽입한 것; 2003과 2008의 heap 구현이 달라서 생긴 일
콜 스택이 깨지는 경우
- EBP, ESP 중 하나만 깨져도 콜 스택을 복원할 수 없다
- 이를 다음 휴리스틱으로 극복
- 스택 메모리에서 주소를 추려낸다 (모듈 정보의 주소 영역을 이용해서)
- 스택 메모리에서 스택 주소를 추려낸다
- 1 + 2를 해서 콜 스택을 추정
- 프로그래머의 해석이 필수
힙 메모리 문제
- 메모리 덤프가 있으면 디버깅에 큰 도움이 된다
- 하지만 모든 메모리 객체에 접근하는 건 쉽지 않음
- 메모리를 exhaustive하게 검색
- vfptr 값 이용
- typeid(T)의 구현 형태를 이용해서 타입 이름을 이용해서 검색
감상:
이번에 네 개 세션 밖에 못들었는데, 그 중 제일 괜찮은 강연이었다. 다음 세션을 회사 돌아갈 시간이라 못 들은게 아쉬움.
내가 예전에 했던 유사한 시도는 통계적으로 분류하고 / 적당한걸 찾을 수 있게 도와준다 정도였는데 (VS 안띄우게 하는게 목표였으니..) 이렇게 실제 사례를 바탕으로 한 내용을 알고 있었다면 훨씬 좋게 할 수 있었을 듯.
그리고 바이너리가 수정된 경우의 처리는 제대로 못했는데 — ipkn 패치해서 돌아가게 수정 — 이 부분에 대한 정보도 얻게 되어서 좋았다.
게다가 강연자 분이 “이런거 되는걸 모아서 새로 짜서 공유했습니다”라고 말한건 대박(…).
아마 `지식 공유’란 점에서 모델이 될만한 수준.
summerlight 님이 녹화한 영상도 토런트 시딩되고 있을테니 (촬영 가능한 세션이었음) 관심 생기신 분들은 한 번씩 보는걸 추천합니다.
개인적으로 가장 궁금했던게 최적화 이후 스택이 바뀌는거에 어떻게 대처하느냐, 였는데 무려 _alloca를 (…) 이건 생각도 못하던 참신한 방법이라 괜찮았습니다.
여담이지만 vs 다음 버젼부터는 최적화로 인해 스택 모양새가 바뀌는 것이나 함수 반환 값도 pdb에 반영해준다고 하니 이제 콜스택 안 보여서 삽질할 일도 많이 줄어들 듯…
흑흑 G모사 Style Guide에서 금하는 그 alloca입죠.
다음 버전 = VS11인건가요. 함수 반환 값 정보가 pdb에 들어가면 좋긴한데 왠지 툴 체인(=cl, windbg, …) 다 업뎃하려면 귀찮긴 하네요(야).
와…..
정말 유용한 정보네요.