]> git.saurik.com Git - apple/libc.git/blobdiff - gen/stack_logging.c
Libc-763.11.tar.gz
[apple/libc.git] / gen / stack_logging.c
index 8389420c6f82a588894d02d8732a8b35b7fe5331..42953c89a44b1ecb09d8e6d9faaf45cced1f0ad0 100644 (file)
@@ -1,21 +1,22 @@
 /*
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999, 2000, 2002-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
  * 
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     Bertrand from vmutils -> CF -> System */
 
 #import "stack_logging.h"
 /*     Bertrand from vmutils -> CF -> System */
 
 #import "stack_logging.h"
+#import "malloc_printf.h"
 
 #import <libc.h>
 #import <pthread.h>
 #import <mach/mach.h>
 #include <mach/vm_statistics.h>
 
 #import <libc.h>
 #import <pthread.h>
 #import <mach/mach.h>
 #include <mach/vm_statistics.h>
+#import <malloc/malloc.h>
+#import <stdlib.h>
+#import <CrashReporterClient.h>
 
 extern void spin_lock(int *);
 
 extern void spin_lock(int *);
+extern void spin_unlock(int *);
+extern void thread_stack_pcs(vm_address_t *, unsigned, unsigned *);
 
 
+static inline void *allocate_pages(unsigned) __attribute__((always_inline));
 static inline void *allocate_pages(unsigned bytes) {
     void *address;
     if (vm_allocate(mach_task_self(), (vm_address_t *)&address, bytes, 
                     VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL)| TRUE)) {
 static inline void *allocate_pages(unsigned bytes) {
     void *address;
     if (vm_allocate(mach_task_self(), (vm_address_t *)&address, bytes, 
                     VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL)| TRUE)) {
-       address = 0;
+       malloc_printf("*** out of memory while stack logging\n");
+       CRSetCrashLogMessage("*** out of memory while stack logging\n");
+       abort();
     } 
     return (void *)address;
 }
 
     } 
     return (void *)address;
 }
 
+static inline void deallocate_pages(void *, unsigned) __attribute__((always_inline));
 static inline void deallocate_pages(void *ptr, unsigned bytes) {
     vm_deallocate(mach_task_self(), (vm_address_t)ptr, bytes);
 }
 
 static inline void deallocate_pages(void *ptr, unsigned bytes) {
     vm_deallocate(mach_task_self(), (vm_address_t)ptr, bytes);
 }
 
+static inline void copy_pages(const void *, void *, unsigned) __attribute__((always_inline));
 static inline void copy_pages(const void *source, void *dest, unsigned bytes) {
     if (vm_copy(mach_task_self(), (vm_address_t)source, bytes, (vm_address_t)dest)) memmove(dest, source, bytes);
 }
 
 static inline void copy_pages(const void *source, void *dest, unsigned bytes) {
     if (vm_copy(mach_task_self(), (vm_address_t)source, bytes, (vm_address_t)dest)) memmove(dest, source, bytes);
 }
 
-/***************       Recording stack         ***********/
-
-static void *first_frame_address(void) {
-#if 0
-    return __builtin_frame_address(1);
-#elif defined(__ppc__)
-    void *addr;
-#warning __builtin_frame_address IS BROKEN IN BEAKER: RADAR #2340421
-    __asm__ volatile("mr %0, r1" : "=r" (addr));
-    return addr;
-#else
-#warning first_frame_address WILL NOT BE FUNCTIONAL ON THIS ARCHITECTURE
-    return NULL;
-#endif
-}
-
-static void *next_frame_address(void *addr) {
-    void *ret;
-#if defined(__MACH__) && defined(__i386__)
-    __asm__ volatile("movl (%1),%0" : "=r" (ret) : "r" (addr));
-#elif defined(__MACH__) && defined(__ppc__)
-    __asm__ volatile("lwz %0,0x0(%1)" : "=r" (ret) : "b" (addr));
-#elif defined(__hpux__)
-    __asm__ volatile("ldw 0x0(%1),%0" : "=r" (ret) : "r" (addr));
-#elif defined(__svr4__)
-    __asm__ volatile("ta 0x3");
-    __asm__ volatile("ld [%1 + 56],%0" : "=r" (ret) : "r" (addr));
-#else
-#error Unknown architecture
-#endif
-    return ret;
-}
-
-#if defined(__i386__) || defined (__m68k__)
-#define FP_LINK_OFFSET 1
-#elif defined(__ppc__)
-#define FP_LINK_OFFSET 2
-#elif defined(__hppa__)
-#define FP_LINK_OFFSET -5
-#elif defined(__sparc__)
-#define FP_LINK_OFFSET 14
-#else
-#error  ********** Unimplemented architecture
-#endif
-
-void thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb) {
-    void *addr;
-    addr = first_frame_address();
-    *nb = 0;
-    while ((addr >= (void *)0x800) && (max--)) {
-        vm_address_t   fp_link = (vm_address_t)(((unsigned *)addr)+FP_LINK_OFFSET);
-        void   *addr2;
-        buffer[*nb] = *((vm_address_t *)fp_link);
-        (*nb)++;
-        addr2 = next_frame_address(addr);
-#if defined(__ppc__)
-        if ((unsigned)addr2 <= (unsigned)addr) break; // catch bozo frames
-#endif
-        addr = addr2;
-    }
-}
-
 /***************       Uniquing stack          ***********/
 
 #define MAX_COLLIDE    8
 /***************       Uniquing stack          ***********/
 
 #define MAX_COLLIDE    8
@@ -171,6 +121,8 @@ int stack_logging_enable_logging = 0;
 
 int stack_logging_dontcompact = 0;
 
 
 int stack_logging_dontcompact = 0;
 
+static int stack_logging_spin_lock = 0;
+
 static stack_logging_record_list_t *GrowLogRecords(stack_logging_record_list_t *records, unsigned desiredNumRecords) {
     stack_logging_record_list_t        *new_records;
     unsigned   old_size = records->overall_num_bytes;
 static stack_logging_record_list_t *GrowLogRecords(stack_logging_record_list_t *records, unsigned desiredNumRecords) {
     stack_logging_record_list_t        *new_records;
     unsigned   old_size = records->overall_num_bytes;
@@ -206,7 +158,7 @@ void stack_logging_log_stack(unsigned type, unsigned arg1, unsigned arg2, unsign
         arg1 *= arg2; arg2 = arg3; arg3 = 0; type &= ~stack_logging_flag_calloc;
     }
     if (type & stack_logging_flag_object) {
         arg1 *= arg2; arg2 = arg3; arg3 = 0; type &= ~stack_logging_flag_calloc;
     }
     if (type & stack_logging_flag_object) {
-        unsigned       *class = (unsigned *)arg1;
+        unsigned       *class = (unsigned *)(uintptr_t)arg1;
         arg1 = arg2 + class[5]; // corresponds to the instance_size field
         arg2 = 0; arg3 = 0; type = stack_logging_type_alloc;
     }
         arg1 = arg2 + class[5]; // corresponds to the instance_size field
         arg2 = 0; arg3 = 0; type = stack_logging_type_alloc;
     }
@@ -217,23 +169,23 @@ void stack_logging_log_stack(unsigned type, unsigned arg1, unsigned arg2, unsign
         if (stack_logging_type_alloc) {
             if (!result) return;
             stack_logging_log_stack(stack_logging_type_alloc, 0, 0, 0, result, num_hot_to_skip+1);
         if (stack_logging_type_alloc) {
             if (!result) return;
             stack_logging_log_stack(stack_logging_type_alloc, 0, 0, 0, result, num_hot_to_skip+1);
-            stack_logging_log_stack(stack_logging_type_alloc, arg1, 0, 0, *((int *)result), num_hot_to_skip+1);
+            stack_logging_log_stack(stack_logging_type_alloc, arg1, 0, 0, *((int *)(uintptr_t)result), num_hot_to_skip+1);
             return;
         }
         if (stack_logging_type_dealloc) {
             if (!arg1) return;
             return;
         }
         if (stack_logging_type_dealloc) {
             if (!arg1) return;
-            stack_logging_log_stack(stack_logging_type_dealloc, *((int *)arg1), 0, 0, 0, num_hot_to_skip+1);
+            stack_logging_log_stack(stack_logging_type_dealloc, *((int *)(uintptr_t)arg1), 0, 0, 0, num_hot_to_skip+1);
             stack_logging_log_stack(stack_logging_type_dealloc, arg1, 0, 0, 0, num_hot_to_skip+1);
             return;
         }
             stack_logging_log_stack(stack_logging_type_dealloc, arg1, 0, 0, 0, num_hot_to_skip+1);
             return;
         }
-        printf("*** Unknown logging type: 0x%x\n", type);
+        fprintf(stderr, "*** Unknown logging type: 0x%x\n", type);
     }
     if (type == stack_logging_flag_set_handle_size) {
         if (!arg1) return;
         // Thanks to a horrible hack, arg3 contains the prvious handle value
     }
     if (type == stack_logging_flag_set_handle_size) {
         if (!arg1) return;
         // Thanks to a horrible hack, arg3 contains the prvious handle value
-        if (arg3 == *((int *)arg1)) return;
+        if (arg3 == *((int *)(uintptr_t)arg1)) return;
         stack_logging_log_stack(stack_logging_type_dealloc, arg3, 0, 0, 0, num_hot_to_skip+1);
         stack_logging_log_stack(stack_logging_type_dealloc, arg3, 0, 0, 0, num_hot_to_skip+1);
-        stack_logging_log_stack(stack_logging_type_alloc, arg2, 0, 0, *((int *)arg1), num_hot_to_skip+1);
+        stack_logging_log_stack(stack_logging_type_alloc, arg2, 0, 0, *((int *)(uintptr_t)arg1), num_hot_to_skip+1);
         return;
     }            
     if (type == (stack_logging_type_dealloc|stack_logging_type_alloc)) {
         return;
     }            
     if (type == (stack_logging_type_dealloc|stack_logging_type_alloc)) {
@@ -253,8 +205,7 @@ void stack_logging_log_stack(unsigned type, unsigned arg1, unsigned arg2, unsign
         if (!arg1) return; // free(nil)
     }
     prepare_to_log_stack();
         if (!arg1) return; // free(nil)
     }
     prepare_to_log_stack();
-    spin_lock(&stack_logging_the_record_list->lock);
-    stack_logging_enable_logging = 0;
+    spin_lock(&stack_logging_spin_lock);
     stack_logging_the_record_list = GrowLogRecords(stack_logging_the_record_list, stack_logging_the_record_list->num_records + 1);
     rec = stack_logging_the_record_list->records + stack_logging_the_record_list->num_records;
     // We take care of the common case of alloc-dealloc
     stack_logging_the_record_list = GrowLogRecords(stack_logging_the_record_list, stack_logging_the_record_list->num_records + 1);
     rec = stack_logging_the_record_list->records + stack_logging_the_record_list->num_records;
     // We take care of the common case of alloc-dealloc
@@ -276,16 +227,15 @@ void stack_logging_log_stack(unsigned type, unsigned arg1, unsigned arg2, unsign
             rec->address = STACK_LOGGING_DISGUISE(arg1); // we disguise the address
         }
        // printf("Before getting samples  0x%x 0x%x 0x%x 0x%x -> 0x%x\n", type, arg1, arg2, arg3, result);
             rec->address = STACK_LOGGING_DISGUISE(arg1); // we disguise the address
         }
        // printf("Before getting samples  0x%x 0x%x 0x%x 0x%x -> 0x%x\n", type, arg1, arg2, arg3, result);
-        thread_stack_pcs(stack_entries, MAX_NUM_PC - 1, &count);
+        thread_stack_pcs((vm_address_t *)stack_entries, MAX_NUM_PC - 1, &count);
         // We put at the bottom of the stack a marker that denotes the thread (+1 for good measure...)
         // We put at the bottom of the stack a marker that denotes the thread (+1 for good measure...)
-        stack_entries[count++] = (int)pthread_self() + 1;
+        stack_entries[count++] = (int)(uintptr_t)pthread_self() + 1;
         /* now let's unique the sample */    
         // printf("Uniquing 0x%x 0x%x 0x%x 0x%x -> 0x%x\n", type, arg1, arg2, arg3, result);
         rec->uniqued_stack = stack_logging_get_unique_stack(&stack_logging_the_record_list->uniquing_table, &stack_logging_the_record_list->uniquing_table_num_pages, stack_entries, count, num_hot_to_skip+2); // we additionally skip the warmest 2 entries that are an artefact of the code
         stack_logging_the_record_list->num_records++;
     }
         /* now let's unique the sample */    
         // printf("Uniquing 0x%x 0x%x 0x%x 0x%x -> 0x%x\n", type, arg1, arg2, arg3, result);
         rec->uniqued_stack = stack_logging_get_unique_stack(&stack_logging_the_record_list->uniquing_table, &stack_logging_the_record_list->uniquing_table_num_pages, stack_entries, count, num_hot_to_skip+2); // we additionally skip the warmest 2 entries that are an artefact of the code
         stack_logging_the_record_list->num_records++;
     }
-    stack_logging_enable_logging = 1;
-    stack_logging_the_record_list->lock = 0;
+    spin_unlock(&stack_logging_spin_lock);
 }
 
 static kern_return_t default_reader(task_t task, vm_address_t address, vm_size_t size, void **ptr) {
 }
 
 static kern_return_t default_reader(task_t task, vm_address_t address, vm_size_t size, void **ptr) {
@@ -330,7 +280,7 @@ kern_return_t stack_logging_get_frames(task_t task, memory_reader_t reader, vm_a
         }
        index++;
     }
         }
        index++;
     }
-    fprintf(stderr, "*** stack_logging: no record found for 0x%x\n", address);
+    fprintf(stderr, "*** stack_logging: no record found for %p\n", address);
     return 0;
 }
 
     return 0;
 }