diff options
Diffstat (limited to 'libmudflap/mf-hooks3.c')
-rw-r--r-- | libmudflap/mf-hooks3.c | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/libmudflap/mf-hooks3.c b/libmudflap/mf-hooks3.c deleted file mode 100644 index 552cbb5..0000000 --- a/libmudflap/mf-hooks3.c +++ /dev/null @@ -1,284 +0,0 @@ -/* Mudflap: narrow-pointer bounds-checking by tree rewriting. - Copyright (C) 2002-2013 Free Software Foundation, Inc. - Contributed by Frank Ch. Eigler <fche@redhat.com> - and Graydon Hoare <graydon@redhat.com> - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC 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 GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - - -#include "config.h" - -#ifndef HAVE_SOCKLEN_T -#define socklen_t int -#endif - -/* These attempt to coax various unix flavours to declare all our - needed tidbits in the system headers. */ -#if !defined(__FreeBSD__) && !defined(__APPLE__) -#define _POSIX_SOURCE -#endif /* Some BSDs break <sys/socket.h> if this is defined. */ -#define _GNU_SOURCE -#define _XOPEN_SOURCE -#define _BSD_TYPES -#define __EXTENSIONS__ -#define _ALL_SOURCE -#define _LARGE_FILE_API -#define _XOPEN_SOURCE_EXTENDED 1 -#define _REENTRANT - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <assert.h> -#include <errno.h> -#include <stdbool.h> - -#include "mf-runtime.h" -#include "mf-impl.h" - -#ifdef _MUDFLAP -#error "Do not compile this file with -fmudflap!" -#endif - -#ifndef LIBMUDFLAPTH -#error "pthreadstuff is to be included only in libmudflapth" -#endif - -/* ??? Why isn't this done once in the header files. */ -DECLARE(void *, malloc, size_t sz); -DECLARE(void, free, void *ptr); -DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, - void * (*start) (void *), void *arg); - - -/* Multithreading support hooks. */ - - -#if !defined(HAVE_TLS) || defined(USE_EMUTLS) -/* We don't have TLS. Ordinarily we could use pthread keys, but since we're - commandeering malloc/free that presents a few problems. The first is that - we'll recurse from __mf_get_state to pthread_setspecific to malloc back to - __mf_get_state during thread startup. This can be solved with clever uses - of a mutex. The second problem is that thread shutdown is indistinguishable - from thread startup, since libpthread is deallocating our state variable. - I've no good solution for this. - - Which leaves us to handle this mess by totally by hand. */ - -/* Yes, we want this prime. If pthread_t is a pointer, it's almost always - page aligned, and if we use a smaller power of 2, this results in "%N" - being the worst possible hash -- all threads hash to zero. */ -#define LIBMUDFLAPTH_THREADS_MAX 1021 - -struct mf_thread_data -{ - pthread_t self; - unsigned char used_p; - unsigned char state; -}; - -static struct mf_thread_data mf_thread_data[LIBMUDFLAPTH_THREADS_MAX]; -static pthread_mutex_t mf_thread_data_lock = PTHREAD_MUTEX_INITIALIZER; - -#define PTHREAD_HASH(p) ((unsigned long) (p) % LIBMUDFLAPTH_THREADS_MAX) - -static struct mf_thread_data * -__mf_find_threadinfo (int alloc) -{ - pthread_t self = pthread_self (); - unsigned long hash = PTHREAD_HASH (self); - unsigned long rehash; - -#ifdef __alpha__ - /* Alpha has the loosest memory ordering rules of all. We need a memory - barrier to flush the reorder buffer before considering a *read* of a - shared variable. Since we're not always taking a lock, we have to do - this by hand. */ - __sync_synchronize (); -#endif - - rehash = hash; - while (1) - { - if (mf_thread_data[rehash].used_p && mf_thread_data[rehash].self == self) - return &mf_thread_data[rehash]; - - rehash += 7; - if (rehash >= LIBMUDFLAPTH_THREADS_MAX) - rehash -= LIBMUDFLAPTH_THREADS_MAX; - if (rehash == hash) - break; - } - - if (alloc) - { - pthread_mutex_lock (&mf_thread_data_lock); - - rehash = hash; - while (1) - { - if (!mf_thread_data[rehash].used_p) - { - mf_thread_data[rehash].self = self; - __sync_synchronize (); - mf_thread_data[rehash].used_p = 1; - - pthread_mutex_unlock (&mf_thread_data_lock); - return &mf_thread_data[rehash]; - } - - rehash += 7; - if (rehash >= LIBMUDFLAPTH_THREADS_MAX) - rehash -= LIBMUDFLAPTH_THREADS_MAX; - if (rehash == hash) - break; - } - - pthread_mutex_unlock (&mf_thread_data_lock); - } - - return NULL; -} - -enum __mf_state_enum -__mf_get_state (void) -{ - struct mf_thread_data *data = __mf_find_threadinfo (0); - if (data) - return data->state; - - /* If we've never seen this thread before, consider it to be in the - reentrant state. The state gets reset to active for the main thread - in __mf_init, and for child threads in __mf_pthread_spawner. - - The trickiest bit here is that the LinuxThreads pthread_manager thread - should *always* be considered to be reentrant, so that none of our - hooks actually do anything. Why? Because that thread isn't a real - thread from the point of view of the thread library, and so lots of - stuff isn't initialized, leading to SEGV very quickly. Even calling - pthread_self is a bit suspect, but it happens to work. */ - - return reentrant; -} - -void -__mf_set_state (enum __mf_state_enum new_state) -{ - struct mf_thread_data *data = __mf_find_threadinfo (1); - data->state = new_state; -} -#endif - -/* The following two functions are used only with __mf_opts.heur_std_data. - We're interested in recording the location of the thread-local errno - variable. - - Note that this doesn't handle TLS references in general; we have no - visibility into __tls_get_data for when that memory is allocated at - runtime. Hopefully we get to see the malloc or mmap operation that - eventually allocates the backing store. */ - -/* Describe the startup information for a new user thread. */ -struct mf_thread_start_info -{ - /* The user's thread entry point and argument. */ - void * (*user_fn)(void *); - void *user_arg; -}; - - -static void -__mf_pthread_cleanup (void *arg) -{ - if (__mf_opts.heur_std_data) - __mf_unregister (&errno, sizeof (errno), __MF_TYPE_GUESS); - -#if !defined(HAVE_TLS) || defined(USE_EMUTLS) - struct mf_thread_data *data = __mf_find_threadinfo (0); - if (data) - data->used_p = 0; -#endif -} - - -static void * -__mf_pthread_spawner (void *arg) -{ - void *result = NULL; - - __mf_set_state (active); - - /* NB: We could use __MF_TYPE_STATIC here, but we guess that the thread - errno is coming out of some dynamically allocated pool that we already - know of as __MF_TYPE_HEAP. */ - if (__mf_opts.heur_std_data) - __mf_register (&errno, sizeof (errno), __MF_TYPE_GUESS, - "errno area (thread)"); - - /* We considered using pthread_key_t objects instead of these - cleanup stacks, but they were less cooperative with the - interposed malloc hooks in libmudflap. */ - /* ??? The pthread_key_t problem is solved above... */ - pthread_cleanup_push (__mf_pthread_cleanup, NULL); - - /* Extract given entry point and argument. */ - struct mf_thread_start_info *psi = arg; - void * (*user_fn)(void *) = psi->user_fn; - void *user_arg = psi->user_arg; - CALL_REAL (free, arg); - - result = (*user_fn)(user_arg); - - pthread_cleanup_pop (1 /* execute */); - - return result; -} - - -#if PIC -/* A special bootstrap variant. */ -int -__mf_0fn_pthread_create (pthread_t *thr, const pthread_attr_t *attr, - void * (*start) (void *), void *arg) -{ - return -1; -} -#endif - - -#undef pthread_create -WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, - void * (*start) (void *), void *arg) -{ - struct mf_thread_start_info *si; - - TRACE ("pthread_create\n"); - - /* Fill in startup-control fields. */ - si = CALL_REAL (malloc, sizeof (*si)); - si->user_fn = start; - si->user_arg = arg; - - /* Actually create the thread. */ - return CALL_REAL (pthread_create, thr, attr, __mf_pthread_spawner, si); -} |