컴퓨터활용/유닉스

AIX dbx 사용 core 분석

멜번초이 2017. 3. 24. 23:02

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 --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       -c sfw0023.c  
 
        cc --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 사용법