1. 개요
2. backtrace (bt)
스택에 대한 backtrace를 보여주는 GDB 명령어이다.
(gdb) bt #0 0x0000003978a32495 in ssignal () from /lib64/libc.so.6 #1 0x00007f85bcab5b80 in ?? () #2 0x00007f868be1cf28 in ?? () #3 0x0000000000000000 in ?? ()
3. 레지스터
레지스터는 CPU 내 공간으로 CPU가 데이터에 접근하기 위한 영역이라고 할 수 있다. info all-registers, info registers 혹은 i r을 실행하면 레지스터 정보를 볼 수 있다. 단 레지스터 이름은 머신이나 비트 수에 따라 다를 수 있다.
3.1. info all-registers
부동 소수점 레지스터를 포함한 모든 레지스터 정보(이름, 값)를 보여준다.
(gdb) info all-registers rax 0x0 0 rbx 0x1 1 rcx 0xffffffffffffffff -1 rdx 0x6 6 rsi 0x7f41 32577 rdi 0x7011 28689 rbp 0x7f85bcab5af0 0x7f85bcab5af0 rsp 0x7f85bcab59a8 0x7f85bcab59a8 r8 0x7f868c05a888 140215851526280 r9 0x8 8 r10 0x8 8 r11 0x206 518 r12 0x7f868c044849 140215851436105 r13 0x7f868bea6337 140215849739063 r14 0x7f868c05fb70 140215851547504 r15 0x7f868be480a0 140215849353376 rip 0x3978a32495 0x3978a32495eflags 0x206 [ PF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 st0 -nan(0x000000034) (raw 0xffff0000000000000034) st1 -nan(0x00000000c) (raw 0xffff000000000000000c) st2 -nan(0x570a3d70a3d71000) (raw 0xffff570a3d70a3d71000) st3 -nan(0x1570a3d70a3d71) (raw 0xffff001570a3d70a3d71) st4 0 (raw 0x00000000000000000000) st5 0 (raw 0x00000000000000000000) st6 0 (raw 0x00000000000000000000) st7 -nan(0x000000001) (raw 0xffff0000000000000001) fctrl 0x37f 895 fstat 0x0 0 ftag 0xffff 65535 fiseg 0x7f86 32646 fioff 0x8bc9e459 -1949703079 foseg 0x7f85 32645 fooff 0xbcab5998 -1129621096 fop 0x0 0 mxcsr 0x1fa0 [ PE IM DM ZM OM UM PM ] ymm0 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm1 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0 }, v16_int16 = {0x0, 0x0, 0xff, 0x0, 0xff, 0xff00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int32 = {0x0, 0xff, 0xff0000ff, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0xff00000000, 0xff0000ff, 0x0, 0x0}, v2_int128 = {0x00000000ff0000ff000000ff00000000, 0x00000000000000000000000000000000}} ymm2 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm3 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0 }, v16_int16 = {0x0, 0x0, 0x0, 0x0, 0xff, 0x0 }, v8_int32 = {0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0xff, 0x0, 0x0}, v2_int128 = {0x00000000000000ff0000000000000000, 0x00000000000000000000000000000000}} ymm4 {v8_float = {0x0, 0x0, 0x24f80000, 0xc, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x3ca48a, 0x0, 0x0}, v32_int8 = {0x38, 0x0, 0x3d, 0x75, 0x63, 0x73, 0x32, 0x2d, 0x3e, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x0 }, v16_int16 = {0x38, 0x753d, 0x7363, 0x2d32, 0x493e, 0x544e, 0x5245, 0x414e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int32 = {0x753d0038, 0x2d327363, 0x544e493e, 0x414e5245, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x2d327363753d0038, 0x414e5245544e493e, 0x0, 0x0}, v2_int128 = {0x414e5245544e493e2d327363753d0038, 0x00000000000000000000000000000000}} ymm5 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm6 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ---Type to continue, or q to quit--- ymm7 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm8 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm9 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm10 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm11 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm12 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm13 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm14 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}} ymm15 {v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0x0 }, v16_int16 = {0x0 }, v8_int32 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x0, 0x0, 0x0, 0x0}, v2_int128 = {0x00000000000000000000000000000000, 0x00000000000000000000000000000000}}
3-2. info registers
부동 소수점 레지스터를 제외한 레지스터 정보(이름, 값)를 보여준다.
(gdb) info registers rax 0x0 0 rbx 0x1 1 rcx 0xffffffffffffffff -1 rdx 0x6 6 rsi 0x7f41 32577 rdi 0x7011 28689 rbp 0x7f85bcab5af0 0x7f85bcab5af0 rsp 0x7f85bcab59a8 0x7f85bcab59a8 r8 0x7f868c05a888 140215851526280 r9 0x8 8 r10 0x8 8 r11 0x206 518 r12 0x7f868c044849 140215851436105 r13 0x7f868bea6337 140215849739063 r14 0x7f868c05fb70 140215851547504 r15 0x7f868be480a0 140215849353376 rip 0x3978a32495 0x3978a32495eflags 0x206 [ PF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0
3.3. 주요 레지스터
32비트 레지스터는 e로 시작하고, 64비트 레지스터는 r로 시작한다.
rax, rbs, rcx, rdx 레지스터들이 주로 데이터를 저장하는데 사용한다면 다음 나오는 포인터나 인덱스 레지스터들은 메모리의 위치를 저장하는데 사용한다.예를 들어 64비트 메모리 주소를 저장한다.
3.3.1. rax (eax)
누산기 (accumulator) 레지스터이다. 산술연산(덧셈, 나눗셈, 곱셈)이나 논리연산을 수행한 반환값이 저장된다.
내부적으로 16비트의 ax가 있고, ax는 다시 각각 8비트인 ah, al로 나뉜다.
================ rax (64 bits) ======== eax (32 bits) ==== ax (16 bits) == ah (8 bits) == al (8 bits)
3-3.2. rbx (ebx)
베이스 레지스터이다.
3-3-3. rcx (ecx)
카운터 레지스터이다. 반복 명령어 사용 시 반복 카운터로 사용되는 값을 저장한다.
3-3-4. rdx (edx)
데이터 레지스터이다. 산술연산과 I/O 명령에서 rax(eax)와 함께 사용된다. 예를 들어 곱하기, 나누기 등 복잡한 연산을 위해 추가적으로 데이터를 저장할 때 사용한다.
3-3-5. rsp (esp)
스택 포인터 레지스터이다. 스택의 가장 마지막 지점 주소를 저장한다.
함수가 호출될 때는 함수의 파라미터가 스택에 push되고, 그 다음 리턴 어드레스가 push된다. 따라서 함수가 호출되면 rsp는 스택의 가장 마지막 지점인 리턴 어드레스를 가리키게 된다.
3-3-6. rbp (ebp)
베이스 포인터 레지스터이다. 스택의 시작 지점 주소를 저장한다.
3-3-7. rsi (esi)
source 인덱스 레지스터
3-3-8. rdi (edi)
destination 인덱스 레지스터
3-4. 컨트롤 유닛
3-4-1. rip
명령 포인터 레지스터이다. 현재 명령의 위치를 가리킨다.
4. 어셈블리어 명령어
4-1. mov
(gdb) x/i 0x0000003978a32495 => 0x3978a32495: mov %rsp,%rdx
위의 mov는 move를 의미하며 데이터를 복사하는(이동하는 것이 아니다) 명령어로 %rdx를 %rsp에 넣는다.
- 값을 메모리나 레지스터에 넣을 때
- 메모리와 레지스터 사이의 데이터 복사
- 레지스터와 레지스터 사이의 데이터 복사
- 단 메모리와 메모리 사이의 복사는 불가
mov를 사용할 때는 값을 직접 넣을 수도 있고 특정 레지스터에 있는 값을 넣을 수도 있다.
mov eax, 6 mov ebx, eax
결과적으로 eax, ebx 모두 6이 들어가 있다.