C 프로그램에서 늘 마주치는 것이 코어덤프인데 어떤 코드 때문에 발생했는 지 찾을 때 사용하는 것이 gdb 와 dbx 명령이다. AIX 에서는 dbx명령을 주로 사용한다. 이렇게 dbx 를 사용하여 추적하기 위하여서는 컴파일 할 때 -g 옵션을 줘서 컴파일을 해 줘야 한다.
| 샘플프로그램 작성
샘플 프로그램인 sfw0023.c 에 아래와 같이 코어덤프가 발생할 코드를 기술한다. ( 324 라인 ) bug 라는 포인터에는 메모리가 할당되지 않았기 때문에 값을 write 하면 core 덤프가 발생하게된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | 318 static long 319 a000_validation(sfw0023_ctx_t *ctx) 320 { 321 long rc = RC_NRM; 322 char *bug= NULL; 323 324 strcpy( bug, "debug"); 325 326 /* 데이터건수 30개로 제한 */ 327 if (sfw0023_IN->data_cnt > 30) { 328 PFM_ERR("PFM03010", "조회 데이터건수는 30개 이하로 로 제한 됩니다."); 329 return RC_ERR; 330 } | cs |
| 컴파일
이제 컴파일을 하고 Tmax 에서 실행이 가능하도록 적용을 한다. 프로프레임에서는 서비스프로그램과 make 파일이 1:1 로 작성하도록 가이드하고 있다. make 파일 뒤에 옵션으로 onlinstall 을 주면 컴파일 후 dlupdate 까지 한꺼번에 실행한다. 컴파일 옵션에 -g 가 들어가 있는 것을 확인한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | [pfm@devap1:/nbsroot/sol/tmax/appbin]$ make -f sfw0023.mk clean all onlinstall cc -qlanglvl=extc99 -g -q64 -O2 -brtl -w -qcpluscmt -DUSE_TCACHE -DPDB_TRACE -DGLOBALCB -DAUTOFREECB -DTRACE -DDEBUG -DTCACHE_ON -D_TMAX_ -DFRAME_DEV -D_BEFORE_REG_ERRDB_ -DVAR_ARGS_SUPPORT -I/nbsroot/sol/fw/inc -I/nbsroot/sol/fw/reference/inc -I/nbsroot/app/fw/inc -I/nbsroot/app/com/inc -I/nbsroot/app/cs/inc -I/nbsroot/app/dep/inc -I/nbsroot/app/for/inc -I/nbsroot/app/ext/inc -I/nbsroot/app/gac/inc -I/nbsroot/app/int/inc -I/nbsroot/app/lan/inc -I/nbsroot/app/lon/inc -I/nbsroot/app/acc/inc -I/nbsroot/app/dbio/inc -I/nbsroot/app/ckk/inc -I/nbsroot/app/ebk/inc -I/nbsroot/sol/tmax/usrinc -I/nbsroot/sol/tmax -I/sw/oracle/product/112/precomp/public -I/nbsroot/oracle/product/112/rdbms/public -I -I -c sfw0023.c cc -G -bshared -o libsfw0023.so sfw0023.o -L/nbsroot/sol/fw/lib -L/nbsroot/app/fw/lib -L/nbsroot/app/com/lib -L/nbsroot/sol/tmax/lib64 -L/nbsroot/oracle/product/112/lib -L/usr/lib -lcacomm -licauth -lcalib -lfilechk ld: 0711-224 WARNING: Duplicate symbol: request_from_tpm ld: 0711-224 WARNING: Duplicate symbol: reply_from_tpm ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information. Target "all" is up to date. | cs |
단말 화면에서 해당 거래를 실행 하면 예상대로 "미들웨어 오류 코드(29:TPESVRDOWN)" 오류가 발생하게 된다.
| 코어 파일 분석
이제 코어파일을 분석해 보자. 코어파일은 바이너리가 실행된 곳에 생기니까 티맥스 서버바이너리가 있는 $TMAXDIR/appbin 에 생겨 있을 것이다. 코어파일은 미들웨어 담당자가 추가 설정을 하여 발생 즉시 rename 해 놓을 수도 있지만 기본적으로 core 라는 이름으로 생성된다. 먼저 어떤 프로그램이 실행되다가 발생되었는 지 확인하기 위하여 file 명령어를 이용한다. 여기서는 TFW002 라는 프로그램이 돌다가 core를 만든 것을 알 수 있다. sfw0023 모듈은 TFW002 속에서 동작하고 있는 것이다.
core를 발생시킨 실행 프로그램을 알았다면 이제 dbx를 실행한다. 실행방법은 [dbx 실행프로그램 코어파일] 이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | [pfm@devap1:/nbsroot/sol/tmax/appbin]$ [pfm@devap1:/nbsroot/sol/tmax/appbin]$ ll core -rw-rw-rw- 1 tmax tmax 36648 Mar 24 18:41 core [pfm@devap1:/nbsroot/sol/tmax/appbin]$ file core core: AIX core file 64-bit, TFW002 [pfm@devap1:/nbsroot/sol/tmax/appbin]$ dbx TFW002 core Type 'help' for help. warning: The core file is not a fullcore. Some info may not be available. [using memory image in core] reading symbolic information ... Segmentation fault in pthread_kill at 0x900000000564f14 0x900000000564f14 (pthread_kill+0xd4) e8410028 ld r2,0x28(r1) | cs |
| 오류 발생 위치 추적
AIX에서는 dbx 명령으로 코어파일을 분석할 수 있다. 분석 방법은 여러가지가 있겠지만 where 명령으로 function call 스택순서를 추적할 수 있다. 맨 아래서 부터 따라 분석하면 TFW002.c > pfmsframe.c > pfmdlcall.c > sfw0023.c 로 function이 호출되어져 온 것을 알 수 있다. 그리고는 결국 sfw0023.c 의 324 라인에서 최종적으로 죽은 것 임을 알 수 있다. ( 8 line ) 위의 샘플 소스 프로그램에서 정확히 324 라인에 오류 루틴을 작성한 것이 정확하게 검출되었음을 알 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | (dbx) where pthread_kill(??, ??) at 0x900000000564f14 _p_raise(??) at 0x900000000564764 skgesigOSCrash(??) at 0x900000003cd1b7c kpeDbgSignalHandler(??, ??) at 0x900000003d3e910 skgesig_sigactionHandler(??, ??, ??) at 0x900000003cd1f00 .() at 0xfe04 IPRA.$a000_validation(ctx = 0x4600000000000046), line 324 in "sfw0023.c" unnamed block in sfw0023(dummy = (nil)), line 246 in "sfw0023.c" sfw0023(dummy = (nil)), line 246 in "sfw0023.c" tdlmain._tdlcall() at 0x900000006022fa0 tdlmain.tdlcall() at 0x900000006026424 customhook.tdlcall() at 0x900000005f58fe8 _mpfm_dlcall(fname = warning: Unable to access address 0x5000000000000050 from core (invalid char ptr (0x5000000000000050)), args = 0x0000000000000063, file_name = warning: (invalid char ptr (0x0000000000000001)), func_name = (nil), line = 0), line 66 in "pfmdlcall.c" unnamed block in svcbody_withcb(ctx = 0x0900000005f540f0), line 227 in "pfmsframe.c" svcbody_withcb(ctx = 0x0900000005f540f0), line 227 in "pfmsframe.c" mpfm_svc_entry(svcname = "`", msg = 0x09001000a18d32e0), line 114 in "pfmsframe.c" sfw0023(msg = 0x0000000058d4e9ce), line 128 in "TFW002.c" service_hook() at 0x900000005f53d70 _call_svc_func() at 0x900000005fce474 _run_svc() at 0x900000005fce028 _request_from_clh() at 0x900000005fd1768 _loop() at 0x900000005fd0ba4 main._tmax_main() at 0x900000005fd1954 tpsvrhook._tmax_main() at 0x900000005f533b4 TFW002_svctab.main(argc = 0, argv = (nil)), line 52 in "TFW002_svctab.c" (dbx) | cs |
|분석 쉘 작성
dbx 에서 where 명령을 주로 사용한다면 분석 쉘을 작성하여 놓고 간편하게 사용하는 것도 괜찮다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #--------------------- # USAGE #--------------------- if [ $# -ne 1 ];then echo "<core file list>" # 코어파일을 찾아서 목록을 보여줌 find /aplog/core/ -ctime -1 -type f -name "core.*" -exec ls -al {} \; | sort +5 +6 +7 echo "\n 사용법 : $> $0 corefile_name " exit fi #--------------------- # MAIN #--------------------- svr_name=`file $1 | awk '{ print $7 }'` echo where | dbx ${TMAX_DIR}/appbin/$svr_name $1 | cs |
| help
dbx 에서 help 명령을 치면 여러가지 사용할 수 있는 명령어들이 많이 나오지만 보통 where 명령만 해도 core 파일 분석에는 충분하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | (dbx) help Commands: addcmd alias assign attribute barrier call case catch clear cleari condition corefile coremap cont delcmd delete detach disable display(/) down dump edit enable fd 때문ㅇ file frame func goto gotoi handler help ignore kthread limitbp list listi malloc map move multproc mutex spinlock next nexti onceblock plugin pluginload pluginunload print printbp proc prompt pthread quit registers rerun resource return run rwlock screen search(/?) set sh skip source status step stepi stop stophwp stopi thread tls tm_status tnext tnexti trace tracehwp tracei tskip tstep tstepi tstop tstophwp tstopi ttrace ttracehwp ttracei unalias unset up use whatis where whereis which Topics: startup execution breakpoints files data machine environment threads corefiles expressions scope set_variables usage Type "help <command>" or "help <topic>" for help on a command or topic. (dbx) | cs |
<2010년1월>
참고글 : gdb 사용법
'컴퓨터활용 > 유닉스' 카테고리의 다른 글
디스크 사용량 조회 (0) | 2017.06.18 |
---|---|
일괄 거래 재거래 (1) | 2017.06.08 |
티베로 쿼리 실행 쉘 예제 (0) | 2016.10.29 |
유닉스 쉘에서 스페이스 잘리지 않게 유지하고 읽는 방법 (0) | 2016.10.29 |
gdb 사용법 (0) | 2016.07.19 |