반응형

fprintf(),fwprintf()로 한글이 출력되지 않는 문제

 

fprintf()로 출력한 한글이 ???와 같이 깨져서 나오는 경우, 다음 함수를 통해 locale을 설정 해 주면 된다.

#include <locale.h>

_wsetlocale(LC_ALL, L"kor");

 


반응형

'C++' 카테고리의 다른 글

Cross Compile - Predefined Macros for OS  (0) 2020.06.18
map 파일  (0) 2011.07.26
Format Specification  (0) 2011.04.20
std::map  (0) 2009.09.03
std::vector  (0) 2009.08.26
반응형

.map 파일

 

n  map 파일이란?

ü  Application 빌드 시 생성되는 map 파일은 빌드 된 실행파일이 메모리에 로드 되었을 때, 전역변수, 함수가 위치할 Address를 기록해 놓은 파일입니다.

ü  Symbol파일이 없는 경우, 함수의 주소를 알고자 하거나 특정 Address가 어느 함수인지 확인 하는 용도로 활용할 수 있습니다.

 

n  map 파일 생성

ü  VC++ : [ 프로젝트> 속성> 구성속성> 링커> 디버깅 ]에서 맵 파일 생성을 예(/MAP)으로 설정하신 후 빌드 하시면 됩니다.


ü  드라이버 : SORCES파일에 아래의 한 줄을 추가해 주시면 됩니다.

 

LINKER_FLAGS=$(LINKER_FLAGS) –MAP

 

 

그럼 mapfile을 통해 함수와 Address를 확인 하는 방법을 알아 보겠습니다.

 

#include "stdafx.h"

#include <WTypes.h>"

 
DWORD g_dwDummy;

void DummyFunction_A()

{

           int a= 0;

           a++;

 

           return;

}

 

void DummyFunction_B()

{

           int b = 0;

           b--;

 

           return;

}

 

void DummyFunction_C()

{

           int c = 0;

           c += 2;

 

           return;

}

  

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

{

           HMODULE hInst = ::GetModuleHandle(NULL);

           DummyFunction_A();

           DummyFunction_B();

            

           printf( "Module Base Address: %#p\n", (void *)hInst);

           printf( "DummyFunction_A() Function Address: %#p\n", (void *)DummyFunction_A);

           printf( "DummyFunction_B() Function Address: %#p\n", (void *)DummyFunction_B);

           printf( "g_dwDummy Global Variable Address: %#p\n", &g_dwDummy);

 

           return 0;

} 


프로젝트 속성을 맵 파일을 생성하도록 설정한 후, 아래의 소스를 빌드하게 되면, TestApp.map이라는 파일이 생성되게 됩니다.

 

생성된 map파일의 내용은 아래와 같습니다.

 

제일 먼저 눈여겨 보아야 할 것은 제일 위의 빨간색 박스 안에 있는

Preferred load address is 00400000

입니다.

 

이 라인의 의미는 해당 바이너리가 메모리에 로드될 때 Base주소로 0x00400000 Address를 사용하겠다는 의미입니다.

Vista이하의 경우, Exe형태의 PE파일들은 대부분 설정을 변경하지 않는 이상 Preferred load Address로 0x00400000 Base주소로 사용하며, 실제로도 해당 Address에 모듈이 Load됩니다.
하지만 Win7의 경우에는 Exe형태의 PE파일이라 하더라도 Base주소가 변경되는 경우가 빈번히 발생합니다.
 

- 디버깅시 메모리에 로드된 모듈의 Base주소가 0x00400000라면 위의 파란 박스 안에 있는 Rva+Base 주소가 해당 함수의 주소가 됩니다.

- 만약 메모리에 로드된 모듈의 Base주소가 변경되었다면 다음과 같이 계산하시면 됩니다.

DummyFunction_A() Address

= 0x00401000(Rva+Base) – 0x00400000(Preferred load Address) + Module Base주소

 

그러면 실제로 map파일에서 추출한 함수 주소와 실제 메모리에 로드된 모듈의 함수주소가 같은지 확인 해 보겠습니다.
 

n  메모리에 로드된 후 함수&전역변수의 실제 Address

 

 

n Mapfile을 통한 함수,전역변수의 Address계산

DummyFunction_A() = 0x00401000 – 0x00400000 + 0x01230000 = 0x1231000

DummyFunction_B() = 0x00401020 – 0x00400000 + 0x01230000 = 0x1231020

g_dwDummy = 0x00403374 – 0x00400000 + 0x01230000 = 0x1233374


보시는 것과 같이 map파일을 통해 계산한 값과 메모리에 로드된 후의 Address가 일치함을 알 수 있습니다.

 

* 함수 DummyFunction_A()함수가 ?DummyFunction_A@@YAXXZ 로 변경되는 이유가 궁금하신 분은 아래의 링크를 참고하십시오
2008/10/07 - [C/C++] - Name Mangling(Name Decoration)

반응형

'C++' 카테고리의 다른 글

Cross Compile - Predefined Macros for OS  (0) 2020.06.18
fprintf(),fwprintf()로 한글이 출력되지 않는 문제  (0) 2011.08.11
Format Specification  (0) 2011.04.20
std::map  (0) 2009.09.03
std::vector  (0) 2009.08.26
반응형

ApplicationXP(Vista) Style의 테마 적용하기

 

XP 이후의 OS에서는 공용 컨트롤들이 좀더 예쁘장한 모습으로 나타납니다.

[ Windows 2000이전 공용 컨트롤들의 모습]

 

[ Windows XP이후 공용 컨트롤들의 모습]

 

 

 

 

내가 만들 Application에도 좀더 세련된 모양의 공용 컨트롤을 사용하려면 아래와 같이 작업하시면 됩니다.

 

n  VC 6.0

1. 아래와 같은 메니페스트 파일을 작성합니다.

MyApp.exe.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

 

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

             <assemblyIdentity version="5.1.0.0"

             processorArchitecture="x86"

             type="win32"

             name="MyApp.exe"/>

 

             <description> MyApp Application</description>

             <dependency>

                           <dependentAssembly>

                                        <assemblyIdentity

                           type="win32"

                           name="Microsoft.Windows.Common-Controls"

                           version="6.0.0.0"

                           publicKeyToken="6595b64144ccf1df"

                           language="*"

                           processorArchitecture="x86"/>

                           </dependentAssembly>

             </dependency>

</assembly>

 

2. resource.h파일에 MANIFEST_RESOURCE_ID를 정의 합니다.

resource.h

#define MANIFEST_RESOURCE_ID 1

 

3. rc파일에 리소스를 추가합니다.

MyApp.rc

/////////////////////////////////////////////////////////////////////////////

//

// 24

//

 

MANIFEST_RESOURCE_ID 24 MOVEABLE PURE " MyApp.exe.manifest"

 

n  VC 2003 이상

ü  위에서 작성된 manifest파일을 [ 프로젝트> 속성 > 구성속성> 메니페스트 도구> 입력 및 출력>추가 메니페스트 파일 ] 항목에 추가한 후 빌드합니다.


ü  혹은 아래의 문구를 stdAfx.h등의 헤더 파일에 추가 한 후 빌드합니다.

( 이 부분은 MFC 프로젝트의 경우, stdafx.h에 자동으로 추가되는 구분이며, #ifdef _UNICODE 로 감싸져 있어, Unicode프로젝트에는 자동으로 적용되는 부분입니다. )

X86

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")

X64

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")

 

 

 

 

반응형
반응형

StackFrame구성 - Stack Overflow

 

CallStack에 대한 이해를 돕고자 간단한 Quiz로 포스팅을 시작하겠습니다.

아래 와 같은 코드가 있습니다.

void Dummy()

{

           printf("In Dummy Function()\n");

 

           exit(0);

}

 

void SomFunction()

{

           BYTE Buf[4];

 

           printf("In SomFunction()\n");

            

           return ;

}

 

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

{

           printf("Before call SomFunction()\n");

 

           SomFunction();

          

           printf("After call SomFunction()\n");

          

           return 0;

}

 

asm 코드를 쓰지 않고 SomFunction()을 수정하여 아래와 같은 결과를 출력한 후, 프로그램이 종료되도록 수정할 수 있을까요?

 

. 감이 오지 않는 분들은 아래의 글을 먼저 읽고 오시기 바랍니다.

[디버깅을 위한 기초지식 #3] CallStack - 프로시저 호출에 따른 스택의 구성

 

이제 어느 정도 방향을 잡으셨나요?

 

아래와 같은 방법을 사용하면 위의 문제를 해결할 수 있을 것 같습니다.

1.     Return Address가 저장되어 있는 Stack상의 Address를 구한다.

A.     asm 코드를 사용하지 않으려면, 해당 주소를 구하기 위해 로컬변수 Buf address를 통해 구해야 할 것 같습니다.

2.     1에서 구한 Address Dummy() 함수의 Address Overwrite하게 되면, SomeFunction이 모든 처리를 마치고 리턴할 때 Dummy()가 실행되게 됩니다..

생각보다 복잡하지는 않군요.

 

그럼 한단계씩 따라가 보겠습니다.

1.     SomeFunction이 복귀할 ReturnAddress가 저장된 Stack상의 주소 구하기

A.     스택 구성에 대한 링크된 포스트의 그림에 따르면 첫번째 로컬 변수의 위치는 ebp-0x4이므로, szBuf의 주소+0x4(szBuf사이즈) ebp의 주소가 됩니다.

B.     Rerturn Address의 주소는 ebp+0x4이므로, [ Buf+0x4/*ebp*/+4/*ebp+4*/ ]로 계산이 되겠습니다.

void SomFunction()

{

           BYTE Buf[8];

           DWORD *pDw = (DWORD *)(Buf+0x8/*ebp*/+4/*ebp+4*/);

 

           *pDw = (DWORD)Dummy;

 

           printf("In SomFunction()\n");

            

           return ;

}


 

2. 그럼 이제 구해진 주소에 Dummy()함수의 주소를 write해주기만 하면 되겠군요

*pDw = (DWORD)Dummy;



혹시 위의 코드를 기반으로 혹은 코드를 작성해서 따라해 보신분…?

머야? 안돼잖아~ 하신분도 있으리라 생각됩니다.

 

저도 테스트를 하다 보니 CallStack내에서의 첫번째 로컬 변수의 주소가 항상 ebp – 0x4의 주소에 위치하지는 않더군요.

 

위의 테스트 코드는 아래의 환경하에서 정상 동작했습니다.

n  VC++ 2008, Release모드, optimize off

 

n  Optimize(최적화)옵션을 켜게 되면, SomFunction()함수의 코드가 wmain()함수 안에 삽입되어 버리거나, stack frame이 생략되는 등 실제 작성된 코드와는 많은 부분이 달라질 수 있습니다.
실제로 아래의 코드는 [ release mode: 최적화-속도 최대화 ]를 설정하여 컴파일한 코드로 SomFunction()의 코드가 wmain()함수 안쪽에 박혀(?)있습니다.


 

n  또한 링크된 포스트의 그림에서 설명한 대로라면 SomeFunction()안의 szBuf변수의 사이즈를 8로 잡을 경우, 첫 번째 로컬변수의 주소가 ebp-0x8로 할당될것으로 생각했으나, 실제로는  ebp-0xc위치로 할당되었습니다.(어떠한 다른 규칙이 있는 것인지 제가 잘못 이해한것인지? 답을 아시는 분은 좀 알려주세요~)


 

별 활용성은 없는 코드이 겠으나, 위의 내용을 완벽히 이해하시면 CallStack BackTrace라던지 함수 호출 흐름 분석에 꽤 도움이 되지 않을까 생각합니다.


반응형
반응형

[MFC] Templete에 설정된 각 클래스 접근(MDI)

 

[CWinApp]

CTestApp *pApp = (CTestApp *)AfxGetApp();

 

[CMainFrame]

CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();

 

[CChildFrame]

CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();

 

[CDocument]

CTestDoc *pDoc = (CTestDoc *)pChild->GetActiveDocument();

 

[CView]

CTestView *pView = (CTestView *)pChild->GetActiveView();

 

 

반응형
반응형

[MFC] Templete에 설정된 각 클래스 접근(SDI)

 

[CWinApp]

CTestApp *pApp = (CTestApp *)AfxGetApp();

 

[CMainFrame]

CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();


[CView]

CTestView *pView = (CTestView *)pFrame->GetActiveView();

 

[CDocument]

CTestDoc *pDoc = (CTestDoc *)pFrame->GetActiveDocument();

 


반응형

+ Recent posts