성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[tree soap] 아차! f는 기억이 나는데, m은 ㅜㅜ 감사합니다!!! ^...
[정성태] 'm'은 decimal 타입의 숫자에 붙는 접미사입니다. ...
[정성태] https://lxr.sourceforge.io/ http...
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
글쓰기
제목
이름
암호
전자우편
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'>CorElementType의 요소 값 설명</h1> <p> CorElementType은 enum 형식으로 다음의 문서에 기본적인 설명이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > CorElementType Enumeration ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/corelementtype-enumeration'>https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/corelementtype-enumeration</a> </pre> <br /> 기본적인 타입들은 이렇게 매핑됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ELEMENT_TYPE_VOID: "System.Void" ELEMENT_TYPE_BOOLEAN: "System.Boolean" ELEMENT_TYPE_I1: "System.SByte" ELEMENT_TYPE_U1: "System.Byte" ELEMENT_TYPE_I2: "System.Int16" ELEMENT_TYPE_U2: "System.UInt16" ELEMENT_TYPE_CHAR: "System.Char" ELEMENT_TYPE_I4: "System.Int32" ELEMENT_TYPE_U4: "System.UInt32" ELEMENT_TYPE_I8: "System.Int64" ELEMENT_TYPE_U8: "System.UInt64" ELEMENT_TYPE_R4: "System.Single" ELEMENT_TYPE_R8: "System.Double" ELEMENT_TYPE_OBJECT: "System.Object" ELEMENT_TYPE_STRING: "System.String" ELEMENT_TYPE_I: "System.IntPtr" ELEMENT_TYPE_U: "System.UIntPtr" ELEMENT_TYPE_SZARRAY: 1차원 배열 Type [] ELEMENT_TYPE_ARRAY: 다차원 배열 Type [,] </pre> <br /> 이제 그 외의 것을 좀 더 자세하게 알아보겠습니다. 우선 ELEMENT_TYPE_VAR, ELEMENT_TYPE_MVAR인데요. 전자는 타입(class,struct)에 사용된 generic을 의미하고, 후자는 메서드에 사용된 generic입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ELEMENT_TYPE_VAR: class<T> (generic class) ELEMENT_TYPE_MVAR: void Method<T>(T obj); (generic method) </pre> <br /> 관련해서 ELEMENT_TYPE_GENERICINST도 있는데요. 이것은 제네릭 인자를 포함하는 타입인 경우에 해당합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ELEMENT_TYPE_GENERICINST: void Method(<span style='color: blue; font-weight: bold'>List<int></span>); </pre> <br /> 닷넷의 IL 코드를 심도 있게 공부하다 보면, 왜 <a target='tab' href='http://www.sysnet.pe.kr/2/0/1581'>자바에서 generic을 단순히 object로 처리</a>했는지를 조금이나마 이해하게 됩니다. (닷넷도 generic을 object로 구현했다면 IL 코드가 더 간단해졌을 거라는 의미입니다.)<br /> <br /> 그리고, 값 형식과 참조 형식을 나누는 요소가 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ELEMENT_TYPE_VALUETYPE: 값 형식 ELEMENT_TYPE_CLASS: 참조 형식 </pre> <br /> 더 설명할 필요가 없겠죠? ^^<br /> <br /> ELEMENT_TYPE_BYREF 값은 좀 재미있습니다. 이것은 out, ref C# 키워드가 사용되었을 때 지정됩니다. 이것을 달리 말하면? C#은 그 자체 내의 문법에서 out, ref를 구분하는 것일 뿐 IL 코드 입장에서 보면 동일하게 ELEMENT_TYPE_BYREF으로 취급된다는 점입니다.<br /> <br /> 또한, ELEMENT_TYPE_PTR 값은 unsafe 구문에서 포인터를 다루는 경우 사용됩니다.<br /> <br /> 일단, 여기까지는 그런대로 쉽게 이해할 수 있는 요소들인데!<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이 부분부터는 주로 C++/CLI로 인해 도입된 것인데 C# 등의 언어로 프로그램할 때는 볼 수 없습니다. 우선, 다음의 값을 볼까요?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ELEMENT_TYPE_CMOD_REQD: C language required modifier. ELEMENT_TYPE_CMOD_OPT: C language optional modifier. </pre> <br /> 이 2개의 값이 잘 설명된 문서는, 14년 동안 "C++ At Work" 컬럼을 담당했던 Paul DiLascia의 마지막 글입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Rationales, Highlights, and a Farewell (C++/CLI의 설계 원리와 발전 과정) ; <a target='tab' href='https://learn.microsoft.com/en-us/archive/msdn-magazine/2007/february/c-at-work-rationales-highlights-and-a-farewell'>https://learn.microsoft.com/en-us/archive/msdn-magazine/2007/february/c-at-work-rationales-highlights-and-a-farewell</a> (영문) ; <span style='text-decoration: line-through'><a target='tab' href='https://learn.microsoft.com/ko-kr/archive/msdn-magazine/2007/february/c-at-work-rationales-highlights-and-a-farewell'>https://learn.microsoft.com/ko-kr/archive/msdn-magazine/2007/february/c-at-work-rationales-highlights-and-a-farewell</span> </pre> <br /> <a name='modreq'></a> 우선, ELEMENT_TYPE_CMOD_OPT 옵션은 .NET Reflector 등의 툴로 보면 modopt 선언자로 표현되는데, 이 옵션이 사용된 구문을 호출 측에서 알지 못해도 전체적인 실행 방식에는 영향이 없을 때 사용하는 것입니다. (여기서 '호출 측'이라는 것은 엄밀히 닷넷 기반의 '언어 개발자'가 해당할 것입니다.)<br /> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> Modopt (optional modifier) is an MSIL declarator that says to CLI consumers: if you understand what this thing is, great; if not, you can safely ignore it.<br /> </div><br /> <br /> "<a target='tab' href='https://learn.microsoft.com/en-us/archive/msdn-magazine/2007/february/c-at-work-rationales-highlights-and-a-farewell'>Rationales, Highlights, and a Farewell</a>" 글에서는 modopt의 사례로 C++/CLI의 const 예약어가 사용된 구문을 보여줍니다. 즉, 아래의 g_private 변수는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // C++/CLI ref class A { static const int g_private = 1; }; </pre> <a name='mod'></a> <br /> 컴파일 후 C++의 const 예약어가 사용되었음을 호출 측에 힌트를 줄 수 있도록 다음과 같은 IL 코드로 변환됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > field public static int32 <span style='color: blue; font-weight: bold'>modopt([mscorlib]System.Runtime.CompilerServices.IsConst)</span> g_private = int32(0x00000001) </pre> <br /> 반면, ELEMENT_TYPE_CMOD_REQD는 modreq로 표현되고,<br /> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> modreq (required modifier) says: if you don't understand this thing, you can't use this function. Volatile is an example of a modreq.<br /> </div><br /> <br /> 반드시 호출 측에서 이에 대한 의미를 알아야만 사용할 수 있음을 의미합니다. 일례로 volatile 예약어가 지정된 사례를 들고 있습니다.<br /> <br /> 아울러, "<a target='tab' href='https://learn.microsoft.com/en-us/archive/msdn-magazine/2007/february/c-at-work-rationales-highlights-and-a-farewell'>Rationales, Highlights, and a Farewell</a>" 글에서 왜 C++/CLI에서 const 함수가 문법적으로 허용되지 않는지를 설명하고 있는데요. 왜냐하면 CLI는 이 2개의 modifier가 함수에 적용되는 것은 허용하지 않기 때문입니다. (즉, 필드나 함수의 인자에만 적용할 수 있습니다.)<br /> <br /> <a target='tab' href='http://en.wikipedia.org/wiki/Common_Intermediate_Language'>modopt가 사용되는 또 다른 예제를 wikipedia에 포함된 코드</a>에서 볼 수 있는데, 다음과 같이 C++/CLI로 정의된 전역 함수의 경우 기본 C++ calling convention에 따라 Cdecl을 따르고, <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class A { // public: virtual void __stdcall meth() { } }; <span style='color: blue; font-weight: bold'>void test_pointer_operations(int param) { }</span> </pre> <br /> 이를 IL 코드로 컴파일된 후에 살펴보면 Cdecl 호출 관례 정보가 modopt를 이용해 기록된 것을 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > .method assembly static void <span style='color: blue; font-weight: bold'>modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)</span> test_pointer_operations(int32 param) cil managed </pre> <br /> 그 외에, 우리가 너무나 많이 사용하고 있는 System.Data.dll 어셈블리에도 SNINativeMethodWrapper 타입에 MarshalConsumerInfo 메서드의 signature에 modopt가 있는 것을 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // Declaring Type: SNINativeMethodWrapper // Assembly: System.Data, Version=4.0.0.0 [ResourceExposure(ResourceScope.None)] private static unsafe void MarshalConsumerInfo(ConsumerInfo consumerInfo, Sni_Consumer_Info* <span style='color: blue; font-weight: bold'>modopt</span>(IsImplicitlyDereferenced) native_consumerInfo) { // ...[생략]... // 심지어 형변환 코드에도 사용됩니다. native_consumerInfo[0] = (Sni_Consumer_Info* <span style='color: blue; font-weight: bold'>modopt</span>(IsImplicitlyDereferenced)) consumerInfo.defaultBufferSize; // ...[생략]... } </pre> <br /> <span style='text-decoration: line-through'>그런데, 여기서 제가 한 가지 풀지 못한 것이 있습니다. 보면 "IsImplicitlyDereferenced"라는 타입이 modopt에 부가적인 값으로 전달되고 있는데 이에 대한 정보를 메서드의 SIGNATURE 값에서는 찾을 수 없었습니다. (MarshalConsumerInfo 메서드의 signature 분석은 아래에서 나옵니다.)</span> <br /> <hr style='width: 50%' /><br /> <br /> <span style='text-decoration: line-through'>그다음, ELEMENT_TYPE_MODIFIER에 대해 알아보겠습니다. 이것은 단독으로 정의되는 경우는 없고 ELEMENT_TYPE_PINNED, ELEMENT_TYPE_SENTINEL과 OR(|)연산자로 함께 사용됩니다. <br /> 이것이 사용된 사례를 위에서 이미 소개한 SNINativeMethodWrapper.MarshalConsumerInfo 메서드의 signature에서 볼 수 있습니다. </span><br /> <br /> ildasm.exe를 이용해 <a target='tab' href='https://www.sysnet.pe.kr/2/0/12379'>signature를 보면 "SIG: 00 02 01 12 20 20 45 0f 11 30" 값이 나오는데, 이를 분석</a>하면 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00: static 02: 2개의 인자 01: (return type) void 12: ELEMENT_TYPE_CLASS 20: ConsumerInfo type (class type token - compressed) 20: ELEMENT_TYPE_CMOD_OPT 45: IsImplicitlyDereferenced type (class type token - compressed) 0f: ELEMENT_TYPE_PTR 11: ELEMENT_TYPE_VALUETYPE 30: Sni_Consumer_Info (value type token - compressed) 타입 ConsumerInfo: 0x08 --> compressed로 바꾸면 0x20 타입 Sni_ConsumerInfo: 0x0C --> compressed로 바꾸면 0x30 </pre> <br /> 위에서 ConsumerInfo와 같은 타입 토큰의 경우 compressed 유형으로 0x20인데, 이를 unpack 시키면 0x02000008(mdTypeDef == 0x02000000)값이 나옵니다. 실제로 <a target='tab' href='http://www.ntcore.com/exsuite.php'>CFF Explorer</a> 같은 도구를 이용해 메타데이터 테이블의 TypeDef 영역을 조사해 보면 이렇게 8번 인덱스 위치에 ConsumerInfo 타입값이 정의된 것을 볼 수 있습니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='element_type_1.png' src='/SysWebRes/bbs/element_type_1.png' /><br /> <br /> 본론으로 돌아와서 ELEMENT_TYPE_MODIFIER | ELEMENT_TYPE_PINNED 값이 사용되고 있는데 관련 설명을 찾아보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Processing the XML File ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/processing-the-xml-file'>https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/processing-the-xml-file</a> </pre> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> ELEMENT_TYPE_PINNED is represented as a '^' following the modified type. The C# compiler never generates this.<br /> </div><br /> <br /> 역시 C# 컴파일러로 인해 생성되는 일은 없고 C++/CLI의 "^" 연산자가 사용되는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Hashtable^ hash = gcnew Hashtable(); </pre> <br /> 이런 유형의 인자 타입을 받는 경우에 ELEMENT_TYPE_PINNED 값이 지정되는 것입니다. 참고로 다음과 같은 부가적인 자료도 나오는 군요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='text-decoration: line-through'>PRB: A pinning pointer passed to variable-argument function causes System.BadImageFormatException ; <a target='tab' href='http://support.microsoft.com/kb/959389'>http://support.microsoft.com/kb/959389</a></span> </pre> <br /> 마지막으로 남은 2가지 요소는 짧은 설명으로 대신합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ELEMENT_TYPE_TYPEDBYREF: A typed reference. (System.TypedReference) ELEMENT_TYPE_SENTINEL: A type modifier that is a sentinel for a list of a variable number of parameters. </pre> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=914&boardid=331301885'>첨부한 파일은 compressed token값을 알아내는 소스코드를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1801
(왼쪽의 숫자를 입력해야 합니다.)