home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / smc / PEwrite.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  13.7 KB  |  437 lines

  1. /*****************************************************************************/
  2. #ifndef _PEWRITE_H_
  3. #define _PEWRITE_H_
  4. /*****************************************************************************/
  5.  
  6. #ifndef _OUTFILE_H_
  7. #include "outfile.h"
  8. #endif
  9.  
  10. #ifndef _CORWRAP_H
  11. #include "CORwrap.h"
  12. #endif
  13.  
  14. /*****************************************************************************/
  15.  
  16. const   unsigned    PEfileAlignment  = 512;
  17. const   unsigned    PEvirtAlignment  = OS_page_size;
  18.  
  19. /*****************************************************************************/
  20.  
  21. const   unsigned    PEmaxSections    = 8;
  22.  
  23. /*****************************************************************************/
  24.  
  25. const   unsigned    MAX_PE_TEXT_SIZE = 1024*1024*16;
  26. const   unsigned    MAX_PE_DATA_SIZE = 1024*256;
  27. const   unsigned    MAX_PE_RDTA_SIZE = 1024*512;
  28. const   unsigned    MAX_PE_RLOC_SIZE = 1024*4;
  29.  
  30. /*****************************************************************************/
  31.  
  32. const   unsigned    CODE_BASE_RVA    = 0x1000;  // ISSUE: Not exactly robust!
  33.  
  34. /*****************************************************************************/
  35.  
  36. enum    WPEstdSects
  37. {
  38.     PE_SECT_text,
  39.     PE_SECT_data,
  40.     PE_SECT_rdata,
  41.     PE_SECT_rsrc,
  42.     PE_SECT_reloc,
  43.  
  44.     PE_SECT_count,
  45. };
  46.  
  47. const   WPEstdSects PE_SECT_string = PE_SECT_count;
  48.  
  49. /*****************************************************************************/
  50.  
  51. struct  PErelocDsc;
  52. typedef PErelocDsc *PEreloc;
  53.  
  54. struct  PErelocDsc
  55. {
  56.     PEreloc         perNext;
  57.  
  58.     unsigned        perSect     :4;     // enough to store 'PEmaxSections'
  59.     unsigned        perOffs     :28;
  60. };
  61.  
  62. /*****************************************************************************/
  63.  
  64. struct  PEsecData;
  65. typedef PEsecData * PEsection;
  66.  
  67. struct  PEsecData
  68. {
  69.     BYTE    *       PEsdBase;
  70.     BYTE    *       PEsdNext;
  71.     BYTE    *       PEsdLast;
  72.     BYTE    *       PEsdEndp;
  73.  
  74.     WPEstdSects     PEsdIndex;
  75.  
  76.     PEreloc         PEsdRelocs;
  77.  
  78. #ifdef  DEBUG
  79.     bool            PEsdFinished;
  80. #endif
  81.  
  82.     unsigned        PEsdAddrFile;
  83.     unsigned        PEsdAddrRVA;
  84.     unsigned        PEsdSizeData;
  85.     unsigned        PEsdFlags;
  86. };
  87.  
  88. /*****************************************************************************
  89.  *
  90.  *  The following is used to build the import tables. We hash all DLL names
  91.  *  along with the imports into a hash table, and keep track of the number
  92.  *  of imports for each DLL and all that.
  93.  */
  94.  
  95. class   WPEnameRec;
  96. typedef WPEnameRec *WPEname;
  97. struct  WPEndefRec;
  98. typedef WPEndefRec *WPEndef;
  99. class   WPEhashTab;
  100. typedef WPEhashTab *WPEhash;
  101. struct  WPEiDLLdsc;
  102. typedef WPEiDLLdsc *WPEimpDLL;
  103.  
  104. class   WPEnameRec
  105. {
  106. public:
  107.  
  108.     WPEname         PEnmNext;       // next name in this hash bucket
  109.     WPEndef         PEnmDefs;       // list of imports for this name
  110.  
  111.     unsigned        PEnmHash;       // hash value
  112.  
  113.     unsigned        PEnmOffs;       // offset within hint/name table
  114.  
  115.     const   char *  PEnmSpelling() { assert(this); return PEnmName; }
  116.  
  117.     unsigned short  PEnmFlags;      // see PENMF_xxxx below
  118.  
  119.     unsigned short  PEnmNlen;       // length of the identifier's name
  120.     char            PEnmName[];     // the spelling follows
  121. };
  122.  
  123. enum    WPEnameFlags
  124. {
  125.     PENMF_IMP_NAME   = 0x01,        // the identifier is an import name
  126. };
  127.  
  128. class   WPEhashTab
  129. {
  130. public:
  131.  
  132.     void            WPEhashInit(Compiler         comp,
  133.                                 norls_allocator *alloc,
  134.                                 unsigned         count = 512);
  135.  
  136.     WPEname         WPEhashName(const char * name, bool *isNewPtr);
  137.     WPEndef         WPEhashName(const char * name,
  138.                                 WPEimpDLL   owner, bool *isNewPtr);
  139.  
  140.     norls_allocator*WPEhashAlloc;
  141.  
  142.     WPEname    *    WPEhashTable;
  143.     unsigned        WPEhashSize;
  144.     unsigned        WPEhashMask;
  145.     Compiler        WPEhashComp;
  146.  
  147.     size_t          WPEhashStrLen;  // total length of all non-DLL strings
  148. };
  149.  
  150. struct  WPEiDLLdsc                  // describes each imported DLL
  151. {
  152.     WPEimpDLL       PEidNext;       // mext DLL name
  153.     WPEname         PEidName;       // name record for this DLL
  154.  
  155.     unsigned        PEidIndex;      // each DLL has an index assigned to it
  156.     unsigned        PEidIATbase;    // offset of first IAT entry
  157.     unsigned        PEidILTbase;    // offset of first import lookup entry
  158.  
  159.     WPEndef         PEidImpList;    // list of imports - head
  160.     WPEndef         PEidImpLast;    // list of imports - tail
  161.     unsigned        PEidImpCnt;     // number of imports in this DLL
  162. };
  163.  
  164. struct  WPEndefRec                  // describes each unique (DLL,import) pair
  165. {
  166.     WPEndef         PEndNext;       // next import with this name (other DLL's)
  167.     WPEname         PEndName;       // the name entry itself
  168.     WPEndef         PEndNextInDLL;  // next import of the same DLL
  169.     WPEimpDLL       PEndDLL;        // the DLL this import comes from
  170.     unsigned        PEndIndex;      // the index within the DLL
  171. };
  172.  
  173. /*****************************************************************************/
  174.  
  175. DEFMGMT
  176. class   writePE
  177. {
  178. private:
  179.  
  180.     Compiler        WPEcomp;
  181.     norls_allocator*WPEalloc;
  182.     OutFile         WPEoutFile;
  183.  
  184.     const   char *  WPEoutFnam;
  185.  
  186. public:
  187.  
  188.     /*************************************************************************/
  189.     /* Prepare to output a PE file, flush and write the file to disk         */
  190.     /*************************************************************************/
  191.  
  192.     bool            WPEinit(Compiler comp, norls_allocator*alloc);
  193.     bool            WPEdone(mdToken entryTok, bool errors);
  194.  
  195.     /*************************************************************************/
  196.     /* Set the name of the output file, this better be done (and on time)!   */
  197.     /*************************************************************************/
  198.  
  199.     void            WPEsetOutputFileName(const char *outfile);
  200.  
  201.     /*************************************************************************/
  202.     /* Add a resource file to the output image                               */
  203.     /*************************************************************************/
  204.  
  205. public:
  206.     bool            WPEaddRCfile(const char *filename);
  207.  
  208. private:
  209.     size_t          WPErsrcSize;
  210.  
  211.     HANDLE          WPErsrcFile;
  212.     HANDLE          WPErsrcFmap;
  213.     const   BYTE  * WPErsrcBase;
  214.  
  215.     void            WPEinitRCimp();
  216.     void            WPEdoneRCimp();
  217.  
  218.     void            WPEgenRCcont(OutFile  outf, PEsection sect);
  219.  
  220.     /*************************************************************************/
  221.     /* The following members create and manage PE file sections              */
  222.     /*************************************************************************/
  223.  
  224. private:
  225.  
  226.     PEsecData       WPEsections[PEmaxSections];
  227.     unsigned        WPEsectCnt;
  228.  
  229.     PEsecData     * WPEgetSection(WPEstdSects sect)
  230.     {
  231.         assert(sect < PE_SECT_count);
  232.         assert(WPEsecTable[sect]);
  233.         return WPEsecTable[sect];
  234.     }
  235.  
  236.     PEsection       WPEsecList;
  237.     PEsection       WPEsecLast;
  238.  
  239. //  unsigned        WPEcodeRVA;             // RVA of the .text  section
  240.     unsigned        WPErdatRVA;             // RVA of the .rdata section
  241.     unsigned        WPEdataRVA;             // RVA of the .data  section
  242.     unsigned        WPErsrcRVA;             // RVA of the .rsrc  section
  243.  
  244.     unsigned        WPEvirtBase;
  245.  
  246.     PEsection       WPEsecTable[PE_SECT_count];
  247.  
  248.     static
  249.     const   char    WPEsecNames[PE_SECT_count][IMAGE_SIZEOF_SHORT_NAME];
  250.  
  251. public:
  252.  
  253.     const   char *  WPEsecName    (WPEstdSects sect);
  254.  
  255.     void            WPEaddSection (WPEstdSects sect, unsigned attrs,
  256.                                                      size_t   maxSz);
  257.  
  258.     unsigned        WPEsecAddrRVA (WPEstdSects sect);
  259.     unsigned        WPEsecAddrVirt(WPEstdSects sect);
  260.     unsigned        WPEsecAddrOffs(WPEstdSects sect, memBuffPtr addr);
  261.     size_t          WPEsecSizeData(WPEstdSects sect);
  262.     size_t          WPEsecNextOffs(WPEstdSects sect);
  263.  
  264.     unsigned        WPEsecRsvData (WPEstdSects sect, size_t         size,
  265.                                                      size_t         align,
  266.                                                  OUT memBuffPtr REF outRef);
  267.     unsigned        WPEsecAddData (WPEstdSects sect, genericBuff    data,
  268.                                                      size_t         size);
  269.     memBuffPtr      WPEsecAdrData (WPEstdSects sect, unsigned       offs);
  270.  
  271.     void            WPEsecAddFixup(WPEstdSects ssrc,
  272.                                    WPEstdSects sdst, unsigned       offs);
  273.  
  274.     unsigned        WPEgetCodeBase()
  275.     {
  276.         return  CODE_BASE_RVA;
  277.     }
  278.  
  279.     unsigned        WPEallocCode  (size_t size, size_t align, OUT memBuffPtr REF dataRef);
  280.     void            WPEallocString(size_t size, size_t align, OUT memBuffPtr REF dataRef);
  281. private:
  282.     unsigned        WPEstrPoolBase;
  283.  
  284.     /*************************************************************************/
  285.     /* The following members manage COM+ / metadata generation               */
  286.     /*************************************************************************/
  287.  
  288. private:
  289.  
  290.     unsigned        WPEcomPlusOffs;
  291.     size_t          WPEcomPlusSize;
  292.  
  293.     unsigned        WPEmetaDataOffs;
  294.     size_t          WPEmetaDataSize;
  295.  
  296.     size_t          WPEgetCOMplusSize(unsigned offs);
  297.     void            WPEgenCOMplusData(OutFile outf, PEsection sect, mdToken entryTok);
  298.  
  299.     WMetaDataDispenser *WPEwmdd;
  300.     WMetaDataEmit      *WPEwmde;
  301.  
  302. public:
  303.  
  304.     void            WPEinitMDemit(WMetaDataDispenser *mdd,
  305.                                   WMetaDataEmit      *mde)
  306.     {
  307.         WPEwmdd = mdd;
  308.         WPEwmde = mde;
  309.     }
  310.  
  311.     void            WPEdoneMDemit()
  312.     {
  313.         WPEwmde = NULL;
  314.         WPEwmdd = NULL;
  315.     }
  316.  
  317.     /*************************************************************************/
  318.     /* The following members manage Debug Directory generation               */
  319.     /*************************************************************************/
  320.  
  321. private:
  322.  
  323.     unsigned        WPEdebugDirOffs;
  324.     size_t          WPEdebugDirSize;
  325.  
  326.     size_t          WPEgetDebugDirSize(unsigned offs);
  327.     void            WPEgenDebugDirData(OutFile outf,
  328.                                        PEsection sect,
  329.                                        DWORD timestamp);
  330.  
  331.     IMAGE_DEBUG_DIRECTORY  WPEdebugDirIDD;
  332.     DWORD                  WPEdebugDirDataSize;
  333.     BYTE                  *WPEdebugDirData;
  334.  
  335. public:
  336.  
  337.     int             WPEinitDebugDirEmit(WSymWriter *cmpSymWriter)
  338.     {
  339.         int err = 0;
  340.  
  341.         /* Get the size of the debug data blob */
  342.  
  343.         if (err = cmpSymWriter->GetDebugInfo(NULL,
  344.                                              0,
  345.                                              &WPEdebugDirDataSize,
  346.                                              NULL))
  347.             return err;
  348.  
  349.         if (WPEdebugDirDataSize)
  350.         {
  351.             WPEdebugDirData = (BYTE*)WPEalloc->nraAlloc(WPEdebugDirDataSize);
  352.  
  353.             err = cmpSymWriter->GetDebugInfo(&WPEdebugDirIDD,
  354.                                              WPEdebugDirDataSize,
  355.                                              NULL,
  356.                                              WPEdebugDirData);
  357.         }
  358.         else
  359.             WPEdebugDirData = NULL;
  360.  
  361.         return err;
  362.     }
  363.  
  364.     /*************************************************************************/
  365.     /* The following members manage the import tables                        */
  366.     /*************************************************************************/
  367.  
  368.     WPEhash         WPEimpHash;
  369.  
  370.     void    *       WPEcorMain;             // IAT entry for _CorMain
  371.  
  372.     unsigned        WPEimpDLLcnt;
  373.     WPEimpDLL       WPEimpDLLlist;
  374.     WPEimpDLL       WPEimpDLLlast;
  375.  
  376.     unsigned        WPEimpSizeAll;          // size of all import tables
  377.  
  378.     unsigned        WPEimpOffsIAT;          // offset of the IAT
  379.     unsigned        WPEimpSizeIAT;          // size   of the IAT
  380.  
  381.     unsigned        WPEimpOffsIDT;          // offset of the import directory
  382.     unsigned        WPEimpSizeIDT;          // size   of the import directory
  383.  
  384.     unsigned        WPEimpOffsLook;         // offset of the lookup    table
  385.     unsigned        WPEimpOffsName;         // offset of the name/hint table
  386.     unsigned        WPEimpOffsDLLn;         // offset of the DLL name  table
  387.  
  388.     unsigned        WPEimpDLLstrLen;        // length of all DLL  strings
  389.  
  390.     void            WPEimportInit();
  391.     size_t          WPEimportDone(unsigned offs);
  392.     void            WPEimportGen (OutFile  outf, PEsection sect);
  393.  
  394.     void          * WPEimportAdd (const char *DLLname, const char *impName);
  395. };
  396.  
  397. /*****************************************************************************/
  398.  
  399. inline
  400. unsigned            writePE::WPEsecAddrRVA (WPEstdSects sect)
  401. {
  402.     PEsecData     * sec = WPEgetSection(sect);
  403.  
  404.     assert(sec->PEsdFinished);
  405.     return sec->PEsdAddrFile;
  406. }
  407.  
  408. inline
  409. unsigned            writePE::WPEsecAddrVirt(WPEstdSects sect)
  410. {
  411.     PEsecData     * sec = WPEgetSection(sect);
  412.  
  413.     assert(sec->PEsdFinished);
  414.     return sec->PEsdAddrRVA;
  415. }
  416.  
  417. inline
  418. size_t              writePE::WPEsecSizeData(WPEstdSects sect)
  419. {
  420.     PEsecData     * sec = WPEgetSection(sect);
  421.  
  422.     assert(sec->PEsdFinished);
  423.     return sec->PEsdSizeData;
  424. }
  425.  
  426. inline
  427. size_t              writePE::WPEsecNextOffs(WPEstdSects sect)
  428. {
  429.     PEsecData     * sec = WPEgetSection(sect);
  430.  
  431.     return sec->PEsdNext - sec->PEsdBase;
  432. }
  433.  
  434. /*****************************************************************************/
  435. #endif//_PEWRITE_H_
  436. /*****************************************************************************/
  437.