Changeset 2944 for trunk/kLdr/kLdrHlp.c


Ignore:
Timestamp:
Jan 13, 2007, 4:55:40 PM (19 years ago)
Author:
bird
Message:

split up kLdrHlp.c and kLdr.c to make it more flexible (like using the module interpreters without the dynamic loader bit and similar).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrHlp.c

    r2898 r2944  
    22/** @file
    33 *
    4  * kLdr - The Dynamic Loader, Helper Functions.
     4 * kLdr - The Dynamic Loader, Misc Helper Functions.
    55 *
    66 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
     
    4141#include <kLdr.h>
    4242#include "kLdrHlp.h"
    43 
    44 
    45 /*******************************************************************************
    46 *   Global Variables                                                           *
    47 *******************************************************************************/
    48 #ifdef __OS2__
    49 /** The loader sempahore. */
    50 static HMTX             g_hmtx;
    51 /** The base of the stub object.
    52  * The OS/2 exe stub consists of a single data object. When allocating memory
    53  * for an executable, we'll have to reuse this.  */
    54 static void            *g_pvStub = NULL;
    55 /** The size of the stub object - 0 if no stub. */
    56 static size_t           g_cbStub = 0;
    57 
    58 #elif defined(__WIN__)
    59 /** The loader sempahore. */
    60 static CRITICAL_SECTION g_CritSect;
    61 /** The system info. */
    62 static SYSTEM_INFO      g_SystemInfo;
    63 #else
    64 # error "port me"
    65 #endif
    66 
    67 
    68 /**
    69  * Initializes the loader semaphore.
    70  *
    71  * @returns 0 on success, non-zero OS status code on failure.
    72  */
    73 int     kldrHlpSemInit(void)
    74 {
    75 #ifdef __OS2__
    76     APIRET rc;
    77     g_hmtx = NULLHANDLE;
    78     rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE);
    79     if (rc)
    80         return rc;
    81 
    82 #elif defined(__WIN__)
    83     InitializeCriticalSection(&g_CritSect);
    84 
    85 #else
    86 # error "port me"
    87 #endif
    88     return 0;
    89 }
    90 
    91 
    92 /**
    93  * Terminates the loader semaphore.
    94  */
    95 void    kldrHlpSemTerm(void)
    96 {
    97 #ifdef __OS2__
    98     HMTX hmtx = g_hmtx;
    99     g_hmtx = NULLHANDLE;
    100     DosCloseMutexSem(hmtx);
    101 
    102 #elif defined(__WIN__)
    103     DeleteCriticalSection(&g_CritSect);
    104 
    105 #else
    106 # error "port me"
    107 #endif
    108 }
    109 
    110 
    111 /**
    112  * Requests the loader sempahore ownership.
    113  * This can be done recursivly.
    114  *
    115  * @returns 0 on success, non-zero OS status code on failure.
    116  */
    117 int     kldrHlpSemRequest(void)
    118 {
    119 #ifdef __OS2__
    120     APIRET rc = DosRequestMutexSem(g_hmtx, 5000);
    121     if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT)
    122     {
    123         unsigned i = 0;
    124         do
    125         {
    126             /** @todo check for deadlocks etc. */
    127             rc = DosRequestMutexSem(g_hmtx, 1000);
    128         } while (   (   rc == ERROR_TIMEOUT
    129                      || rc == ERROR_SEM_TIMEOUT
    130                      || rc == ERROR_INTERRUPT)
    131                  && i++ < 120);
    132     }
    133     return rc;
    134 
    135 #elif defined(__WIN__)
    136     EnterCriticalSection(&g_CritSect);
    137     return 0;
    138 
    139 #else
    140 # error "port me"
    141 #endif
    142 }
    143 
    144 
    145 /**
    146  * Releases the loader semaphore ownership.
    147  * The caller is responsible for making sure it's the semaphore owner!
    148  */
    149 void    kldrHlpSemRelease(void)
    150 {
    151 #ifdef __OS2__
    152     APIRET rc = DosReleaseMutexSem(g_hmtx);
    153     kldrHlpAssert(!rc); (void)rc;
    154 
    155 #elif defined(__WIN__)
    156     LeaveCriticalSection(&g_CritSect);
    157 
    158 #else
    159 # error "port me"
    160 #endif
    161 
    162 }
    163 
    164 #ifdef __OS2__
    165 static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt)
    166 {
    167     switch (enmProt)
    168     {
    169         case KLDRPROT_NOACCESS:             return PAG_EXECUTE | PAG_READ | PAG_WRITE;
    170         case KLDRPROT_READONLY:             return PAG_COMMIT | PAG_READ;
    171         case KLDRPROT_READWRITE:            return PAG_COMMIT | PAG_READ | PAG_WRITE;
    172         case KLDRPROT_EXECUTE:              return PAG_COMMIT | PAG_EXECUTE;
    173         case KLDRPROT_EXECUTE_READ:         return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
    174         case KLDRPROT_EXECUTE_READWRITE:    return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
    175         default:
    176             kldrHlpAssert(0);
    177             return ~0U;
    178     }
    179 }
    180 #elif defined(__WIN__)
    181 static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt)
    182 {
    183     switch (enmProt)
    184     {
    185         case KLDRPROT_NOACCESS:             return PAGE_NOACCESS;
    186         case KLDRPROT_READONLY:             return PAGE_READONLY;
    187         case KLDRPROT_READWRITE:            return PAGE_READWRITE;
    188         case KLDRPROT_EXECUTE:              return PAGE_EXECUTE;
    189         case KLDRPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
    190         case KLDRPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
    191         default:
    192             kldrHlpAssert(0);
    193             return ~0U;
    194     }
    195 }
    196 #endif
    197 
    198 
    199 /**
    200  * Allocate a chunk of memory with page granularity.
    201  *
    202  * @returns 0 on success, non-zero OS status code on failure.
    203  * @param   ppv         Where to store the address of the allocated memory.
    204  *                      If fFixed is set, *ppv will on entry contain the desired address (page aligned).
    205  * @param   cb          Number of bytes. Page aligned.
    206  * @param   enmProt     The new protection. Copy-on-write is invalid.
    207  */
    208 int     kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed)
    209 {
    210 #ifdef __OS2__
    211     APIRET  rc;
    212     ULONG   fFlags = kldrHlpPageProtToNative(enmProt);;
    213 
    214     if (!fFixed)
    215     {
    216         /* simple */
    217         rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
    218         if (rc == ERROR_INVALID_PARAMETER)
    219             rc = DosAllocMem(ppv, cb, fFlags);
    220     }
    221     else
    222     {
    223         /* not so simple. */
    224         /** @todo I've got code for this in libc somewhere. */
    225         rc = -1;
    226     }
    227     if (!rc)
    228         return 0;
    229     kldrHlpAssert(0);
    230     return rc;
    231 
    232 #elif defined(__WIN__)
    233     /* (We don't have to care about the stub here, because the stub will be unmapped before we get here.) */
    234     int     rc;
    235     DWORD   fProt = kldrHlpPageProtToNative(enmProt);
    236 
    237     if (!g_SystemInfo.dwPageSize)
    238         GetSystemInfo(&g_SystemInfo);
    239 
    240     *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
    241     if (*ppv != NULL)
    242         return 0;
    243     rc = GetLastError();
    244     kldrHlpAssert(0);
    245     return rc;
    246 
    247 #else
    248 # error "port me"
    249 #endif
    250 }
    251 
    252 
    253 /**
    254  * Change the protection of one or more pages in an allocation.
    255  *
    256  * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
    257  *
    258  * @returns 0 on success, non-zero OS status code on failure.
    259  * @param   pv          First page. Page aligned.
    260  * @param   cb          Number of bytes. Page aligned.
    261  * @param   enmProt     The new protection. Copy-on-write is invalid.
    262  */
    263 int     kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
    264 {
    265 #ifdef __OS2__
    266     APIRET      rc;
    267     ULONG       fFlags = kldrHlpPageProtToNative(enmProt);;
    268 
    269     /*
    270      * The non-stub pages.
    271      */
    272     rc = DosSetMem(pv, cb, fFlags);
    273     if (rc && fFlags != PAG_DECOMMIT)
    274         rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
    275     if (rc)
    276     {
    277         /* Try page by page. */
    278         while (cb > 0)
    279         {
    280             rc = DosSetMem(pv, 0x1000, fFlags);
    281             if (rc && fFlags != PAG_DECOMMIT)
    282                 rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
    283             if (rc)
    284                 return rc;
    285             pv = (void *)((uintptr_t)pv + 0x1000);
    286             cb -= 0x1000;
    287         }
    288     }
    289     kldrHlpAssert(!rc);
    290     return rc;
    291 
    292 #elif defined(__WIN__)
    293     DWORD fOldProt = 0;
    294     DWORD fProt = kldrHlpPageProtToNative(enmProt);
    295     int rc = 0;
    296 
    297     if (!VirtualProtect(pv, cb, fProt, &fOldProt))
    298     {
    299         rc = GetLastError();
    300         kldrHlpAssert(0);
    301     }
    302     return rc;
    303 #else
    304 # error "port me"
    305 #endif
    306 }
    307 
    308 
    309 /**
    310  * Free memory allocated by kldrHlpPageAlloc().
    311  *
    312  * @returns 0 on success, non-zero OS status code on failure.
    313  * @param   pv          The address returned by kldrHlpPageAlloc().
    314  * @param   cb          The byte count requested from kldrHlpPageAlloc().
    315  */
    316 int     kldrHlpPageFree(void *pv, size_t cb)
    317 {
    318 #ifdef __OS2__
    319     APIRET rc;
    320 
    321     /*
    322      * Deal with any portion overlapping with the stub.
    323      */
    324     uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
    325     if (offStub < g_cbStub)
    326     {
    327         /* decommit the pages in the stub. */
    328         size_t cbStub = KLDR_MIN(g_cbStub - offStub, cb);
    329         rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
    330         if (rc)
    331         {
    332             /* Page by page, ignoring errors after the first success. */
    333             while (cbStub > 0)
    334             {
    335                 if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
    336                     rc = 0;
    337                 pv = (void *)((uintptr_t)pv + 0x1000);
    338                 cbStub -= 0x1000;
    339                 cb -= 0x1000;
    340             }
    341             if (rc)
    342             {
    343                 kldrHlpAssert(!rc);
    344                 return rc;
    345             }
    346         }
    347         else
    348         {
    349             cb -= cbStub;
    350             if (!cb)
    351                 return 0;
    352             pv = (void *)((uintptr_t)pv + cbStub);
    353         }
    354     }
    355 
    356     /*
    357      * Free the object.
    358      */
    359     rc = DosFreeMem(pv);
    360     kldrHlpAssert(!rc);
    361     return rc;
    362 
    363 #elif defined(__WIN__)
    364     /*
    365      * Free the object.
    366      */
    367     int rc = 0;
    368     if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
    369     {
    370         rc = GetLastError();
    371         kldrHlpAssert(0);
    372     }
    373     return rc;
    374 
    375 #else
    376 # error "port me"
    377 #endif
    378 }
    37943
    38044
     
    503167
    504168/**
    505  * Get the pointer to the filename part of the name.
    506  *
    507  * @returns Pointer to where the filename starts within the string pointed to by pszFilename.
    508  * @returns Pointer to the terminator char if no filename.
    509  * @param   pszFilename     The filename to parse.
    510  */
    511 char   *kldrHlpGetFilename(const char *pszFilename)
    512 {
    513     const char *pszLast = NULL;
    514     for (;;)
    515     {
    516         char ch = *pszFilename;
    517 #if defined(__OS2__) || defined(__WIN__)
    518         if (ch == '/' || ch == '\\' || ch == ':')
    519         {
    520             while ((ch = *++pszFilename) == '/' || ch == '\\' || ch == ':')
    521                 /* nothing */;
    522             pszLast = pszFilename;
    523         }
    524 #else
    525         if (ch == '/')
    526         {
    527             while ((ch = *++pszFilename) == '/')
    528                 /* betsuni */;
    529             pszLast = pszFilename;
    530         }
    531 #endif
    532         if (!ch)
    533             return (char *)(pszLast ? pszLast : pszFilename);
    534         pszFilename++;
    535     }
    536 }
    537 
    538 
    539 /**
    540  * Gets the filename suffix.
    541  *
    542  * @returns Pointer to where the suffix starts within the string pointed to by pszFilename.
    543  * @returns Pointer to the terminator char if no suffix.
    544  * @param   pszFilename     The filename to parse.
    545  */
    546 char   *kldrHlpGetSuff(const char *pszFilename)
    547 {
    548     const char *pszDot = NULL;
    549     pszFilename = kldrHlpGetFilename(pszFilename);
    550     for (;;)
    551     {
    552         char ch = *pszFilename;
    553         if (ch == '.')
    554         {
    555             while ((ch = *++pszFilename) == '.')
    556                 /* nothing */;
    557             if (ch)
    558                 pszDot = pszFilename - 1;
    559         }
    560         if (!ch)
    561             return (char *)(pszDot ? pszDot : pszFilename);
    562         pszFilename++;
    563     }
    564 }
    565 
    566 
    567 /**
    568  * Gets the filename extention.
    569  *
    570  * @returns Pointer to where the extension starts within the string pointed to by pszFilename.
    571  * @returns Pointer to the terminator char if no extension.
    572  * @param   pszFilename     The filename to parse.
    573  */
    574 char   *kldrHlpGetExt(const char *pszFilename)
    575 {
    576     char *psz = kldrHlpGetSuff(pszFilename);
    577     return *psz ? psz + 1 : psz;
    578 }
    579 
    580 
    581 /**
    582  * Checks if this is only a filename or if it contains any kind
    583  * of drive, directory, or server specs.
    584  *
    585  * @returns 1 if this is a filename only.
    586  * @returns 0 of it's isn't only a filename.
    587  * @param   pszFilename     The filename to parse.
    588  */
    589 int kldrHlpIsFilenameOnly(const char *pszFilename)
    590 {
    591     for (;;)
    592     {
    593         const char ch = *pszFilename++;
    594 #if defined(__OS2__) || defined(__WIN__)
    595         if (ch == '/' || ch == '\\' || ch == ':')
    596 #else
    597         if (ch == '/')
    598 #endif
    599             return 0;
    600         if (!ch)
    601             return 1;
    602     }
    603 }
    604 
    605 
    606 /**
    607169 * Terminate the process.
    608170 *
     
    640202    usleep(cMillies * 1000);
    641203#endif
    642 }
    643 
    644 
    645 /**
    646  * Converts an signed integer to an ascii string.
    647  *
    648  * @returns psz.
    649  * @param   psz         Pointer to the output buffer.
    650  * @param   cch         The size of the output buffer.
    651  * @param   lVal        The value.
    652  * @param   iBase       The base to format it. (2,8,10 or 16)
    653  */
    654 char *kldrHlpInt2Ascii(char *psz, size_t cch, long lVal, unsigned iBase)
    655 {
    656     static const char s_szDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    657     char *pszRet = psz;
    658 
    659     if (cch >= (lVal < 0 ? 3U : 2U) && psz)
    660     {
    661         /* prefix */
    662         if (lVal < 0)
    663         {
    664             *psz++ = '-';
    665             cch--;
    666             lVal = -lVal;
    667         }
    668 
    669         /* the digits */
    670         do
    671         {
    672             *psz++ = s_szDigits[lVal % iBase];
    673             cch--;
    674             lVal /= iBase;
    675         } while (lVal && cch > 1);
    676 
    677         /* overflow indicator */
    678         if (lVal)
    679             psz[-1] = '+';
    680     }
    681     else if (!pszRet)
    682         return pszRet;
    683     else if (cch < 1 || !pszRet)
    684         return pszRet;
    685     else
    686         *psz++ = '+';
    687     *psz = '\0';
    688 
    689     return pszRet;
    690204}
    691205
     
    765279}
    766280
    767 
    768 #ifdef kLdrHlpStrChr_needed
    769 char   *kLdrHlpStrChr(const char *psz, int ch)
    770 {
    771     while (*psz)
    772     {
    773         if (*psz == ch)
    774             return (char *)psz;
    775         psz++;
    776     }
    777     return NULL;
    778 }
    779 #endif
    780 
    781 
    782 #ifdef kLdrHlpMemChr_needed
    783 void   *kLdrHlpMemChr(const void *pv, int ch, size_t cb)
    784 {
    785     const uint8_t *pb = (const uint8_t *)pv;
    786     const uint8_t  b = (uint8_t)ch;
    787     while (cb-- > 0)
    788     {
    789         if (*pb == b)
    790             return (void *)pb;
    791         pb++;
    792     }
    793     return NULL;
    794 }
    795 #endif
    796 
    797 
    798 #ifdef kLdrHlpMemMove_needed
    799 void   *kLdrHlpMemMove(void *pv1, const void *pv2, size_t cb)
    800 {
    801     uint8_t        *pbDst = (uint8_t *)pv1;
    802     const uint8_t  *pbSrc = (const uint8_t *)pv2;
    803     while (cb-- > 0)
    804     {
    805         const uint8_t b = *pbSrc++;
    806         *pbDst++ = b;
    807     }
    808     return pv1;
    809 }
    810 #endif
    811 
    812 
    813 int     kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb)
    814 {
    815     const uint8_t *pb1 = (const uint8_t *)pv1;
    816     const uint8_t *pb2 = (const uint8_t *)pv2;
    817     while (cb-- > 0)
    818     {
    819         if (*pb1 != *pb2)
    820         {
    821             const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
    822             const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
    823             if (u1 != u2)
    824                 return (int)*pb1 - (int)*pb2;
    825         }
    826         pb1++;
    827         pb2++;
    828     }
    829     return 0;
    830 }
    831 
    832 
    833 int     kLdrHlpStrIComp(const char *pv1, const char *pv2)
    834 {
    835     const uint8_t *pb1 = (const uint8_t *)pv1;
    836     const uint8_t *pb2 = (const uint8_t *)pv2;
    837     for (;;)
    838     {
    839         if (*pb1 != *pb2)
    840         {
    841             const uint8_t u1 = *pb1 >= 'a' && *pb1 <= 'z' ? *pb1 - 'a' : *pb1;
    842             const uint8_t u2 = *pb2 >= 'a' && *pb2 <= 'z' ? *pb2 - 'a' : *pb2;
    843             if (u1 != u2)
    844                 return (int)*pb1 - (int)*pb2;
    845         }
    846         if (!*pb1)
    847             break;
    848         pb1++;
    849         pb2++;
    850     }
    851     return 0;
    852 }
    853 
    854 
    855 #ifdef kLdrHlpStrNComp_needed
    856 int     kLdrHlpStrNComp(const char *psz1, const char *psz2, size_t cch)
    857 {
    858     while (cch-- > 0)
    859     {
    860         if (*psz1 != *psz2)
    861             return (int)*psz1 - (int)*psz2;
    862         if (!*psz1)
    863             break;
    864         psz1++;
    865         psz2++;
    866     }
    867     return 0;
    868 }
    869 #endif
    870 
Note: See TracChangeset for help on using the changeset viewer.