반응형

8086 명령어

 

 

 

 

 

ADD

Signed or Unsigned ADD

원천 오퍼랜드를 목적지 오퍼랜드에 더하고 그 결과를 목적지 오퍼랜드에 저장한다

AND

Logical AND

두 오퍼랜드에 대해 논리 AND를 수행하여 그 결과를 목적지 오퍼랜드에 저장한다

CALL

Call a Procedure

제어를 프로시져로 넘긴다. RET를 사용하여 제어를 CALL 다음의 명령어로 되돌린다

CMP

Compare Operands

길이가 같은 두 오퍼랜드를 비교한다. 원천 및 목적지 오퍼랜드는 변경되지 않는다

CMPS

Compare Byte or Word String

스트링을 한번에 한 바이트 또는 한 워드씩 비교한다

CMPSB

Compare Byte or Word String

스트링을 한번에 한 바이트 또는 한 워드씩 비교한다

CMPSW

Compare Byte or Word String

스트링을 한번에 한 바이트 또는 한 워드씩 비교한다

DEC

Decrement

목적지 오퍼랜드에서 1을 뺀다

DIV

Unsigned Division

부호없는 워드(AX)를 바이트로 나누거나 부호없는 더블워드(DX:AX)를 워드로 나눈다

IDIV

Signed Number Division

부호있는 워드(AX)를 바이트로 나누거나 부호있는 더블워드(DX:AX)를 워드로 나눈다

IMUL

Signed Number Multiplication

부호있는 바이트 또는 워드 원천 오퍼랜드를 AL 또는 AX에 있는 부호있는 바이트 또는 워드에 곱하여 그 결과를 AX 또는 DX:AX에 저장한다

INC

Increment

오퍼랜드에 의해 지정된 레지스터 또는 메모리 위치에 1을 더한다.

INT

Intettupt

실행을 256가지의 인터럽트중의 하나로 넘긴다

JUMP

Conditional Jump

어떤 조건이 만족되면 행선지 번지로 점프하도록 하는데 사용한다.

JMP

Unconditional Jump

새로운 번지로 제어를 무조건 넘기는데 사용한다. JMP CALL의 차이는, CALL 명령어는 CALL 다음의 명령어로 되돌아와 실행을 계속하는 반면 JMP는 되돌아오지 않는다

LEA

Load Effective Address

직접 메모리 오퍼랜드의 유효 번지를 목적지에 로드한다

LOCK

Lock System Bus Prefix

2개 이상의 프로세서가 있는 마이크로컴퓨터에서 한 프로세서가 명령어를 실행하고 있는 동안 다른 프로세서가 시스템 버스의 제어권을 빼앗지 못하도록 하기 위해 사용된다

LOOP

Loop until CX =0

CX 1 감소시킨 다음 CX가 아니면 오퍼랜드가 가리키는 곳으로 점프하며, 0일 경우에는 LOOP아래에 있는 다음 명령어를 실행 시킨다

MOV

Move

레지스터, 메모리 위치, 즉석 상수인 워드 또는 바이트를 레지스터 또는 메모리 위치에 복사한다.

MOVS

Move Byte or Word String

 

DS : SI가 가리키는 메모리의 위치로부터 바이트 또는 워드를 ES : DI가 가리키는 메모리 위치로 복사한다.

MOVSB

Move Byte or Word String

DS : SI가 가리키는 메모리의 위치로부터 바이트 또는 워드를 ES : DI가 가리키는 메모리 위치로 복사한다.

MOVSW

Move Byte or Word String

DS : SI가 가리키는 메모리의 위치로부터 바이트 또는 워드를 ES : DI가 가리키는 메모리 위치로 복사한다.

MUL

Unsigned Multiplication

오퍼랜드가 가리키는 부호 없는 바이트 또는 워드를 AL 또는 AX에 들어있는 바이트 또는 워드에 곱한 결과를 AX 또는 DX : AX 에 저장한다

NEG

Negate

오퍼랜드에 대해 2의 보수를 취한다

NOP

No Operation

아무 일도 수행하지 않는다

NOT

Logical NOT

오퍼랜드에 대해 1의 보수를 취한다

OR

Logical OR

두 오퍼랜드에 대해 비트끼리 논리 OR 연산을 수행하고 그 결과를 목적지 오퍼랜드에 저장한다

POP

POP Word

스택포인터가 가리키는 워드를 오퍼랜드가 가리키는 레지스터 메모리위치로 복사하고 SP 2 증가 시킨다

POPF

POP Flags off Stack

스택에 PUSH시켜 놓았던 비트를 플래그 레지스터로 복사한 다음에 SP2 증가 시킨다

PUSH

PUSH Word

스택에 원천 오퍼랜드의 워드를 복사하고 SP 2 감소시킨다

PUSHF

PUSH Flags onto Stack

SP 2 감소시킨 다음에 플래그 레지스터의 내용을 스택에 복사한다

RET

Return from a Procedure

앞서 CALL 명령어에 의해 호출되었던 피호출 프로시저로부터 호출프로시저로 복귀하는데 사용된다.

SHL

Shift Left

부호 없는 수에 사용되는 논리쉬프트로써 부호 비트도 데이터로 취급한다.

SHR

Shift Right

부호 없는 수에 사용되는 논리쉬프트로써 부호 비트도 데이터로 취급한다.

STOS

Store Byte or Word String

: AX, AL의 내용을 ES:DI가 가리키는 위치에 복사하고, DI 1또는 2 증가시킨다

STOSB

Store Byte or Word String

: AX, AL의 내용을 ES:DI가 가리키는 위치에 복사하고, DI 1또는 2 증가시킨다

STOSW

Store Byte or Word String

: AX, AL의 내용을 ES:DI가 가리키는 위치에 복사하고, DI 1또는 2 증가시킨다

SUB

Subtract

목적지 오퍼랜드로부터 원천 오퍼랜드를 빼서 그 결과를 목적지에 저장한다

TEST

Test Bits

두 오퍼랜드에 대해 논리 AND를 수행하고 플래그를 설정하지만 두 오퍼랜드의 내용은 변하지 않는다.

XCHG

Exchange

두 레지스터 또는 레지스터와 메모리 위치의 내용을 교환한다

XOR

Exclusive OR

두 오퍼랜드의 비트들에 대해 논리 XOR를 수행하여 그 결과를 목적지 오퍼랜드에 저장한다.

 

반응형
반응형

CPU 레지스터(8086)의 종류와 용도

Windows 구조와 원리(정덕영 저)

어셈 코드를 디버깅할 때, asm명령과 레지스터 몇가지만 알고 있어도 많은 도움이 됩니다.
이번 포스트에서는 x86 CPU레지스터에 대해 정리합니다.

범용 레지스터( General Register )

범용 레지스터는 연산 결과를 받을 수도 있으며, 연산에 사용되어질 수도 있는 레지스터로 과거 8bit컴퓨터에서는 연산 결과를 저장하기 위하여 특정 레지스터를 사용할 수 밖에 없었으나 8086에서는 범용 레지스터를 사용하여 모든 연산을 수행 할 수 있다

AX( AH, AL )

Accumulator Register

산술, 놀리 연산의 중심이 되는 레지스터이며, Input/Output 포트의 입출력 명령 또한 주로 이 레지스터를 사용한다.

BX( BH, BL )

Base Register

간접 번지 지정 시 번지 레지스터. 베이스 레지스터로 주로 사용된다

CX( CH, CL )

Count Register

루프와 같이 어떤 명령을 반복적으로 수행하고자 할 때 반복 횟수를 지정하는데 주로 사용된다

DX( DH, DL )

Data Register

간접 번지 지정에 의한 입출력 명령을 실행 할 때 번지 지정에 사용된다. 곱셈, 나눗셈을 할 때는 보조 어큐뮬레이터로 사용되이 지기도 한다.

포인터 레지스터

SP

Stack Pointer

현재까지 사용되어진 스택의 위치를 저장하기 위하여 사용되는 레지스터로 세그먼트 레지스터 SS와 함께 사용된다.

BP

Base Pointer

스택의 데이터를 액세스 하기 위해 사용된다.

인덱스 레지스터

SI, DI

Source Index

다른 범용 레지스터와 마찬가지로 연산과 간접 번지 지정에 사용된다. 그 밖에 문자열의 전송이나 비교 등을 하는 스트링 명령에서 SI source가 되는 문자열을 나타내고, DI destination이 되는 문자열의 번지를 표시하는데 쓰인다.

IP( 명령 포인터 )

IP

Instruction Pointer

이 레지스터는 언제나 다음에 실행할 명령이 들어 있는 메모리의 번지를 가리킨다. CS 세그먼트 레지스터와 한 쌍이 되어 실행 번지가 만들어 진다.

플래그 레지스터

8086에는 16비트로 된 플래그 레지스터가 준비되어 있다. 연산의 결과 및 시스템 제어를 위한 정보가 각각 배정되어 있다.

상태 플래그

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

O

D

I

T

S

Z

A

P

C

Flags

Status Flags

CF

Carry Flag

연산 명령 실행 후 최상위 비트(MSB)에 덧셈에 따른 자리올림(carry) 또는 뺄셈에 의한 빌림(borrow)이 생길 때 설정된다.

PF

Parity Flag

연산의 결과 하위 8비트 중에서 1로 되어 있는 비트의 개수가 짝수 개일 때 셋(1)되고, 홀수 개일 때는 리셋(0)된다.

AF

Auxiliary Flag

연산의 결과 하위 4비트에 자리올림 또는 빌림이 TODRURT을 경우 설정된다. 10진 연산 처리를 할 경우에 이용된다.

ZF

Zero Flag

연산 결과가 0이 될 때 설정된다. 비교 명령 등도 레지스터의 내용은 변경시키지 않지만 뺄셈이 이루어지므로 그 결과에 따라서 설정된다.

SF

Sing Flag

연산 결과 최상위 비트가 1일 때 설정되고, 0일 때 리셋된다. 부호가 있는 수치의 경우에는 최상위 비트(MSB) 1이면 음수를 표시한다.

OF

Overflow Flag

부호 연산 처리의 결과 부호부 2진 표시로 오버플로우가 생겼을 때 설정된다. 바이트 연산에서는 -128~+128, 워드 연산에서는 -32768~+32767의 범위를 초과했다는 것을 표시한다.

컨트롤 플래그

Flags

Status Flags

DF

Direction Flag

스트링 처리에서 연속하여 처리되는 문자열에 대해서 그 처리 방향을 표시한다. 스트링 명열의 실행에 앞서서 이 플래그를 설정도는 리셋하여 처리 방향을 정해 둔다. , DF 플래그가 0일 때에는 하위 번지로부터 상위 번지 쪽으로 처리되며, DF 플래그가 1일 때에는 상위 번지로부터 하위 번지 쪽으로 처리된다.

IF

Interrupt Flag

8086의 인터럽트 중에서 하드웨어로부터의 인터럽트에 관하여 제어를 한다. IF 플래그가 1일 때에는 인터럽트를 받아들이고, 0일 때에는 인터럽트를 받아들이지 않는다.

TF

Trap Flag

명령 실행 후 이 플래그가 세트되어 있으면 단일 스텝 인터럽트가 발생한다. 이 기능을 사용하면 하드웨어의 도움을 받을 필요 없이 프로그램을 한 명령씩 실행 시켜 동작을 확인할 수 있다.

세그먼트 레지스터

프로그램이 수행되기 위해서는 여러 가지 메모리 주소가 필요하다. 우선 현재 수행되고 있는 명령어의 위치를 나타내는 값, 프로그램이 사용하는 데이터가 있는 메모리 값, 그리고 함수 호출등을 휘한 스택의 위치를 나타내는 값 emddlekk.

8086은 어드레스 버스가 20비트로 구성되어 있어서 1MByte까지 메모리 번지를 나타낼 수 있으나 8086에 있는 레지스터는 16비트 밖에 되지 않아서 어떤 명령이 수행되어 메모리를 참조할 때에는 항상 다음과 같이 암시적 또는 명시적으로 세그먼트 레지스터가 개입된다.

세그먼트

오프셋

목적

CS( Code Segment )

IP

수행되어질 명령어의 위치

DS( Data Segment )

AX, BX, CX, DX와 같은 범용레지스터와 BX, DI,SI

데이터 주소 참조

SS( Stack Segment )

SP 또는 BP

스택 주소 참조

ES( E Segment )

스트링 명령어를 위한 DI

스트링 목적지 주소

 

반응형
반응형

이 카타고리에서는 WinDbg를 이용한 실제 디버깅 방법에 대해 다룰 계획이다.

 

그렇다면 내가 WinDbg를 잘 다루는가?

 

~얼대 아니다.

 

이제 겨우 WinDbg 커맨드에 대해 공부하고 있는 입장이니, 병아리라 봐야겠지.

 

그래도 해야하고, 또 재미를 느낄 수 있으니 하나하나 습득해 가는 지식들을 채워갈 요량이다.

 

우선, WinDbg카타고리에는 맞지 않을지 모르나,

 

내가 WinDbg 사용방법을 익히는 첫번째 이유가 드라이버 디버깅이기 때문에,

 

디버깅에 필요한 선수 지식부터 정리할 생각이다.

 

순서 대로 가자면, WinDbg 설치, 디버거 셋팅 등등이 선행되야겠지만,

 

지금 보고 있는 부분이 어셈블리 코드를 통한 디버깅, 콜스택 백 트레이싱, 덤프 분석 부분이기 때문에

 

이 과정에서 필요한 선수 지식에 대해 먼저 다룬다.

 

드라이버 하는 사람들에게는 기본인지 모르겠으나,

 

난 아직 기본이 안되서 인지, 맨땅에 헤딩이니 이해되는 부분부터 살살 정리 할란다.

 

... CPU레지스터, 스택 등등에 대한 내용이 되지 않을까 싶다.

 

생각보다 먼~나라 이야기만은 아닌거 같다.

 

 

반응형
반응형

ba(break on access)

 

ba 커맨드에 대해 설명하기 전에 한가지 재미있는(?혹은 식상할 수도) 코드를 보여드리려 합니다.

이 프로그램은 두 개의 전역변수를 가지고 있고, PrintGlobalVariable() 함수를 통해 두개의 전역변수를 출력합니다.

프로그램이 간단하니 어렵지 않게 출력 결과를 유추하실 수 있겠죠?

char g_szTitle[32] = "TestApp - User";

DWORD g_dwPort = 8080;

 

void PrintGlobalVariable();

 

int _tmain(int argc, _TCHAR* argv[])

{

             PrintGlobalVariable();

             strcpy(g_szTitle, "TestApp - GOODSMELL's COMPUTER!!!!");

             PrintGlobalVariable();

            

             return 0;

}

 

void PrintGlobalVariable()

{

             printf("g_szTitle = %s, g_dwPort  = %d\n", g_szTitle, g_dwPort);

}

 

예상하신 결과가 맞나요??

 

위의 프로그램은 아주 예전에 발생했던 문제를 간소화 해서 코딩한 것입니다.

프로그램의 타이틀은 [AppName + Remote컴퓨터명 + etc…] 형태로 되어있고, 지정된 포트를 통해 다른 컴퓨터에 접속하는 프로그램이었습니다만, 특정 컴퓨터(항상 이게 문제죠…!)에서 접속을 2회 이상시도하게 되면 접속이 되지 않는 문제 였습니다.

 

위 프로그램의 출력결과는 아래와 같습니다.


두번째 출력전에 한것이라곤 g_szTitle에 문자열을 복사한 것 뿐인데, 포트 값이 바뀌어 있네요..

이제 어느정도 감이 오시죠?

 

문제를 좀더 명확히 하기 위해 다음 한 줄의 코딩을 추가했습니다.

printf("g_szTitle address = %p, g_dwPort address = %p\n", g_szTitle, &g_dwPort);

 

출력 결과는 다음과 같습니다.


이제 문제가 명확해 졌군요.
g_szTitleg_dwPort는 다른 변수이지만 할당된 메모리 공간이 인접해 있습니다.

0x002B7058 – 0x002B7038 = 0x20(32) ,g_szTitle이 할당된 메모리(32byte)에 연속해서 g_dwPort(4byte)가 할당되어 있습니다. strcpy()함수 호출을 통해 35byte(g_szTitle:32byte)의 메모리를 변경했기때문에 g_dwPort 3byte를 덮어써 버린것이죠.  

g_szTitle(32bytes)

0x002B7038

g_dwPort(4bytes)

0x002B7058

 

 

 

 

 


위와 같은 문제가 아주 덩치가 큰 프로그램에서 발생한다고 하면, 사실 좀 난감합니다. 일단 어찌 어찌해서 g_dwPort가 변경되는 것 까지는 확인했다고 치겠습니다.

 

이 상황에서 ba 커맨드는 아주 유용합니다.

ba 커맨드의 사용포맷은 이렇습니다.(Access Size 는 붙여서 씁니다)

ba Access Size Address

n  Access

ü  e – excute(설정된 Address가 실행될 때 적중)

ü  r – read/write(설정된 AddressSize만큼 read or write 가 발생할때 적중)

ü  w - write(설정된 AddressSize만큼 write 가 발생할때 적중)

ü  I - io(설정된 Address io가 발생할때 적중) - widbg설명을 보니 port address등에 bp를 걸어 사용하면 되는듯 합니다만, 전 거의 그럴일이 없으니 pass~

n  Size

ü r/w - 1,2 or 4 (x86), 1,2,4 or 8 (x64)

ü 1e - 1

n  Address

ü  Memory 주소

 

자 그럼 위에서 하던 얘기를 마저 하겠습니다. 지금 상황에서는 다음과 같은 커맨드이면 될 것 같습니다.

ba w1 TestApp!g_dwPort

 

그럼 한 단계씩 디버깅해 보겠습니다.

n  [File>Open Excutable]메뉴를 이용해 TestApp.exe를 실행한후 wmail()함수에 breakpoint를 설정합니다. 

n  Wmain() breakpoint가 적중되면, g_dwPort ba커맨드로 breakpoint를 설정합니다.
계속 진행시키면 strcat+0xcd에서 breakpoint가 적중되었군요
.
strcpy
가 내부적으로 strcat을 호출하는가 봅니다.

 

n  그럼 이 시점에서의 CallStack strcat의 인자를 확인해 보겠습니다.
wmain
에서 호출된 strcat(strcpy)에 의해서 g_dwPort값이 변경되는 것을 알 수 있습니다
.
인자를 출력해 보니 역시나, g_szTitle에 복사하려던 문자열이네요.

 

ba 커맨드는 의외로 유용하게 사용 할 상황이 많이 있습니다. 저도 두번인가? 정말 유용하게 써먹었던 기억이 있습니다.^^
(아 그리고 string카피할때는 strncpy나 strcpy_s류의 함수를 쓰는게 좋은 습관인건 아시죠?)

 

 

 

아래는 ba관련 windbg도움말 입니다. 참고하세요.

ba (Break on Access)

The ba command sets a data breakpoint. This breakpoint is triggered when the specified memory is accessed.

Syntax

User-Mode

[~Thread] ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"]

Kernel-Mode

ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"]

Parameters

Thread
Specifies the thread that the breakpoint applies to. For more information about syntax, see Thread Syntax. You can specify threads only in user mode.
ID
Specifies an optional number that identifies the breakpoint. If you do not specify ID, the first available breakpoint number is used. You cannot add space between ba and the ID number. Each processor supports only a limited number of data breakpoints, but there is no restriction on the value of the ID number. If you enclose ID in square brackets ([]), ID can include any expression. For more information about the syntax, see Numerical Expression Syntax.
Access
Specifies the type of access that satisfies the breakpoint. This parameter can be one of the following values.
Option Action
e (execute) Breaks into the debugger when the CPU retrieves an instruction from the specified address.
r (read/write) Breaks into the debugger when the CPU reads or writes at the specified address.
w (write) Breaks into the debugger when the CPU writes at the specified address.
i (i/o) (Microsoft Windows XP and later versions, kernel mode only, x86-based systems only) Breaks into the debugger when the I/O port at the specified Address is accessed.

You cannot add space between Access and Size.

Note On Windows Server 2003 with Service Pack 1 (SP1), on an Itanium-based computer that uses WOW64 to emulate x86, data breakpoints do not work with the execute option but they do work with the read and write options.

Size
Specifies the size of the location, in bytes, to monitor for access. On an x86-based processor, this parameter can be 1, 2, or 4. However, if Access equals e, Size must be 1.

On an x64-based processor, this parameter can be 1, 2, 4, or 8. However, if Access equals e, Size must be 1.

On an Itanium-based processor, this parameter can be any power of 2, from 1 to 0x80000000.

You cannot add space between Access and Size.

Options
Specifies breakpoint options. You can use any number of the following options, except as indicated:
/1
Creates a "one-shot" breakpoint. After this breakpoint is triggered, the breakpoint is permanently removed from the breakpoint list.
/f PredNum
(Itanium only, user mode only) Specifies a predicate number. The breakpoint is predicated with the corresponding predicate register (for example, bp /f 4 address sets a breakpoint that is predicated with the p4 predicate register). For more information about predicate registers, see Itanium Architecture.
/p EProcess
(Kernel mode only) Specifies a process that is associated with this breakpoint. EProcess should be the actual address of the EPROCESS structure, not the PID. The breakpoint is triggered only if it is encountered in the context of this process.
/t EThread
(Kernel mode only) Specifies a thread that is associated with this breakpoint. EThread should be the actual address of the ETHREAD structure, not the thread ID. The breakpoint is triggered only if it is encountered in the context of this thread. If you use /p EProcess and /t EThread , you can enter them in either order.
/c MaxCallStackDepth
Causes the breakpoint to be active only when the call stack depth is less than MaxCallStackDepth. You cannot combine this option together with /C.
/C MinCallStackDepth
Causes the breakpoint to be active only when the call stack depth is larger than MinCallStackDepth. You cannot combine this option together with /c.
Address
Specifies any valid address. If the application accesses memory at this address, the debugger stops execution and displays the current values of all registers and flags. This address must be an offset and suitably aligned to match the Size parameter. (For example, if Size is 4, Address must be a multiple of 4.) If you omit Address, the current instruction pointer is used. For more information about the syntax, see Address and Address Range Syntax.
Passes
Specifies the number of times the breakpoint is passed by until it activates. This number can be any 16-bit value. The number of times the program counter passes through this point without breaking is one less than the value of this number. Therefore, omitting this number is the same as setting it equal to 1. Note also that this number counts only the times that the application executes past this point. Stepping or tracing past this point does not count. After the full count is reached, you can reset this number only by clearing and resetting the breakpoint.
CommandString
Specifies a list of commands to execute every time that the breakpoint is encountered the specified number of times. These commands are executed only if the breakpoint is hit after you issue a g (Go) command, instead of after a t (Trace) or p (Step) command. Debugger commands in CommandString can include parameters.

You must enclose this command string in quotation marks, and you should separate multiple commands by semicolons. You can use standard C control characters (such as \n and \"). Semicolons that are contained in second-level quotation marks (\") are interpreted as part of the embedded quoted string.

This parameter is optional

Environment

Modes User mode, kernel mode
Targets Live debugging only
Platforms All

Comments

The debugger uses the ID number to refer to the breakpoint in later bc (Breakpoint Clear), bd (Breakpoint Disable), and be (Breakpoint Enable) commands.

Use the bl (Breakpoint List) command to list all existing breakpoints, their ID numbers, and their status.

Use the .bpcmds (Display Breakpoint Commands) command to list all existing breakpoints, their ID numbers, and the commands that were used to create them.

The ba command provides the same functionality that the debug registers provide. You can break execution when the particular memory location is read from, written to, or executed.

The breakpoint is satisfied only when the access occurs at the given address and for the specified number of bytes. If the memory that is accessed overlaps the specified area to monitor, the breakpoint is not satisfied.

Although the size is required for all breakpoint types, an execute breakpoint is satisfied only if the address is the first byte in the instruction.

When you debug a multiprocessor system in kernel mode, breakpoints that you set by using bp (Set Breakpoint) or ba apply to all processors. For example, if the current processor is 3 and you type ba e1 MemoryAddress to put a breakpoint at MemoryAddress, any processor (not only processor 3) that executes at that address causes a breakpoint trap.

You cannot set the initial breakpoint in a user-mode process by using the ba command.

You cannot create multiple breakpoints at the same address that differ only in their CommandString values. However, you can create multiple breakpoints at the same address that have different restrictions (for example, different values of the /p, /t, /c, and /C options).

When you debug in kernel mode, the target computer distinguishes between user-mode and kernel-mode data breakpoints. A user-mode data breakpoint cannot affect kernel execution or memory access. A kernel-mode data breakpoint might affect user-mode execution or memory access, depending on whether the user-mode code is using the debug register state and whether there is a user-mode debugger that is attached.

To apply the current process' existing data breakpoints to a different register context, use the .apply_dbp (Apply Data Breakpoint to Context) command.

The following examples show the ba command. The following command sets a breakpoint for read access on 4 bytes of the variable myVar.

0:000> ba r4 myVar

The following command adds a breakpoint on all serial ports with addresses from 0x3F8 through 0x3FB. This breakpoint is triggered if anything is read or written to these ports.

kd> ba i4 3f8

Additional Information

For more information about and examples of using breakpoints, other breakpoint commands and methods of controlling breakpoints, and information about how to set breakpoints in user space from a kernel debugger, see Using Breakpoints. For more information about conditional breakpoints, see Setting a Conditional Breakpoint.

Build machine: CAPEBUILD
반응형
반응형

Windbg Case by Case

 

n  Windbg vmware를 이용한 디버깅 환경 구축
[디버깅/WinDbg] - VMware WinDbg 이용한 커널 디버깅

n  브레이크 포인트에 조건을 걸어 보자
[디버깅/WinDbg] - [WinDbg] 조건부 브레이크 포인트

n  커널모드에서 특정 프로세스 디버깅
[디버깅/WinDbg] - Kernel 모드에서 특정 프로세스 디버깅하기

n  wow64환경에서 x86프로셋 디버깅
[디버깅/WinDbg] - WOW64 디버깅

n 메모리 엑세스 시점 잡기
[디버깅/WinDbg]ba(break on access) 메모리 엑세스 시점


 

반응형
반응형

조건부 breadkpoint

 

아래와 같은 코드를 포함한 TestApp.exe 프로그램이 있고, 지역변수 i의 값이 9999인 상황에 문제가 발생한다 가정해 보자.

void DoSomething( int iValue )

{

             static int iStaticValue = 0;

            

             iStaticValue = iValue;

}

 

void SomeFunction()

{

             int i = 0;

             for ( i = 0; i < 10000; i++ )

             {

                           DoSomething( i );

             }

}

 

이 경우 다음과 같은 선택이 가능할 것이다.

1.      해당 함수에 breakpoint를 걸고 9999번을 트레이스 한다.(설마?)

2.      i값을 디버깅 상태에서 수정해서 디버깅을 한다.(어디까지나 이건 가정이고 만들어낸 예시 코드니까 이경우엔 부가적인 문제가 있다고 치자 - 예시는 예시일 뿐, 꼬투리 잡지 말자~)

3.      다음과 같은 코드를 작성한 후, “int k = 0;”breakpoint를 걸어서 디버깅한다.

void SomeFunction()

{

             int i = 0;

             for ( i = 0; i < 10000; i++ )

             {

                           if ( i == 9999 )

                           {

                                        int k = 0;

                           }

                           DoSomething( i );

             }

}

아마 많은 개발자들이 이와 같은 방법으로 디버깅을 할 꺼라 생각된다.

 

하지만 이러한 상황이 Unload를 지원하지 않는 드라이버의 코드라면? 혹은 여러 모듈이 얽혀서 돌아가는 시스템의 일부라면 여간 성가신 작업이 아닐 수 없다.

 

바로 이러한 상황에 사용하면 편리한 것이 조건부 breakpoint이다.

 

위의 상황에 적용해 보자면 아래와 같은 설정이 되겠다.(SomeFunction breakpoint를 걸려면 주소를 써야하니 보기 편하게 DoSomething() breakpoint를 걸어본다)

bp TestApp!DoSomething ".if@@( iValue == 9999 ) {} .else {gc}"

breakpoint에서 멈춰진 후 iValue의 값을 보면 9999임을 알 수 있다.

 

그럼 조건부 breakpoint 문법에 대해 조금 자세히 살펴보자

bp FuncAddress “.if @@(Condition) { Commands } .elsif @@(Condition) { Commands } .else { Commands }”

n  @@( )
괄호안에는 C/C++타입의 코드를 사용할 수 있을 뿐만 아니라, 정확한 심볼이 있다면 변수의 이름도 사용 가능하다..

n  { Commands }

n  Breakpoint가 적중되었을때 실행될 Windbg Command를 입력한다.

n  메시지를 출력하려면 .echo String 을 쓴다

n  두개 이상의 명령을 사용하려면, ;로 각 명령어를 구분한다.

n  .else 조건(조건이 만족하지 않을 경우)에는 g 커맨드 대신 gc(Go from Conditional Breakpoint)를 사용한다.(gc대신 g를 사용하면 해당 함수를 한 줄씩 step trace하는 동안 해당 함수를 도달 했을때 다음 명령(F10)이 아니라 F5를 누른 것처럼 그냥 진행되어 버린다.)

n  bp FuncAddress ntimes
breakpoint를 설정하면 해당 breakpointntimes만큼 적중(?)되었을 때 breakpoint가 걸리게 된다.
- [ bp TestApp!DoSomthing 10 ]

 

* WinDbg 도움말 키워드 - 'Setting a Conditional Breakpoint' 

* 참고사이트

http://blogs.msdn.com/debuggingtoolbox/archive/2008/06/12/special-command-if-and-j-to-use-in-breakpoints-and-scripts.aspx

http://www.driveronline.org/bbs/view.asp?tb=tipbbs&no=91

반응형

+ Recent posts