System.Data.SQLite
Check-in [08f855ffb1]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Better generic entrypoint handling
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sourceforge
Files: files | file ages | folders
SHA1: 08f855ffb188e8a1865848160da8d5a93f2d0387
User & Date: rmsimpson 2006-01-27 22:21:50
Context
2006-01-27
22:41
Documentation updates check-in: 5b7117d61a user: rmsimpson tags: sourceforge
22:21
Better generic entrypoint handling check-in: 08f855ffb1 user: rmsimpson tags: sourceforge
06:13
Fixed a bug in aggregate functions with empty resultsets check-in: ab8b2729bb user: rmsimpson tags: sourceforge
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to bin/tools/mergebin.exe.

cannot compute difference between binary files

Changes to tools/mergebin/mergebin.cpp.

10
11
12
13
14
15
16





17
18
19
20
21
22
23
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
200
201
202
203
204
205
206
207



208
209
210
211

212
213
214
215
216





217
218
219
220
221
222
223
224
225
226
...
301
302
303
304
305
306
307

308
309
310
311
312
313
314
...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
347
348
349
350
351
352
353



354
355
356
357
358
359
360
...
376
377
378
379
380
381
382

383
384
385
386
387

388
389
390
391
392
393
394
395
#include "MetaDataTables.h"
#include "TableData.h"

void DumpCLRInfo(LPCTSTR pszFile);
void MergeModules(LPCTSTR pszAssembly, LPCTSTR pszNative, LPCTSTR pszSection);
void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection);






int _tmain(int argc, _TCHAR* argv[])
{
  if (argc == 1)
  {
    _tprintf(_T(
"MERGEBIN - Merges a pure .NET assembly with a native DLL\n \
Syntax: MERGEBIN [/I:assembly] [/S:sectionname assembly nativedll]\n \
................................................................................

  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("Unable to retrieve .NET assembly information for file %s\n"), pszFile);
    return;
  }

  _tprintf(_T("%d Bytes required to merge %s\n"), (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb, pszFile);
}

void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection)
{
  CPEFile peFile;
  HRESULT hr;
  DWORD dwMinRVA;
................................................................................
// %s\n\n\
#include <windef.h>\n\n\
#pragma data_seg(\"%s\")\n\
#pragma comment(linker, \"/SECTION:%s,ER\")\n\
  char __ph[%d] = {0}; // The number of bytes to reserve\n\
#pragma data_seg()\n\n\
typedef BOOL (WINAPI *DLLMAIN)(HANDLE, DWORD, LPVOID);\n\
extern BOOL WINAPI _DllMainCRTStartup(HANDLE, DWORD, LPVOID);\n\n\



__declspec(dllexport) BOOL WINAPI _CorDllMainStub(HANDLE hModule, DWORD dwReason, LPVOID pvReserved)\n\
{\n\
  HANDLE hMod;\n\
  DLLMAIN proc;\n\n\

  hMod = GetModuleHandle(_T(\"mscoree\"));\n\
  if (hMod)\n\
    proc = (DLLMAIN)GetProcAddress(hMod, _T(\"_CorDllMain\"));\n\
  else\n\
    proc = _DllMainCRTStartup;\n\n\





  return proc(hModule, dwReason, pvReserved);\n\
}\n\
"), pszAssembly, pszSection, pszSection, (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb);
}

/*   When merged, the native DLL's entrypoint must go to _CorDllMain in MSCOREE.DLL.
  ** In order to do this, we need to change the DLL's entrypoint to "something" that will
  ** call CorDllMain.  Since its too much hassle to add imports to the DLL and make drastic
  ** changes to it, we rely on the native DLL to export a function that we can call which will
  ** forward to CorDllMain.  Exported functions are easy to identify and get an RVA for.
................................................................................
  PIMAGE_COR20_HEADER pCor;
  PIMAGE_NT_HEADERS32 pNT;
  PIMAGE_NT_HEADERS64 pNT64;
  int diffRVA;
  CTableData *p;
  DWORD *pdwRVA;
  DWORD dwRows;


  // Open the .NET assembly
  hr = peFile.Open(pszAssembly);
  if (FAILED(hr)) return;

  // Scan the .NET assembly and find the block of .NET code specified in the .NET metadata
  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
................................................................................
  if (!pSection)
  {
    _tprintf(_T("Unable to find section %s in file\n"), pszSection);
    return;
  }

  // If the section isn't large enough, tell the user how large it needs to be
  if (pSection->Misc.VirtualSize < dwSize)
  {
    _tprintf(_T("Not enough room in section for data.  Need %d bytes\n"), dwSize);
    return;
  }

  /*
  ** Find a new entrypoint to use for the DLL.  The old entrypoint is written into the .NET header
  */
  dwNewEntrypoint = GetExportedCorDllMainRVA(peDest);
................................................................................
    _tprintf(_T("Native DLL must export a function that calls _CorDllMain, and its name must contain the word \"CorDllMain\".\n"));
    return;
  }

  // Change this section's flags
  pSection->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
  dwDestRVA = pSection->VirtualAddress;




  // If the native DLL has been merged with an assembly beforehand, we need to strip the .NET stuff and restore the entrypoint
  pCor = peDest;
  if (pCor)
  {
    if (pCor->Flags & 0x10)
    {
................................................................................

  pNT = peDest;
  pNT64 = peDest;

  // Fixup the NT header on the native DLL to include the new .NET header
  if (pNT)
  {

    pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = pSection->VirtualAddress;
    pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = dwSize;
  }
  else
  {

    pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = pSection->VirtualAddress;
    pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = dwSize;
  }
  dwDestRVA += dwSize;
  if (dwDestRVA % 4) dwDestRVA += (4 - (dwDestRVA % 4));

  // Copy the .NET block of code and metadata into the section, after the header
  dwSize = dwMaxRVA - dwMinRVA;







>
>
>
>
>







 







|







 







|
>
>
>



|
>




|
>
>
>
>
>


|







 







>







 







|

|







 







>
>
>







 







>
|




>
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
#include "MetaDataTables.h"
#include "TableData.h"

void DumpCLRInfo(LPCTSTR pszFile);
void MergeModules(LPCTSTR pszAssembly, LPCTSTR pszNative, LPCTSTR pszSection);
void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection);

typedef struct EXTRA_STUFF
{
  DWORD dwNativeEntryPoint;
} EXTRA_STUFF, *LPEXTRA_STUFF;

int _tmain(int argc, _TCHAR* argv[])
{
  if (argc == 1)
  {
    _tprintf(_T(
"MERGEBIN - Merges a pure .NET assembly with a native DLL\n \
Syntax: MERGEBIN [/I:assembly] [/S:sectionname assembly nativedll]\n \
................................................................................

  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("Unable to retrieve .NET assembly information for file %s\n"), pszFile);
    return;
  }

  _tprintf(_T("%d Bytes required to merge %s\n"), (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb + sizeof(EXTRA_STUFF), pszFile);
}

void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection)
{
  CPEFile peFile;
  HRESULT hr;
  DWORD dwMinRVA;
................................................................................
// %s\n\n\
#include <windef.h>\n\n\
#pragma data_seg(\"%s\")\n\
#pragma comment(linker, \"/SECTION:%s,ER\")\n\
  char __ph[%d] = {0}; // The number of bytes to reserve\n\
#pragma data_seg()\n\n\
typedef BOOL (WINAPI *DLLMAIN)(HANDLE, DWORD, LPVOID);\n\
typedef struct EXTRA_STUFF\n\
{\n\
  DWORD dwNativeEntryPoint;\n\
} EXTRA_STUFF, *LPEXTRA_STUFF;\n\n\
__declspec(dllexport) BOOL WINAPI _CorDllMainStub(HANDLE hModule, DWORD dwReason, LPVOID pvReserved)\n\
{\n\
  HANDLE hMod;\n\
  DLLMAIN proc;\n\
  LPEXTRA_STUFF pExtra;\n\n\
  hMod = GetModuleHandle(_T(\"mscoree\"));\n\
  if (hMod)\n\
    proc = (DLLMAIN)GetProcAddress(hMod, _T(\"_CorDllMain\"));\n\
  else\n\
  {\n\
    MEMORY_BASIC_INFORMATION mbi;\n\n\
    VirtualQuery(_CorDllMainStub, &mbi, sizeof(mbi));\n\
    pExtra = (LPEXTRA_STUFF)__ph;\n\
    proc = (DLLMAIN)(pExtra->dwNativeEntryPoint + (DWORD)mbi.AllocationBase);\n\
  }\n\
  return proc(hModule, dwReason, pvReserved);\n\
}\n\
"), pszAssembly, pszSection, pszSection, (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb + sizeof(EXTRA_STUFF));
}

/*   When merged, the native DLL's entrypoint must go to _CorDllMain in MSCOREE.DLL.
  ** In order to do this, we need to change the DLL's entrypoint to "something" that will
  ** call CorDllMain.  Since its too much hassle to add imports to the DLL and make drastic
  ** changes to it, we rely on the native DLL to export a function that we can call which will
  ** forward to CorDllMain.  Exported functions are easy to identify and get an RVA for.
................................................................................
  PIMAGE_COR20_HEADER pCor;
  PIMAGE_NT_HEADERS32 pNT;
  PIMAGE_NT_HEADERS64 pNT64;
  int diffRVA;
  CTableData *p;
  DWORD *pdwRVA;
  DWORD dwRows;
  LPEXTRA_STUFF pExtra;

  // Open the .NET assembly
  hr = peFile.Open(pszAssembly);
  if (FAILED(hr)) return;

  // Scan the .NET assembly and find the block of .NET code specified in the .NET metadata
  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
................................................................................
  if (!pSection)
  {
    _tprintf(_T("Unable to find section %s in file\n"), pszSection);
    return;
  }

  // If the section isn't large enough, tell the user how large it needs to be
  if (pSection->Misc.VirtualSize < (dwSize + sizeof(EXTRA_STUFF)))
  {
    _tprintf(_T("Not enough room in section for data.  Need %d bytes\n"), dwSize + sizeof(EXTRA_STUFF));
    return;
  }

  /*
  ** Find a new entrypoint to use for the DLL.  The old entrypoint is written into the .NET header
  */
  dwNewEntrypoint = GetExportedCorDllMainRVA(peDest);
................................................................................
    _tprintf(_T("Native DLL must export a function that calls _CorDllMain, and its name must contain the word \"CorDllMain\".\n"));
    return;
  }

  // Change this section's flags
  pSection->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
  dwDestRVA = pSection->VirtualAddress;

  pExtra = (LPEXTRA_STUFF)peDest.GetPtrFromRVA(dwDestRVA);
  dwDestRVA += sizeof(EXTRA_STUFF);

  // If the native DLL has been merged with an assembly beforehand, we need to strip the .NET stuff and restore the entrypoint
  pCor = peDest;
  if (pCor)
  {
    if (pCor->Flags & 0x10)
    {
................................................................................

  pNT = peDest;
  pNT64 = peDest;

  // Fixup the NT header on the native DLL to include the new .NET header
  if (pNT)
  {
    pExtra->dwNativeEntryPoint = pNT->OptionalHeader.AddressOfEntryPoint;
    pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = dwDestRVA;
    pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = dwSize;
  }
  else
  {
    pExtra->dwNativeEntryPoint = pNT64->OptionalHeader.AddressOfEntryPoint;
    pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = dwDestRVA;
    pNT64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = dwSize;
  }
  dwDestRVA += dwSize;
  if (dwDestRVA % 4) dwDestRVA += (4 - (dwDestRVA % 4));

  // Copy the .NET block of code and metadata into the section, after the header
  dwSize = dwMaxRVA - dwMinRVA;

Changes to tools/mergebin/mergebin.vcproj.

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="$(ProjectName).exe"
				LinkIncremental="1"
				GenerateManifest="false"
				GenerateDebugInformation="true"
				SubSystem="1"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				TargetMachine="1"







|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="..\..\bin\tools\$(ProjectName).exe"
				LinkIncremental="1"
				GenerateManifest="false"
				GenerateDebugInformation="true"
				SubSystem="1"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				TargetMachine="1"