LCOV - app.info - js/src/ctypes/libffi/src/closures.c

LCOV - code coverage report
| Current view: | directory - js/src/ctypes/libffi/src - closures.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 137 | 0 | 0.0 %
| Date: | 2012-04-07 | Functions: | 12 | 0 | 0.0 %

           1                 : /* -----------------------------------------------------------------------
           2                 :    closures.c - Copyright (c) 2007  Red Hat, Inc.
           3                 :    Copyright (C) 2007, 2009 Free Software Foundation, Inc
           4                 :
           5                 :    Code to allocate and deallocate memory for closures.
           6                 :
           7                 :    Permission is hereby granted, free of charge, to any person obtaining
           8                 :    a copy of this software and associated documentation files (the
           9                 :    ``Software''), to deal in the Software without restriction, including
          10                 :    without limitation the rights to use, copy, modify, merge, publish,
          11                 :    distribute, sublicense, and/or sell copies of the Software, and to
          12                 :    permit persons to whom the Software is furnished to do so, subject to
          13                 :    the following conditions:
          14                 :
          15                 :    The above copyright notice and this permission notice shall be included
          16                 :    in all copies or substantial portions of the Software.
          17                 :
          18                 :    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
          19                 :    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
          20                 :    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
          21                 :    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
          22                 :    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
          23                 :    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
          24                 :    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
          25                 :    DEALINGS IN THE SOFTWARE.
          26                 :    ----------------------------------------------------------------------- */
          27                 :
          28                 : #if defined __linux__ && !defined _GNU_SOURCE
          29                 : #define _GNU_SOURCE 1
          30                 : #endif
          31                 :
          32                 : #include <ffi.h>
          33                 : #include <ffi_common.h>
          34                 :
          35                 : #ifndef FFI_MMAP_EXEC_WRIT
          36                 : # if __gnu_linux__
          37                 : /* This macro indicates it may be forbidden to map anonymous memory
          38                 :    with both write and execute permission.  Code compiled when this
          39                 :    option is defined will attempt to map such pages once, but if it
          40                 :    fails, it falls back to creating a temporary file in a writable and
          41                 :    executable filesystem and mapping pages from it into separate
          42                 :    locations in the virtual memory space, one location writable and
          43                 :    another executable.  */
          44                 : #  define FFI_MMAP_EXEC_WRIT 1
          45                 : #  define HAVE_MNTENT 1
          46                 : # endif
          47                 : # if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
          48                 : /* Windows systems may have Data Execution Protection (DEP) enabled,
          49                 :    which requires the use of VirtualMalloc/VirtualFree to alloc/free
          50                 :    executable memory. */
          51                 : #  define FFI_MMAP_EXEC_WRIT 1
          52                 : # endif
          53                 : #endif
          54                 :
          55                 : #if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
          56                 : # ifdef __linux__
          57                 : /* When defined to 1 check for SELinux and if SELinux is active,
          58                 :    don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
          59                 :    might cause audit messages.  */
          60                 : #  define FFI_MMAP_EXEC_SELINUX 1
          61                 : # endif
          62                 : #endif
          63                 :
          64                 : #if FFI_CLOSURES
          65                 :
          66                 : # if FFI_MMAP_EXEC_WRIT
          67                 :
          68                 : #define USE_LOCKS 1
          69                 : #define USE_DL_PREFIX 1
          70                 : #ifdef __GNUC__
          71                 : #ifndef USE_BUILTIN_FFS
          72                 : #define USE_BUILTIN_FFS 1
          73                 : #endif
          74                 : #endif
          75                 :
          76                 : /* We need to use mmap, not sbrk.  */
          77                 : #define HAVE_MORECORE 0
          78                 :
          79                 : /* We could, in theory, support mremap, but it wouldn't buy us anything.  */
          80                 : #define HAVE_MREMAP 0
          81                 :
          82                 : /* We have no use for this, so save some code and data.  */
          83                 : #define NO_MALLINFO 1
          84                 :
          85                 : /* We need all allocations to be in regular segments, otherwise we
          86                 :    lose track of the corresponding code address.  */
          87                 : #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
          88                 :
          89                 : /* Don't allocate more than a page unless needed.  */
          90                 : #define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
          91                 :
          92                 : #if FFI_CLOSURE_TEST
          93                 : /* Don't release single pages, to avoid a worst-case scenario of
          94                 :    continuously allocating and releasing single pages, but release
          95                 :    pairs of pages, which should do just as well given that allocations
          96                 :    are likely to be small.  */
          97                 : #define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
          98                 : #endif
          99                 :
         100                 : #include <sys/types.h>
         101                 : #include <sys/stat.h>
         102                 : #include <fcntl.h>
         103                 : #include <errno.h>
         104                 : #ifndef _MSC_VER
         105                 : #include <unistd.h>
         106                 : #endif
         107                 : #include <string.h>
         108                 : #include <stdio.h>
         109                 : #if !defined(X86_WIN32) && !defined(X86_WIN64)
         110                 : #ifdef HAVE_MNTENT
         111                 : #include <mntent.h>
         112                 : #endif /* HAVE_MNTENT */
         113                 : #include <sys/param.h>
         114                 : #include <pthread.h>
         115                 :
         116                 : /* We don't want sys/mman.h to be included after we redefine mmap and
         117                 :    dlmunmap.  */
         118                 : #include <sys/mman.h>
         119                 : #define LACKS_SYS_MMAN_H 1
         120                 :
         121                 : #if FFI_MMAP_EXEC_SELINUX
         122                 : #include <sys/statfs.h>
         123                 : #include <stdlib.h>
         124                 :
         125                 : static int selinux_enabled = -1;
         126                 :
         127                 : static int
         128               0 : selinux_enabled_check (void)
         129                 : {
         130                 :   struct statfs sfs;
         131                 :   FILE *f;
         132               0 :   char *buf = NULL;
         133               0 :   size_t len = 0;
         134                 :
         135               0 :   if (statfs ("/selinux", &sfs) >= 0
         136               0 :       && (unsigned int) sfs.f_type == 0xf97cff8cU)
         137               0 :     return 1;
         138               0 :   f = fopen ("/proc/mounts", "r");
         139               0 :   if (f == NULL)
         140               0 :     return 0;
         141               0 :   while (getline (&buf, &len, f) >= 0)
         142                 :     {
         143               0 :       char *p = strchr (buf, ' ');
         144               0 :       if (p == NULL)
         145               0 :         break;
         146               0 :       p = strchr (p + 1, ' ');
         147               0 :       if (p == NULL)
         148               0 :         break;
         149               0 :       if (strncmp (p + 1, "selinuxfs ", 10) == 0)
         150                 :         {
         151               0 :           free (buf);
         152               0 :           fclose (f);
         153               0 :           return 1;
         154                 :         }
         155                 :     }
         156               0 :   free (buf);
         157               0 :   fclose (f);
         158               0 :   return 0;
         159                 : }
         160                 :
         161                 : #define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
         162                 :                               : (selinux_enabled = selinux_enabled_check ()))
         163                 :
         164                 : #else
         165                 :
         166                 : #define is_selinux_enabled() 0
         167                 :
         168                 : #endif /* !FFI_MMAP_EXEC_SELINUX */
         169                 :
         170                 : #elif defined (__CYGWIN__)
         171                 :
         172                 : #include <sys/mman.h>
         173                 :
         174                 : /* Cygwin is Linux-like, but not quite that Linux-like.  */
         175                 : #define is_selinux_enabled() 0
         176                 :
         177                 : #endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
         178                 :
         179                 : /* Declare all functions defined in dlmalloc.c as static.  */
         180                 : static void *dlmalloc(size_t);
         181                 : static void dlfree(void*);
         182                 : static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
         183                 : static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
         184                 : static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
         185                 : static void *dlvalloc(size_t) MAYBE_UNUSED;
         186                 : static int dlmallopt(int, int) MAYBE_UNUSED;
         187                 : static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
         188                 : static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
         189                 : static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
         190                 : static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
         191                 : static void *dlpvalloc(size_t) MAYBE_UNUSED;
         192                 : static int dlmalloc_trim(size_t) MAYBE_UNUSED;
         193                 : static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
         194                 : static void dlmalloc_stats(void) MAYBE_UNUSED;
         195                 :
         196                 : #if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
         197                 : /* Use these for mmap and munmap within dlmalloc.c.  */
         198                 : static void *dlmmap(void *, size_t, int, int, int, off_t);
         199                 : static int dlmunmap(void *, size_t);
         200                 : #endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
         201                 :
         202                 : #define mmap dlmmap
         203                 : #define munmap dlmunmap
         204                 :
         205                 : #include "dlmalloc.c"
         206                 :
         207                 : #undef mmap
         208                 : #undef munmap
         209                 :
         210                 : #if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
         211                 :
         212                 : /* A mutex used to synchronize access to *exec* variables in this file.  */
         213                 : static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
         214                 :
         215                 : /* A file descriptor of a temporary file from which we'll map
         216                 :    executable pages.  */
         217                 : static int execfd = -1;
         218                 :
         219                 : /* The amount of space already allocated from the temporary file.  */
         220                 : static size_t execsize = 0;
         221                 :
         222                 : /* Open a temporary file name, and immediately unlink it.  */
         223                 : static int
         224               0 : open_temp_exec_file_name (char *name)
         225                 : {
         226               0 :   int fd = mkstemp (name);
         227                 :
         228               0 :   if (fd != -1)
         229               0 :     unlink (name);
         230                 :
         231               0 :   return fd;
         232                 : }
         233                 :
         234                 : /* Open a temporary file in the named directory.  */
         235                 : static int
         236               0 : open_temp_exec_file_dir (const char *dir)
         237                 : {
         238                 :   static const char suffix[] = "/ffiXXXXXX";
         239               0 :   int lendir = strlen (dir);
         240               0 :   char *tempname = __builtin_alloca (lendir + sizeof (suffix));
         241                 :
         242               0 :   if (!tempname)
         243               0 :     return -1;
         244                 :
         245               0 :   memcpy (tempname, dir, lendir);
         246               0 :   memcpy (tempname + lendir, suffix, sizeof (suffix));
         247                 :
         248               0 :   return open_temp_exec_file_name (tempname);
         249                 : }
         250                 :
         251                 : /* Open a temporary file in the directory in the named environment
         252                 :    variable.  */
         253                 : static int
         254               0 : open_temp_exec_file_env (const char *envvar)
         255                 : {
         256               0 :   const char *value = getenv (envvar);
         257                 :
         258               0 :   if (!value)
         259               0 :     return -1;
         260                 :
         261               0 :   return open_temp_exec_file_dir (value);
         262                 : }
         263                 :
         264                 : #ifdef HAVE_MNTENT
         265                 : /* Open a temporary file in an executable and writable mount point
         266                 :    listed in the mounts file.  Subsequent calls with the same mounts
         267                 :    keep searching for mount points in the same file.  Providing NULL
         268                 :    as the mounts file closes the file.  */
         269                 : static int
         270               0 : open_temp_exec_file_mnt (const char *mounts)
         271                 : {
         272                 :   static const char *last_mounts;
         273                 :   static FILE *last_mntent;
         274                 :
         275               0 :   if (mounts != last_mounts)
         276                 :     {
         277               0 :       if (last_mntent)
         278               0 :         endmntent (last_mntent);
         279                 :
         280               0 :       last_mounts = mounts;
         281                 :
         282               0 :       if (mounts)
         283               0 :         last_mntent = setmntent (mounts, "r");
         284                 :       else
         285               0 :         last_mntent = NULL;
         286                 :     }
         287                 :
         288               0 :   if (!last_mntent)
         289               0 :     return -1;
         290                 :
         291                 :   for (;;)
         292                 :     {
         293                 :       int fd;
         294                 :       struct mntent mnt;
         295                 :       char buf[MAXPATHLEN * 3];
         296                 :
         297               0 :       if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)))
         298               0 :         return -1;
         299                 :
         300               0 :       if (hasmntopt (&mnt, "ro")
         301               0 :           || hasmntopt (&mnt, "noexec")
         302               0 :           || access (mnt.mnt_dir, W_OK))
         303               0 :         continue;
         304                 :
         305               0 :       fd = open_temp_exec_file_dir (mnt.mnt_dir);
         306                 :
         307               0 :       if (fd != -1)
         308               0 :         return fd;
         309               0 :     }
         310                 : }
         311                 : #endif /* HAVE_MNTENT */
         312                 :
         313                 : /* Instructions to look for a location to hold a temporary file that
         314                 :    can be mapped in for execution.  */
         315                 : static struct
         316                 : {
         317                 :   int (*func)(const char *);
         318                 :   const char *arg;
         319                 :   int repeat;
         320                 : } open_temp_exec_file_opts[] = {
         321                 :   { open_temp_exec_file_env, "TMPDIR", 0 },
         322                 :   { open_temp_exec_file_dir, "/tmp", 0 },
         323                 :   { open_temp_exec_file_dir, "/var/tmp", 0 },
         324                 :   { open_temp_exec_file_dir, "/dev/shm", 0 },
         325                 :   { open_temp_exec_file_env, "HOME", 0 },
         326                 : #ifdef HAVE_MNTENT
         327                 :   { open_temp_exec_file_mnt, "/etc/mtab", 1 },
         328                 :   { open_temp_exec_file_mnt, "/proc/mounts", 1 },
         329                 : #endif /* HAVE_MNTENT */
         330                 : };
         331                 :
         332                 : /* Current index into open_temp_exec_file_opts.  */
         333                 : static int open_temp_exec_file_opts_idx = 0;
         334                 :
         335                 : /* Reset a current multi-call func, then advances to the next entry.
         336                 :    If we're at the last, go back to the first and return nonzero,
         337                 :    otherwise return zero.  */
         338                 : static int
         339               0 : open_temp_exec_file_opts_next (void)
         340                 : {
         341               0 :   if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
         342               0 :     open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
         343                 :
         344               0 :   open_temp_exec_file_opts_idx++;
         345               0 :   if (open_temp_exec_file_opts_idx
         346               0 :       == (sizeof (open_temp_exec_file_opts)
         347                 :           / sizeof (*open_temp_exec_file_opts)))
         348                 :     {
         349               0 :       open_temp_exec_file_opts_idx = 0;
         350               0 :       return 1;
         351                 :     }
         352                 :
         353               0 :   return 0;
         354                 : }
         355                 :
         356                 : /* Return a file descriptor of a temporary zero-sized file in a
         357                 :    writable and exexutable filesystem.  */
         358                 : static int
         359               0 : open_temp_exec_file (void)
         360                 : {
         361                 :   int fd;
         362                 :
         363                 :   do
         364                 :     {
         365               0 :       fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
         366               0 :         (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
         367                 :
         368               0 :       if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
         369               0 :           || fd == -1)
         370                 :         {
         371               0 :           if (open_temp_exec_file_opts_next ())
         372               0 :             break;
         373                 :         }
         374                 :     }
         375               0 :   while (fd == -1);
         376                 :
         377               0 :   return fd;
         378                 : }
         379                 :
         380                 : /* Map in a chunk of memory from the temporary exec file into separate
         381                 :    locations in the virtual memory address space, one writable and one
         382                 :    executable.  Returns the address of the writable portion, after
         383                 :    storing an offset to the corresponding executable portion at the
         384                 :    last word of the requested chunk.  */
         385                 : static void *
         386               0 : dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
         387                 : {
         388                 :   void *ptr;
         389                 :
         390               0 :   if (execfd == -1)
         391                 :     {
         392               0 :       open_temp_exec_file_opts_idx = 0;
         393                 :     retry_open:
         394               0 :       execfd = open_temp_exec_file ();
         395               0 :       if (execfd == -1)
         396               0 :         return MFAIL;
         397                 :     }
         398                 :
         399               0 :   offset = execsize;
         400                 :
         401               0 :   if (ftruncate (execfd, offset + length))
         402               0 :     return MFAIL;
         403                 :
         404               0 :   flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
         405               0 :   flags |= MAP_SHARED;
         406                 :
         407               0 :   ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
         408                 :               flags, execfd, offset);
         409               0 :   if (ptr == MFAIL)
         410                 :     {
         411               0 :       if (!offset)
         412                 :         {
         413               0 :           close (execfd);
         414               0 :           goto retry_open;
         415                 :         }
         416               0 :       ftruncate (execfd, offset);
         417               0 :       return MFAIL;
         418                 :     }
         419               0 :   else if (!offset
         420               0 :            && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
         421               0 :     open_temp_exec_file_opts_next ();
         422                 :
         423               0 :   start = mmap (start, length, prot, flags, execfd, offset);
         424                 :
         425               0 :   if (start == MFAIL)
         426                 :     {
         427               0 :       munmap (ptr, length);
         428               0 :       ftruncate (execfd, offset);
         429               0 :       return start;
         430                 :     }
         431                 :
         432               0 :   mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
         433                 :
         434               0 :   execsize += length;
         435                 :
         436               0 :   return start;
         437                 : }
         438                 :
         439                 : /* Map in a writable and executable chunk of memory if possible.
         440                 :    Failing that, fall back to dlmmap_locked.  */
         441                 : static void *
         442               0 : dlmmap (void *start, size_t length, int prot,
         443                 :         int flags, int fd, off_t offset)
         444                 : {
         445                 :   void *ptr;
         446                 :
         447                 :   assert (start == NULL && length % malloc_getpagesize == 0
         448                 :           && prot == (PROT_READ | PROT_WRITE)
         449                 :           && flags == (MAP_PRIVATE | MAP_ANONYMOUS)
         450                 :           && fd == -1 && offset == 0);
         451                 :
         452                 : #if FFI_CLOSURE_TEST
         453                 :   printf ("mapping in %zi\n", length);
         454                 : #endif
         455                 :
         456               0 :   if (execfd == -1 && !is_selinux_enabled ())
         457                 :     {
         458               0 :       ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
         459                 :
         460               0 :       if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
         461                 :         /* Cool, no need to mess with separate segments.  */
         462               0 :         return ptr;
         463                 :
         464                 :       /* If MREMAP_DUP is ever introduced and implemented, try mmap
         465                 :          with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
         466                 :          MREMAP_DUP and prot at this point.  */
         467                 :     }
         468                 :
         469               0 :   if (execsize == 0 || execfd == -1)
         470                 :     {
         471               0 :       pthread_mutex_lock (&open_temp_exec_file_mutex);
         472               0 :       ptr = dlmmap_locked (start, length, prot, flags, offset);
         473               0 :       pthread_mutex_unlock (&open_temp_exec_file_mutex);
         474                 :
         475               0 :       return ptr;
         476                 :     }
         477                 :
         478               0 :   return dlmmap_locked (start, length, prot, flags, offset);
         479                 : }
         480                 :
         481                 : /* Release memory at the given address, as well as the corresponding
         482                 :    executable page if it's separate.  */
         483                 : static int
         484               0 : dlmunmap (void *start, size_t length)
         485                 : {
         486                 :   /* We don't bother decreasing execsize or truncating the file, since
         487                 :      we can't quite tell whether we're unmapping the end of the file.
         488                 :      We don't expect frequent deallocation anyway.  If we did, we
         489                 :      could locate pages in the file by writing to the pages being
         490                 :      deallocated and checking that the file contents change.
         491                 :      Yuck.  */
         492               0 :   msegmentptr seg = segment_holding (gm, start);
         493                 :   void *code;
         494                 :
         495                 : #if FFI_CLOSURE_TEST
         496                 :   printf ("unmapping %zi\n", length);
         497                 : #endif
         498                 :
         499               0 :   if (seg && (code = add_segment_exec_offset (start, seg)) != start)
         500                 :     {
         501               0 :       int ret = munmap (code, length);
         502               0 :       if (ret)
         503               0 :         return ret;
         504                 :     }
         505                 :
         506               0 :   return munmap (start, length);
         507                 : }
         508                 :
         509                 : #if FFI_CLOSURE_FREE_CODE
         510                 : /* Return segment holding given code address.  */
         511                 : static msegmentptr
         512                 : segment_holding_code (mstate m, char* addr)
         513                 : {
         514                 :   msegmentptr sp = &m->seg;
         515                 :   for (;;) {
         516                 :     if (addr >= add_segment_exec_offset (sp->base, sp)
         517                 :         && addr < add_segment_exec_offset (sp->base, sp) + sp->size)
         518                 :       return sp;
         519                 :     if ((sp = sp->next) == 0)
         520                 :       return 0;
         521                 :   }
         522                 : }
         523                 : #endif
         524                 :
         525                 : #endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
         526                 :
         527                 : /* Allocate a chunk of memory with the given size.  Returns a pointer
         528                 :    to the writable address, and sets *CODE to the executable
         529                 :    corresponding virtual address.  */
         530                 : void *
         531               0 : ffi_closure_alloc (size_t size, void **code)
         532                 : {
         533                 :   void *ptr;
         534                 :
         535               0 :   if (!code)
         536               0 :     return NULL;
         537                 :
         538               0 :   ptr = dlmalloc (size);
         539                 :
         540               0 :   if (ptr)
         541                 :     {
         542               0 :       msegmentptr seg = segment_holding (gm, ptr);
         543                 :
         544               0 :       *code = add_segment_exec_offset (ptr, seg);
         545                 :     }
         546                 :
         547               0 :   return ptr;
         548                 : }
         549                 :
         550                 : /* Release a chunk of memory allocated with ffi_closure_alloc.  If
         551                 :    FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
         552                 :    writable or the executable address given.  Otherwise, only the
         553                 :    writable address can be provided here.  */
         554                 : void
         555               0 : ffi_closure_free (void *ptr)
         556                 : {
         557                 : #if FFI_CLOSURE_FREE_CODE
         558                 :   msegmentptr seg = segment_holding_code (gm, ptr);
         559                 :
         560                 :   if (seg)
         561                 :     ptr = sub_segment_exec_offset (ptr, seg);
         562                 : #endif
         563                 :
         564               0 :   dlfree (ptr);
         565               0 : }
         566                 :
         567                 :
         568                 : #if FFI_CLOSURE_TEST
         569                 : /* Do some internal sanity testing to make sure allocation and
         570                 :    deallocation of pages are working as intended.  */
         571                 : int main ()
         572                 : {
         573                 :   void *p[3];
         574                 : #define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
         575                 : #define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
         576                 :   GET (0, malloc_getpagesize / 2);
         577                 :   GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
         578                 :   PUT (1);
         579                 :   GET (1, 2 * malloc_getpagesize);
         580                 :   GET (2, malloc_getpagesize / 2);
         581                 :   PUT (1);
         582                 :   PUT (0);
         583                 :   PUT (2);
         584                 :   return 0;
         585                 : }
         586                 : #endif /* FFI_CLOSURE_TEST */
         587                 : # else /* ! FFI_MMAP_EXEC_WRIT */
         588                 :
         589                 : /* On many systems, memory returned by malloc is writable and
         590                 :    executable, so just use it.  */
         591                 :
         592                 : #include <stdlib.h>
         593                 :
         594                 : void *
         595                 : ffi_closure_alloc (size_t size, void **code)
         596                 : {
         597                 :   if (!code)
         598                 :     return NULL;
         599                 :
         600                 :   return *code = malloc (size);
         601                 : }
         602                 :
         603                 : void
         604                 : ffi_closure_free (void *ptr)
         605                 : {
         606                 :   free (ptr);
         607                 : }
         608                 :
         609                 : # endif /* ! FFI_MMAP_EXEC_WRIT */
         610                 : #endif /* FFI_CLOSURES */

Generated by: LCOV version 1.7