성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>coreclr 소스코드로 알아보는 .NET 4.0의 모듈 로딩 함수</h1> <p> (그냥 기록 차원에서 남겨둡니다. ^^)<br /> <br /> .NET 4.0 이후부터 DLL을 LoadLibrary로 로딩하지 않는다고 했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > CLR 4.0 환경에서 DLL 모듈의 로드 주소(Base address) 알아내는 방법 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11325'>http://www.sysnet.pe.kr/2/0/11325</a> </pre> <br /> 정말 그럴까요? ^^ 이를 알아보기 위해 coreclr 소스 코드를 이용해 추적해 봤습니다.<br /> <br /> 우선 단서는 GetHINSTANCE를 역어셈블한 코드에서 시작했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [SecurityCritical] public static IntPtr GetHINSTANCE(Module m) { if (m == null) { throw new ArgumentNullException("m"); } RuntimeModule internalModule = m as RuntimeModule; // ...[생략]... return <span style='color: blue; font-weight: bold'>GetHINSTANCE</span>(internalModule.GetNativeHandle()); } [SecurityCritical, SuppressUnmanagedCodeSecurity, SuppressUnmanagedCodeSecurity, <span style='color: blue; font-weight: bold'>DllImport("QCall", CharSet=CharSet.Unicode)</span>] <span style='color: blue; font-weight: bold'>private static extern IntPtr GetHINSTANCE(RuntimeModule m);</span> </pre> <br /> 이제부터 coreclr 소스 코드 안으로 들어갑니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/46ab1d132c9ad471d79afa20c188c2f9c85e5f20/src/vm/commodule.cpp'>https://github.com/dotnet/coreclr/blob/46ab1d132c9ad471d79afa20c188c2f9c85e5f20/src/vm/commodule.cpp</a> // coreclr / src / vm / commodule.cpp HINSTANCE QCALLTYPE COMModule::<span style='color: blue; font-weight: bold'>GetHINSTANCE</span>(QCall::ModuleHandle pModule) { // ...[생략]... <span style='color: blue; font-weight: bold'>PEFile *pPEFile = pModule->GetFile(); </span> if (!pPEFile->IsDynamic() && !pPEFile->IsResource()) { hMod = (HMODULE) pModule->GetFile()-><span style='color: blue; font-weight: bold'>GetManagedFileContents</span>(); } // ...[생략]... return (HINSTANCE)hMod; } </pre> <br /> 보는 바와 같이 PEFile 인스턴스의 GetManagedFileContents 함수의 반환 결과로 나옵니다. 그렇다면 DLL은 PEFile에 의해 관리되는 것으로 짐작됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/13e7c4368da664a8b50228b1a5ef01a660fbb2dd/src/vm/pefile.inl'>https://github.com/dotnet/coreclr/blob/13e7c4368da664a8b50228b1a5ef01a660fbb2dd/src/vm/pefile.inl</a> // coreclr / src / vm / pefile.inl #ifndef DACCESS_COMPILE inline const void *PEFile::<span style='color: blue; font-weight: bold'>GetManagedFileContents</span>(COUNT_T *pSize/*=NULL*/) { // ...[생략]... <span style='color: blue; font-weight: bold'>LoadLibrary(FALSE); </span> // ...[생략]... RETURN GetLoadedIL()->GetBase(); } inline PTR_PEImageLayout PEFile::GetLoadedIL() { // ...[생략]... return GetOpenedILimage()->GetLoadedLayout(); }; </pre> <br /> LoadLibrary가 눈에 띄는군요. 얼핏 Win32 API의 LoadLibrary가 호출된다고 생각할 수 있지만 유사한 역할을 하는 것에 불과합니다. LoadLibrary의 선언과 정의를 추적해 들어가면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/13e7c4368da664a8b50228b1a5ef01a660fbb2dd/src/vm/pefile.h'>https://github.com/dotnet/coreclr/blob/13e7c4368da664a8b50228b1a5ef01a660fbb2dd/src/vm/pefile.h</a> // coreclr / src / vm / pefile.h class PEFile { // ...[생략]... static PEFile *Open(PEImage *image); PTR_PEImage m_identity; <span style='color: blue; font-weight: bold'>void LoadLibrary(BOOL allowNativeSkip = TRUE);</span> PTR_PEImage GetILimage() { // ...[생략]... #ifndef DACCESS_COMPILE if (m_openedILimage == NULL && m_identity != NULL) { PEImage* pOpenedILimage; m_identity->Clone(MDInternalImport_Default,&pOpenedILimage); if (InterlockedCompareExchangeT(&m_openedILimage,pOpenedILimage,NULL) != NULL) pOpenedILimage->Release(); } #endif return m_openedILimage; } PEImage *GetOpenedILimage() { // ...[생략]... return m_openedILimage; } // ...[생략]... }; </pre> <br /> LoadLibrary의 정의는 아래의 pefile.cpp에서 찾아볼 수 있는 데 결국 pefile.h에 정의된 GetILimage 함수를 다시 호출합니다. 따라서 GetILimage 함수의 내용에 따라 결국 이미 저장되어 있던 PTR_PEImage 타입의 m_identity에 DLL 정보가 관리됩니다. m_identity는 다시 아래의 pefile.cpp에 정의된 PEFile 생성자에서 할당되는데, 다시 PEFile 생성자가 호출되는 곳은 PEFile::Open static 함수입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/46ab1d132c9ad471d79afa20c188c2f9c85e5f20/src/vm/pefile.cpp'>https://github.com/dotnet/coreclr/blob/46ab1d132c9ad471d79afa20c188c2f9c85e5f20/src/vm/pefile.cpp</a> // coreclr/src/vm/pefile.cpp void PEFile::<span style='color: blue; font-weight: bold'>LoadLibrary</span>(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==FALSE force IL image load { // ...[생략]... if (<span style='color: blue; font-weight: bold'>GetILimage()</span>->IsFile()) { #ifdef PLATFORM_UNIX if (GetILimage()->IsILOnly()) { <span style='color: blue; font-weight: bold'>GetILimage()</span>->Load(); } else #endif // PLATFORM_UNIX { <span style='color: blue; font-weight: bold'>GetILimage()</span>->LoadFromMapped(); } } else { GetILimage()->LoadNoFile(); } // ...[생략]... } PEFile::PEFile(<span style='color: blue; font-weight: bold'>PEImage *identity</span>, BOOL fCheckAuthenticodeSignature/*=TRUE*/) : // ...[생략]... { // ...[생략]... if (identity) { identity->AddRef(); <span style='color: blue; font-weight: bold'>m_identity = identity; </span> if(identity->IsOpened()) { //already opened, prepopulate identity->AddRef(); <span style='color: blue; font-weight: bold'>m_openedILimage = identity;</span> } } // ...[생략]... } PEFile *PEFile::Open(<span style='color: blue; font-weight: bold'>PEImage *image</span>) { // ...[생략]... <span style='color: blue; font-weight: bold'>PEFile *pFile = new PEFile(image, FALSE); </span> // ...[생략]... RETURN pFile; } </pre> <br /> 그렇다면, 다시 DLL에 대한 관리가 내부적으로는 PEImage에서 된다는 것을 짐작게 합니다. 그래서 이번에는 PEImage 인스턴스의 생성을 찾아봤습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/ef8d1522eb15cb0371f31a9392891c942547a91f/src/vm/coreassemblyspec.cpp'>https://github.com/dotnet/coreclr/blob/ef8d1522eb15cb0371f31a9392891c942547a91f/src/vm/coreassemblyspec.cpp</a> // src / vm / coreassemblyspec.cpp // 이 함수 외에도 coreclr / src / vm / compile.cpp 경로의 CEECompileInfo::LoadAssemblyByPath 함수에서도 PEImage::OpenImage를 사용 STDAPI BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage **ppPEImage, PEImage **ppNativeImage, BOOL fExplicitBindToNativeImage) { // ...[생략]... EX_TRY { <span style='color: blue; font-weight: bold'>PEImageHolder pImage</span> = NULL; PEImageHolder pNativeImage = NULL; // ...[생략]... { <span style='color: blue; font-weight: bold'>pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default);</span> // Make sure that the IL image can be opened if the native image is not available. hr=<span style='color: blue; font-weight: bold'>pImage->TryOpenFile()</span>; // ...[생략]... } if (pImage) *ppPEImage = pImage.Extract(); // ...[생략]... } // ...[생략]... } </pre> <br /> 그런데, PEImageHolder는 뭘까요? 이에 대한 힌트는 peimage.h에서 찾을 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/31b5ee0bc7df328fd9187d25dbadebe7c1623d38/src/vm/peimage.h'>https://github.com/dotnet/coreclr/blob/31b5ee0bc7df328fd9187d25dbadebe7c1623d38/src/vm/peimage.h</a> // coreclr / src / vm / peimage.h class PEImage { PTR_PEImageLayout m_pLayouts[IMAGE_COUNT]; // ...[생략]... void Init(LPCWSTR pPath); // ...[생략]... }; FORCEINLINE void PEImageRelease(PEImage *i) { WRAPPER_NO_CONTRACT; i->Release(); } <span style='color: blue; font-weight: bold'>typedef Wrapper<PEImage *, DoNothing, PEImageRelease> PEImageHolder;</span> </pre> <br /> 하지만 본론으로 돌아와서 ^^ PEImage::OpenImage의 코드를 보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/ef8d1522eb15cb0371f31a9392891c942547a91f/src/vm/peimage.inl'>https://github.com/dotnet/coreclr/blob/ef8d1522eb15cb0371f31a9392891c942547a91f/src/vm/peimage.inl</a> // coreclr / src / vm / peimage.inl inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags /* = MDInternalImport_Default */) { // ...[생략]... <span style='color: blue; font-weight: bold'>PEImageHolder pImage(new PEImage);</span> <span style='color: blue; font-weight: bold'>pImage->Init(pPath);</span> return dac_cast<PTR_PEImage>(pImage.Extract()); // ...[생략]... } inline void PEImage::Init(LPCWSTR pPath) { // ...[생략]... m_path = pPath; m_path.Normalize(); SetModuleFileNameHintForDAC(); } inline PTR_PEImageLayout PEImage::GetLoadedLayout() { // ...[생략]... return m_pLayouts[IMAGE_LOADED]; //no addref } </pre> <br /> new PEImage와 함께 Init 메서드를 호출하지만 PEImage::Init은 별다르게 로딩 코드가 없습니다. 다시 BinderAcquirePEImage 함수로 가면 pImage 인스턴스에 대해 TryOpenFile을 호출하는데 아마도 여기서 로딩할 것으로 짐작됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/31b5ee0bc7df328fd9187d25dbadebe7c1623d38/src/vm/peimage.cpp'>https://github.com/dotnet/coreclr/blob/31b5ee0bc7df328fd9187d25dbadebe7c1623d38/src/vm/peimage.cpp</a> // coreclr / src / vm / peimage.cpp HRESULT PEImage::TryOpenFile() { // ...[생략]... if (m_hFile!=INVALID_HANDLE_VALUE) return S_OK; { ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); m_hFile=<span style='color: blue; font-weight: bold'>WszCreateFile</span>((LPCWSTR) m_path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } // ...[생략]... } PTR_PEImage PEImage::LoadImage(HMODULE hMod) { // ...[생략]... StackSString path; GetPathFromDll(hMod, path); PEImageHolder pImage(PEImage::OpenImage(path,(MDInternalImportFlags)(MDInternalImport_CheckLongPath|MDInternalImport_CheckShortPath))); if (pImage->HasLoadedLayout()) RETURN dac_cast<PTR_PEImage>(pImage.Extract()); SimpleWriteLockHolder lock(pImage->m_pLayoutLock); if(pImage->m_pLayouts[IMAGE_LOADED]==NULL) pImage->SetLayout(IMAGE_LOADED,PEImageLayout::CreateFromHMODULE(hMod,pImage,WszGetModuleHandle(NULL)!=hMod)); // ...[생략]... RETURN dac_cast<PTR_PEImage>(pImage.Extract()); } </pre> <br /> WszCreateFile은 결국 내부적으로 CreateFileW를 호출하게 됩니다. 확인 끝났군요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/c440335be80ee0762856d0be6e91ec3ea2f90504/src/inc/winwrap.h'>https://github.com/dotnet/coreclr/blob/c440335be80ee0762856d0be6e91ec3ea2f90504/src/inc/winwrap.h</a> // coreclr / src / inc / winwrap.h #define WszCreateFile CreateFileWrapper // <a target='tab' href='https://github.com/dotnet/coreclr/blob/52a816d3011f4d03b80b5940dc036b40d701f52d/src/utilcode/longfilepathwrappers.cpp'>https://github.com/dotnet/coreclr/blob/52a816d3011f4d03b80b5940dc036b40d701f52d/src/utilcode/longfilepathwrappers.cpp</a> // coreclr / src / utilcode / longfilepathwrappers.cpp HANDLE CreateFileWrapper( _In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile ) { // ...[생략]... ret = CreateFileW(path.GetUnicode(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); // ...[생략]... return ret; } </pre> <br /> <hr style='width: 50%' /><br /> <br /> 중간에 잠시 살펴봤던 PEImageHolder에 대해 살펴보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > typedef Wrapper<PEImage *, DoNothing, PEImageRelease> PEImageHolder; </pre> <br /> Wrapper는 단순히 PEImageRelease 인자로 객체 해제 방법을 아는 스마트 포인터 관리 클래스의 일종이라고 보시면 됩니다. 나머지 정의는 다음의 파일에서 각각 찾을 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/0ad57d9177ac88aabbf9354b985c5ac192a307e7/src/inc/holder.h'>https://github.com/dotnet/coreclr/blob/0ad57d9177ac88aabbf9354b985c5ac192a307e7/src/inc/holder.h</a> template <typename TYPE, typename BASE, UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault<TYPE>, HolderStackValidation VALIDATION_TYPE = HSV_ValidateNormalStackReq> <span style='color: blue; font-weight: bold'>class BaseWrapper : public BaseHolder</span><TYPE, BASE, DEFAULTVALUE, IS_NULL, VALIDATION_TYPE> { // ...[생략]... }; template < typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE), UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault<TYPE>, HolderStackValidation VALIDATION_TYPE = HSV_ValidateNormalStackReq, // For legacy compat (see EEJitManager::WriterLockHolder), where default ctor // causes ACQUIREF(DEFAULTVALUE), but ACQUIREF ignores the argument and // operates on static or global value instead. bool DEFAULT_CTOR_ACQUIRE = true > <span style='color: blue; font-weight: bold'>class Wrapper : public BaseWrapper</span><TYPE, FunctionBase<TYPE, ACQUIREF, RELEASEF, VALIDATION_TYPE>, DEFAULTVALUE, IS_NULL, VALIDATION_TYPE> { typedef BaseWrapper<TYPE, FunctionBase<TYPE, ACQUIREF, RELEASEF, VALIDATION_TYPE>, DEFAULTVALUE, IS_NULL, VALIDATION_TYPE> BaseT; // ...[생략]... }; // Wrapper<> template < typename TYPE, typename BASE, UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault<TYPE>, HolderStackValidation VALIDATION_TYPE = HSV_ValidateNormalStackReq > <span style='color: blue; font-weight: bold'>class BaseHolder : protected BASE</span> { // ...[생략]... FORCEINLINE TYPE Extract() { STATIC_CONTRACT_WRAPPER; SuppressRelease(); return GetValue(); } FORCEINLINE TYPE GetValue() { STATIC_CONTRACT_LEAF; return this->m_value; } }; </pre> <br /> <hr style='width: 50%' /><br /> <br /> 알아본 김에 모듈의 로딩 주소를 반환하는 과정에서 GetLoadedIL()이 반환하는 PEImage의 GetLoadedLayout 함수의 layout 관련 코드도 살펴봤습니다. 우선 상속 구조는 이렇고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/0a8bd5554a736de337ca6c24eba3de3ec0decfd1/src/vm/peimagelayout.h'>https://github.com/dotnet/coreclr/blob/0a8bd5554a736de337ca6c24eba3de3ec0decfd1/src/vm/peimagelayout.h</a> // coreclr / src / vm / peimagelayout.h class PEImageLayout : public PEDecoder { // ...[생략]... }; class RawImageLayout: public PEImageLayout { // ...[생략]... }; </pre> <br /> CreateFromHMODULE에 의해 HMODULE hModule 값을 생성자에서 받아둡니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/0a8bd5554a736de337ca6c24eba3de3ec0decfd1/src/vm/peimagelayout.cpp'>https://github.com/dotnet/coreclr/blob/0a8bd5554a736de337ca6c24eba3de3ec0decfd1/src/vm/peimagelayout.cpp</a> // coreclr / src / vm / peimagelayout.cpp PEImageLayout* PEImageLayout::CreateFromHMODULE(HMODULE hModule,PEImage* pOwner, BOOL bTakeOwnership) { // ...[생략]... return new RawImageLayout(hModule,pOwner,bTakeOwnership,TRUE); } </pre> <br /> 맨 처음으로 돌아가 load address를 반환하는 GetManagedFileContents 메서드가 결국 PEDecoder의 GetBase를 호출하는데, 구현은 HMODULE hModule 값을 담고 있는 m_base를 반환하는 것에 불과합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // <a target='tab' href='https://github.com/dotnet/coreclr/blob/master/src/inc/pedecoder.h'>https://github.com/dotnet/coreclr/blob/master/src/inc/pedecoder.h</a> // coreclr / src / inc / pedecoder.h // <a target='tab' href='https://github.com/dotnet/coreclr/blob/master/src/inc/pedecoder.inl'>https://github.com/dotnet/coreclr/blob/master/src/inc/pedecoder.inl</a> // coreclr / src / inc / pedecoder.inl inline PTR_VOID PEDecoder::GetBase() const { // ...[생략]... return PTR_VOID(m_base); } inline PEDecoder::PEDecoder(PTR_VOID mappedBase, bool fixedUp /*= FALSE*/) : m_base(dac_cast<TADDR>(mappedBase)), // ...[생략]... { // ...[생략]... } inline void PEDecoder::Init(void *flatBase, COUNT_T size) { // ...[생략]... m_base = (TADDR)flatBase; m_size = size; m_flags = FLAG_CONTENTS; } </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7603
(왼쪽의 숫자를 입력해야 합니다.)