Changeset 2944 for trunk/kLdr/kLdrHlp.c
- Timestamp:
- Jan 13, 2007, 4:55:40 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrHlp.c
r2898 r2944 2 2 /** @file 3 3 * 4 * kLdr - The Dynamic Loader, Helper Functions.4 * kLdr - The Dynamic Loader, Misc Helper Functions. 5 5 * 6 6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net> … … 41 41 #include <kLdr.h> 42 42 #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 memory53 * 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 #else64 # error "port me"65 #endif66 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 #else86 # error "port me"87 #endif88 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 #else106 # error "port me"107 #endif108 }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 do125 {126 /** @todo check for deadlocks etc. */127 rc = DosRequestMutexSem(g_hmtx, 1000);128 } while ( ( rc == ERROR_TIMEOUT129 || rc == ERROR_SEM_TIMEOUT130 || rc == ERROR_INTERRUPT)131 && i++ < 120);132 }133 return rc;134 135 #elif defined(__WIN__)136 EnterCriticalSection(&g_CritSect);137 return 0;138 139 #else140 # error "port me"141 #endif142 }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 #else159 # error "port me"160 #endif161 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 #endif197 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 else222 {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 #else248 # error "port me"249 #endif250 }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 #else304 # error "port me"305 #endif306 }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 else348 {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 #else376 # error "port me"377 #endif378 }379 43 380 44 … … 503 167 504 168 /** 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 #else525 if (ch == '/')526 {527 while ((ch = *++pszFilename) == '/')528 /* betsuni */;529 pszLast = pszFilename;530 }531 #endif532 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 kind583 * 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 #else597 if (ch == '/')598 #endif599 return 0;600 if (!ch)601 return 1;602 }603 }604 605 606 /**607 169 * Terminate the process. 608 170 * … … 640 202 usleep(cMillies * 1000); 641 203 #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 do671 {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 else686 *psz++ = '+';687 *psz = '\0';688 689 return pszRet;690 204 } 691 205 … … 765 279 } 766 280 767 768 #ifdef kLdrHlpStrChr_needed769 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 #endif780 781 782 #ifdef kLdrHlpMemChr_needed783 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 #endif796 797 798 #ifdef kLdrHlpMemMove_needed799 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 #endif811 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_needed856 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 #endif870
Note:
See TracChangeset
for help on using the changeset viewer.