/********************************************************* * Copyright (C) 2009-2015 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation version 2.1 and no later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * *********************************************************/ /* * utilMem.c -- * * misc util functions */ #ifdef _WIN32 #include #endif #include #include #include #include "vm_assert.h" #include "util.h" #ifdef __APPLE__ #include #if !defined TARGET_OS_IPHONE #define TARGET_OS_IPHONE 0 #endif #endif static NORETURN void UtilAllocationFailure0(void); static NORETURN void UtilAllocationFailure1(int bugNumber, const char *file, int lineno); static void UtilAllocationFailure0(void) { Panic("Unrecoverable memory allocation failure\n"); } static void UtilAllocationFailure1(int bugNumber, const char *file, int lineno) { if (bugNumber == -1) { Panic("Unrecoverable memory allocation failure at %s:%d\n", file, lineno); } else { Panic("Unrecoverable memory allocation failure at %s:%d. Bug " "number: %d\n", file, lineno, bugNumber); } } /* *----------------------------------------------------------------------------- * * UtilSafeMalloc0 -- * UtilSafeMalloc1 -- * Helper function for malloc * * Results: * Pointer to the dynamically allocated memory. * * Side effects: * May Panic if ran out of memory. * *----------------------------------------------------------------------------- */ void * UtilSafeMalloc0(size_t size) // IN: { void *result = malloc(size); if (result == NULL && size != 0) { UtilAllocationFailure0(); } return result; } void * UtilSafeMalloc1(size_t size, // IN: int bugNumber, // IN: const char *file, // IN: int lineno) // IN: { void *result = malloc(size); if (result == NULL && size != 0) { UtilAllocationFailure1(bugNumber, file, lineno); } return result; } /* *----------------------------------------------------------------------------- * * UtilSafeRealloc0 -- * UtilSafeRealloc1 -- * Helper function for realloc * * Results: * Pointer to the dynamically allocated memory. * * Side effects: * May Panic if ran out of memory. * *----------------------------------------------------------------------------- */ void * UtilSafeRealloc0(void *ptr, // IN: size_t size) // IN: { void *result = realloc(ptr, size); if (result == NULL && size != 0) { UtilAllocationFailure0(); } return result; } void * UtilSafeRealloc1(void *ptr, // IN: size_t size, // IN: int bugNumber, // IN: const char *file, // IN: int lineno) // IN: { void *result = realloc(ptr, size); if (result == NULL && size != 0) { UtilAllocationFailure1(bugNumber, file, lineno); } return result; } /* *----------------------------------------------------------------------------- * * UtilSafeCalloc0 -- * UtilSafeCalloc1 -- * Helper function for calloc * * Results: * Pointer to the dynamically allocated memory. * * Side effects: * May Panic if ran out of memory. * *----------------------------------------------------------------------------- */ void * UtilSafeCalloc0(size_t nmemb, // IN: size_t size) // IN: { void *result = calloc(nmemb, size); if (result == NULL && nmemb != 0 && size != 0) { UtilAllocationFailure0(); } return result; } void * UtilSafeCalloc1(size_t nmemb, // IN: size_t size, // IN: int bugNumber, // IN: const char *file, // IN: int lineno) // IN: { void *result = calloc(nmemb, size); if (result == NULL && nmemb != 0 && size != 0) { UtilAllocationFailure1(bugNumber, file, lineno); } return result; } /* *----------------------------------------------------------------------------- * * Util_SafeStrdup -- * Helper function for strdup * * Results: * Pointer to the dynamically allocated, duplicate string * * Side effects: * May Panic if ran out of memory. * *----------------------------------------------------------------------------- */ char * UtilSafeStrdup0(const char *s) // IN: { char *result; if (s == NULL) { return NULL; } #if defined(_WIN32) if ((result = _strdup(s)) == NULL) { #else if ((result = strdup(s)) == NULL) { #endif UtilAllocationFailure0(); } return result; } char * UtilSafeStrdup1(const char *s, // IN: int bugNumber, // IN: const char *file, // IN: int lineno) // IN: { char *result; if (s == NULL) { return NULL; } #if defined(_WIN32) if ((result = _strdup(s)) == NULL) { #else if ((result = strdup(s)) == NULL) { #endif UtilAllocationFailure1(bugNumber, file, lineno); } return result; } /* *----------------------------------------------------------------------------- * * Util_SafeStrndup -- * * Returns a string consisting of first n characters of 's' if 's' has * length >= 'n', otherwise returns a string duplicate of 's'. * * Results: * Pointer to the duplicated string. * * Side effects: * May Panic if ran out of memory. * *----------------------------------------------------------------------------- */ char * UtilSafeStrndup0(const char *s, // IN: size_t n) // IN: { size_t size; char *copy; const char *null; size_t newSize; if (s == NULL) { return NULL; } null = memchr(s, '\0', n); size = null ? (size_t)(null - s) : n; newSize = size + 1; if (newSize < size) { // Prevent integer overflow copy = NULL; } else { copy = malloc(newSize); } if (copy == NULL) { UtilAllocationFailure0(); } copy[size] = '\0'; return (char *) memcpy(copy, s, size); } char * UtilSafeStrndup1(const char *s, // IN: size_t n, // IN: int bugNumber, // IN: const char *file, // IN: int lineno) // IN: { size_t size; char *copy; const char *null; size_t newSize; if (s == NULL) { return NULL; } null = memchr(s, '\0', n); size = null ? (size_t)(null - s) : n; newSize = size + 1; if (newSize < size) { // Prevent integer overflow copy = NULL; } else { copy = malloc(newSize); } if (copy == NULL) { UtilAllocationFailure1(bugNumber, file, lineno); } copy[size] = '\0'; return (char *) memcpy(copy, s, size); } void * Util_Memcpy(void *dest, const void *src, size_t count) { #if defined(__x86_64__) || defined(__i386__) uintptr_t align = ((uintptr_t)dest | (uintptr_t)src | count); #if defined __GNUC__ #if defined(__x86_64__) size_t dummy0; void *dummy1; void *dummy2; if ((align & 7) == 0) { __asm__ __volatile__("\t" "cld" "\n\t" "rep ; movsq" "\n" : "=c" (dummy0), "=D" (dummy1), "=S" (dummy2) : "0" (count >> 3), "1" (dest), "2" (src) : "memory", "cc" ); return dest; } else if ((align & 3) == 0) { __asm__ __volatile__("\t" "cld" "\n\t" "rep ; movsd" "\n" : "=c" (dummy0), "=D" (dummy1), "=S" (dummy2) : "0" (count >> 2), "1" (dest), "2" (src) : "memory", "cc" ); return dest; } #elif defined(__i386__) size_t dummy0; void *dummy1; void *dummy2; if ((align & 3) == 0) { __asm__ __volatile__("\t" "cld" "\n\t" "rep ; movsd" "\n" : "=c" (dummy0), "=D" (dummy1), "=S" (dummy2) : "0" (count >> 2), "1" (dest), "2" (src) : "memory", "cc" ); return dest; } #endif #elif defined _MSC_VER #if defined(__x86_64__) if ((align & 7) == 0) { __movsq((uint64 *)dest, (uint64 *)src, count >> 3); return dest; } else if ((align & 3) == 0) { __movsd((unsigned long *)dest, (unsigned long *)src, count >> 2); return dest; } #elif defined(__i386__) if ((((uintptr_t)dest | (uintptr_t)src | count) & 3) == 0) { __movsd((unsigned long *)dest, (unsigned long *)src, count >> 2); return dest; } #endif #endif #endif memcpy(dest, src, count); return dest; }