Skip to content

Commit 89631ca

Browse files
committed
peview: Add MVID for CLR images
1 parent ae0de7e commit 89631ca

File tree

4 files changed

+167
-98
lines changed

4 files changed

+167
-98
lines changed

tools/peview/clrprp.c

Lines changed: 157 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,156 @@ typedef struct _STORAGESTREAM
5656
} STORAGESTREAM, *PSTORAGESTREAM;
5757
#include <poppack.h>
5858

59+
PSTORAGESIGNATURE PvpPeGetClrMetaDataHeader(
60+
VOID
61+
)
62+
{
63+
PSTORAGESIGNATURE metaData;
64+
65+
metaData = PhMappedImageRvaToVa(&PvMappedImage, PvImageCor20Header->MetaData.VirtualAddress, NULL);
66+
67+
if (metaData)
68+
{
69+
__try
70+
{
71+
PhProbeAddress(metaData, PvImageCor20Header->MetaData.Size, PvMappedImage.ViewBase, PvMappedImage.Size, 4);
72+
}
73+
__except (EXCEPTION_EXECUTE_HANDLER)
74+
{
75+
metaData = NULL;
76+
}
77+
}
78+
79+
return metaData;
80+
}
81+
82+
PPH_STRING PvpPeGetClrFlagsText(
83+
VOID
84+
)
85+
{
86+
PH_STRING_BUILDER stringBuilder;
87+
88+
PhInitializeStringBuilder(&stringBuilder, 256);
89+
90+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_ILONLY)
91+
PhAppendStringBuilder2(&stringBuilder, L"IL only, ");
92+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_32BITREQUIRED)
93+
PhAppendStringBuilder2(&stringBuilder, L"32-bit only, ");
94+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_32BITPREFERRED)
95+
PhAppendStringBuilder2(&stringBuilder, L"32-bit preferred, ");
96+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_IL_LIBRARY)
97+
PhAppendStringBuilder2(&stringBuilder, L"IL library, ");
98+
99+
if (PvImageCor20Header->StrongNameSignature.VirtualAddress != 0 && PvImageCor20Header->StrongNameSignature.Size != 0)
100+
{
101+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_STRONGNAMESIGNED)
102+
PhAppendStringBuilder2(&stringBuilder, L"Strong-name signed, ");
103+
else
104+
PhAppendStringBuilder2(&stringBuilder, L"Strong-name delay signed, ");
105+
}
106+
107+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT)
108+
PhAppendStringBuilder2(&stringBuilder, L"Native entry-point, ");
109+
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_TRACKDEBUGDATA)
110+
PhAppendStringBuilder2(&stringBuilder, L"Track debug data, ");
111+
112+
if (PhEndsWithString2(stringBuilder.String, L", ", FALSE))
113+
PhRemoveEndStringBuilder(&stringBuilder, 2);
114+
115+
return PhFinalStringBuilderString(&stringBuilder);
116+
}
117+
118+
PPH_STRING PvpPeGetClrVersionText(
119+
VOID
120+
)
121+
{
122+
return PhFormatString(
123+
L"%hu.%hu",
124+
PvImageCor20Header->MajorRuntimeVersion,
125+
PvImageCor20Header->MinorRuntimeVersion
126+
);
127+
}
128+
129+
PPH_STRING PvpPeGetClrStorageVersionText(
130+
_In_ PSTORAGESIGNATURE ClrMetaData
131+
)
132+
{
133+
if (ClrMetaData && ClrMetaData->VersionLength != 0)
134+
{
135+
return PhZeroExtendToUtf16Ex(
136+
PTR_ADD_OFFSET(ClrMetaData, RTL_SIZEOF_THROUGH_FIELD(STORAGESIGNATURE, VersionLength)),
137+
ClrMetaData->VersionLength
138+
);
139+
}
140+
141+
return PhCreateString(L"N/A");
142+
}
143+
144+
PPH_STRING PvpPeClrGetMvid(
145+
_In_ PSTORAGESIGNATURE ClrMetaData
146+
)
147+
{
148+
PPH_STRING guidMvidString = NULL;
149+
PSTORAGEHEADER storageHeader;
150+
PSTORAGESTREAM streamHeader;
151+
USHORT i;
152+
153+
storageHeader = PTR_ADD_OFFSET(ClrMetaData, sizeof(STORAGESIGNATURE) + ClrMetaData->VersionLength);
154+
streamHeader = PTR_ADD_OFFSET(storageHeader, sizeof(STORAGEHEADER));
155+
156+
for (i = 0; i < storageHeader->Streams; i++)
157+
{
158+
if (PhEqualBytesZ(streamHeader->Name, "#GUID", TRUE))
159+
{
160+
guidMvidString = PhFormatGuid(PTR_ADD_OFFSET(ClrMetaData, streamHeader->Offset));
161+
break;
162+
}
163+
164+
streamHeader = PTR_ADD_OFFSET(streamHeader, ALIGN_UP(UFIELD_OFFSET(STORAGESTREAM, Name) + strlen(streamHeader->Name) + 1, ULONG));
165+
}
166+
167+
return guidMvidString;
168+
}
169+
170+
VOID PvpPeClrEnumSections(
171+
_In_ PSTORAGESIGNATURE ClrMetaData,
172+
_In_ HWND ListViewHandle
173+
)
174+
{
175+
PSTORAGEHEADER storageHeader;
176+
PSTORAGESTREAM streamHeader;
177+
USHORT i;
178+
179+
storageHeader = PTR_ADD_OFFSET(ClrMetaData, sizeof(STORAGESIGNATURE) + ClrMetaData->VersionLength);
180+
streamHeader = PTR_ADD_OFFSET(storageHeader, sizeof(STORAGEHEADER));
181+
182+
for (i = 0; i < storageHeader->Streams; i++)
183+
{
184+
INT lvItemIndex;
185+
WCHAR sectionName[65];
186+
WCHAR pointer[PH_PTR_STR_LEN_1];
187+
188+
if (PhCopyStringZFromBytes(
189+
streamHeader->Name,
190+
sizeof(streamHeader->Name),
191+
sectionName,
192+
ARRAYSIZE(sectionName),
193+
NULL
194+
))
195+
{
196+
lvItemIndex = PhAddListViewItem(ListViewHandle, MAXINT, sectionName, NULL);
197+
PhPrintPointer(pointer, UlongToPtr(streamHeader->Offset));
198+
PhSetListViewSubItem(ListViewHandle, lvItemIndex, 1, pointer);
199+
PhSetListViewSubItem(ListViewHandle, lvItemIndex, 2, PhaFormatSize(streamHeader->Size, -1)->Buffer);
200+
}
201+
202+
// Stream headers don't have fixed sizes...
203+
// The size is aligned up based on a variable length string at the end.
204+
streamHeader = PTR_ADD_OFFSET(streamHeader, ALIGN_UP(UFIELD_OFFSET(STORAGESTREAM, Name) + strlen(streamHeader->Name) + 1, ULONG));
205+
}
206+
}
207+
208+
59209
INT_PTR CALLBACK PvpPeClrDlgProc(
60210
_In_ HWND hwndDlg,
61211
_In_ UINT uMsg,
@@ -74,9 +224,7 @@ INT_PTR CALLBACK PvpPeClrDlgProc(
74224
case WM_INITDIALOG:
75225
{
76226
HWND lvHandle;
77-
PPH_STRING string;
78-
PH_STRING_BUILDER stringBuilder;
79-
PSTORAGESIGNATURE metaData;
227+
PSTORAGESIGNATURE clrMetaData;
80228

81229
lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
82230
PhSetListViewStyle(lvHandle, TRUE, TRUE);
@@ -85,97 +233,15 @@ INT_PTR CALLBACK PvpPeClrDlgProc(
85233
PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"VA");
86234
PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 80, L"Size");
87235

88-
string = PhaFormatString(
89-
L"%u.%u",
90-
PvImageCor20Header->MajorRuntimeVersion,
91-
PvImageCor20Header->MinorRuntimeVersion);
92-
PhSetDialogItemText(hwndDlg, IDC_RUNTIMEVERSION, string->Buffer);
236+
PhSetDialogItemText(hwndDlg, IDC_RUNTIMEVERSION, PH_AUTO_T(PH_STRING, PvpPeGetClrVersionText())->Buffer);
237+
PhSetDialogItemText(hwndDlg, IDC_FLAGS, PH_AUTO_T(PH_STRING, PvpPeGetClrFlagsText())->Buffer);
93238

94-
PhInitializeStringBuilder(&stringBuilder, 256);
95-
96-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_ILONLY)
97-
PhAppendStringBuilder2(&stringBuilder, L"IL only, ");
98-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_32BITREQUIRED)
99-
PhAppendStringBuilder2(&stringBuilder, L"32-bit only, ");
100-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_32BITPREFERRED)
101-
PhAppendStringBuilder2(&stringBuilder, L"32-bit preferred, ");
102-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_IL_LIBRARY)
103-
PhAppendStringBuilder2(&stringBuilder, L"IL library, ");
104-
105-
if (PvImageCor20Header->StrongNameSignature.VirtualAddress != 0 && PvImageCor20Header->StrongNameSignature.Size != 0)
106-
{
107-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_STRONGNAMESIGNED)
108-
PhAppendStringBuilder2(&stringBuilder, L"Strong-name signed, ");
109-
else
110-
PhAppendStringBuilder2(&stringBuilder, L"Strong-name delay signed, ");
111-
}
112-
113-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT)
114-
PhAppendStringBuilder2(&stringBuilder, L"Native entry-point, ");
115-
if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_TRACKDEBUGDATA)
116-
PhAppendStringBuilder2(&stringBuilder, L"Track debug data, ");
117-
118-
if (PhEndsWithString2(stringBuilder.String, L", ", FALSE))
119-
PhRemoveEndStringBuilder(&stringBuilder, 2);
120-
121-
PhSetDialogItemText(hwndDlg, IDC_FLAGS, stringBuilder.String->Buffer);
122-
PhDeleteStringBuilder(&stringBuilder);
123-
124-
metaData = PhMappedImageRvaToVa(&PvMappedImage, PvImageCor20Header->MetaData.VirtualAddress, NULL);
125-
126-
if (metaData)
127-
{
128-
__try
129-
{
130-
PhProbeAddress(metaData, PvImageCor20Header->MetaData.Size, PvMappedImage.ViewBase, PvMappedImage.Size, 4);
131-
}
132-
__except (EXCEPTION_EXECUTE_HANDLER)
133-
{
134-
metaData = NULL;
135-
}
136-
}
137-
138-
if (metaData && metaData->VersionLength != 0)
239+
if (clrMetaData = PvpPeGetClrMetaDataHeader())
139240
{
140-
string = PhZeroExtendToUtf16Ex(PTR_ADD_OFFSET(metaData, RTL_SIZEOF_THROUGH_FIELD(STORAGESIGNATURE, VersionLength)), metaData->VersionLength);
141-
PhSetDialogItemText(hwndDlg, IDC_VERSIONSTRING, string->Buffer);
142-
PhDereferenceObject(string);
241+
PhSetDialogItemText(hwndDlg, IDC_VERSIONSTRING, PH_AUTO_T(PH_STRING, PvpPeGetClrStorageVersionText(clrMetaData))->Buffer);
242+
PhSetDialogItemText(hwndDlg, IDC_MVIDSTRING, PH_AUTO_T(PH_STRING, PvpPeClrGetMvid(clrMetaData))->Buffer);
143243

144-
{
145-
PSTORAGEHEADER storageHeader = PTR_ADD_OFFSET(metaData, sizeof(STORAGESIGNATURE) + metaData->VersionLength);
146-
PSTORAGESTREAM streamHeader = PTR_ADD_OFFSET(storageHeader, sizeof(STORAGEHEADER));
147-
148-
for (USHORT i = 0; i < storageHeader->Streams; i++)
149-
{
150-
INT lvItemIndex;
151-
WCHAR sectionName[65];
152-
WCHAR pointer[PH_PTR_STR_LEN_1];
153-
154-
if (PhCopyStringZFromBytes(
155-
streamHeader->Name,
156-
sizeof(streamHeader->Name),
157-
sectionName,
158-
ARRAYSIZE(sectionName),
159-
NULL
160-
))
161-
{
162-
lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, sectionName, NULL);
163-
164-
PhPrintPointer(pointer, UlongToPtr(streamHeader->Offset));
165-
166-
PhSetListViewSubItem(lvHandle, lvItemIndex, 1, pointer);
167-
PhSetListViewSubItem(lvHandle, lvItemIndex, 2, PhaFormatSize(streamHeader->Size, -1)->Buffer);
168-
}
169-
170-
// Stream headers don't have fixed sizes...
171-
// The size is aligned up based on a variable length string at the end.
172-
streamHeader = PTR_ADD_OFFSET(streamHeader, ALIGN_UP(UFIELD_OFFSET(STORAGESTREAM, Name) + strlen(streamHeader->Name) + 1, ULONG));
173-
}
174-
}
175-
}
176-
else
177-
{
178-
PhSetDialogItemText(hwndDlg, IDC_VERSIONSTRING, L"N/A");
244+
PvpPeClrEnumSections(clrMetaData, lvHandle);
179245
}
180246
}
181247
break;

tools/peview/pdb.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ BOOLEAN PdbGetSymbolTypedefType(
211211
Info->TypeIndex = typeIndex;
212212

213213
wcsncpy(Info->Name, symbolName, ARRAYSIZE(Info->Name));
214-
Info->Name[ARRAYSIZE(Info->Name) - 1] = 0;
214+
Info->Name[ARRAYSIZE(Info->Name) - 1] = UNICODE_NULL;
215215
LocalFree(symbolName);
216216

217217
return TRUE;
@@ -235,7 +235,7 @@ BOOLEAN PdbGetSymbolEnumType(
235235
return FALSE;
236236

237237
wcsncpy(Info->Name, symbolName, ARRAYSIZE(Info->Name));
238-
Info->Name[ARRAYSIZE(Info->Name) - 1] = 0;
238+
Info->Name[ARRAYSIZE(Info->Name) - 1] = UNICODE_NULL;
239239
LocalFree(symbolName);
240240

241241
// Type index ("typeId" in DIA)
@@ -367,7 +367,7 @@ BOOLEAN PdbGetSymbolUDTClass(
367367
return FALSE;
368368

369369
wcsncpy(Info->Name, symbolName, ARRAYSIZE(Info->Name));
370-
Info->Name[ARRAYSIZE(Info->Name) - 1] = 0;
370+
Info->Name[ARRAYSIZE(Info->Name) - 1] = UNICODE_NULL;
371371
LocalFree(symbolName);
372372

373373
// Length ("length" in DIA)
@@ -423,7 +423,7 @@ BOOLEAN PdbGetSymbolUDTUnion(
423423
return FALSE;
424424

425425
wcsncpy(Info->Name, symbolName, ARRAYSIZE(Info->Name));
426-
Info->Name[ARRAYSIZE(Info->Name) - 1] = 0;
426+
Info->Name[ARRAYSIZE(Info->Name) - 1] = UNICODE_NULL;
427427
LocalFree(symbolName);
428428

429429
// Length ("length" in DIA)
@@ -649,7 +649,7 @@ BOOLEAN PdbGetSymbolData(
649649
return FALSE;
650650

651651
wcsncpy(Info->Name, symbolName, ARRAYSIZE(Info->Name));
652-
Info->Name[ARRAYSIZE(Info->Name) - 1] = 0;
652+
Info->Name[ARRAYSIZE(Info->Name) - 1] = UNICODE_NULL;
653653
LocalFree(symbolName);
654654

655655
// Index of type symbol ("typeId" in DIA)

tools/peview/peview.rc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,10 @@ BEGIN
264264
EDITTEXT IDC_FLAGS,76,19,217,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
265265
LTEXT "Version String:",IDC_STATIC,7,31,48,8
266266
LTEXT "Static",IDC_VERSIONSTRING,78,31,215,8
267-
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,57,286,216
268-
LTEXT "Sections:",IDC_STATIC,7,47,30,8
267+
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,69,286,204
268+
LTEXT "Sections:",IDC_STATIC,7,58,30,8
269+
LTEXT "MVID:",IDC_STATIC,7,44,21,8
270+
EDITTEXT IDC_MVIDSTRING,76,45,217,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
269271
END
270272

271273
IDD_PELOADCONFIG DIALOGEX 0, 0, 300, 280

tools/peview/resource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define IDC_VERSION 1013
4040
#define IDC_VERSIONSTRING 1014
4141
#define IDC_IMAGEBASE 1015
42+
#define IDC_MVIDSTRING 1015
4243
#define IDC_ENTRYPOINT 1016
4344
#define IDC_SYMSEARCH 1017
4445
#define IDC_IMAGETYPE 1017

0 commit comments

Comments
 (0)