AutoMonitor.h   [plain text]


/*
 * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
 *
 * @APPLE_APACHE_LICENSE_HEADER_START@
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @APPLE_APACHE_LICENSE_HEADER_END@
 */

#pragma once
#ifndef __AUTO_MONITOR__
#define __AUTO_MONITOR__

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <CoreFoundation/CFMessagePort.h>
#include <CoreFoundation/CFData.h>

#include "AutoDefs.h"

extern "C" {
    struct ptr_set;
}

namespace Auto {

    // Forward declarations.
    class Admin;
    class Large;
    class Subzone;
    class Zone;
    
    //----- Monitor -----//
    
    //
    // Handles requests from an external memory debugging tool.
    //

    class Monitor : public AuxAllocated {
    
      private:
      
        enum {
            request_size    = 256,                          // size of the request line buffer
            max_args        = 16,                           // maximum number of request args
        };
      
        static Monitor *_monitor;                           // current monitor
                                                            // non-NULL if the monitor has been initialized

        static int (*_class_list)(void **buffer, int count);// class lister.
        static ptr_set *_class_set;                         // known classes.
        static int _class_count;                            // known class count.

        char      _request[request_size];                   // current request
        CFMessagePortRef _request_port;                     // message port for requests.
        CFMutableDataRef _response_buffer;                  // message port response buffer.
        int       _argc;                                    // argument count
        char      *_args[max_args];                         // array of argument strings
        void *_stack_bottom;                                // monitor stack bottom.
       
      public:
      
        //
        // monitor
        //
        // Get monitor.  Start if not running.
        //
        static Monitor *monitor();

        static void set_class_list(int (*class_list)(void **buffer, int count));
        static bool is_object(void *ptr, long size);
        
        //
        // Constructor
        //
        Monitor();
        
        
        //
        // open_mach_port()
        //
        // Opens the mach communication port.
        //
        void open_mach_port();
        

        //
        // print
        //
        // Formatted print to response buffer.
        //
        void print(const char *fmt, ...);
        
        
        //
        // tokenize_args
        //
        // Scan the request generating an array of arguments.
        // 
        void tokenize_args();
        
        
        //
        // process_request
        //
        // Generate a report based on the supplied request.
        // XXX_JML number of commands is currently small and performance is not an issue
        // XXX_JML later might want to be table driven.
        //
        void process_request();

        //
        // receive_request
        //
        // CFMessagePort function for handling monitor requests.
        //
        static CFDataRef receive_request(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info);
        
        
        //
        // send_all_blocks
        //
        // Sends all block information to monitor.
        //
        void send_all_blocks();
        
        //
        // send_root_blocks
        //
        // Send all blocks that are scanned, have refcount > 0 or are referenced by the GC's internal
        // root table.
        // 
        void send_root_blocks();
        
        //
        // send_block_info
        //
        // Send specific information about block
        //
        void send_block_info(Zone *zone, void *block);
        void send_block_info(Zone *zone, Subzone *subzone, usword_t q, void *block);
        void send_block_info(Zone *zone, Large *large, void *block);
        
        //
        // send_malloc_block_info
        //
        // Send fake information about a malloc block.
        //
        void send_malloc_block_info(void *block, size_t size);
        
        
        //
        // send_block_content
        //
        // Send the content of a block to monitor.
        //
        void send_block_content();

        //
        // send_block_description
        //
        // Send a low-level description of the block, if it's owned by our zone, and known to be
        // an object. If so, then we call CFCopyDescription() on the object, escape the resulting
        // string so it can be represented in an XML-plist, and return it.
        //
        void send_block_description();

        
        //
        // send_block
        //
        // Send details of a block
        //
        void send_block(Zone *zone, Subzone *subzone, usword_t q, void *block);
        void send_block(Zone *zone, Large *large, void *block);
        
        
        //
        // send_all_zones
        //
        // Send addresses of all zones.
        //
        void send_all_zones();
        
        
        //
        // send_leaks, scan_leaks
        //
        // Send all blocks that are unreferenced but have a retain count.
        //
        void send_leaks();
        
        
        //
        // send_references
        //
        // Send all reference information for the specified block.
        //
        void send_references();


        //
        // send_roots
        //
        // Send all root information for the specified block.
        //
        void send_roots();
        
        
        //
        // send_zone_samples
        //
        // Send sample of statistics for the specified zone.
        //
        void send_zone_samples();
        
        
        //
        // send_process_samples
        //
        // Send sample of statistics for the entire process.
        //
        void send_process_samples();
    };

};

#endif // __AUTO_MONITOR__