"Fossies" - the Fresh Open Source Software Archive

Member "FunctionCheck-3.2.0/src/fcmanager/main.c" (1 Jun 2012, 9374 Bytes) of package /linux/privat/old/FunctionCheck-3.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * FunctionCheck profiler
    3  * (C) Copyright 2000-2012 Yannick Perret
    4  * 
    5  *  This program is free software; you can redistribute it and/or
    6  *  modify it under the terms of the GNU General Public License as
    7  *  published by the Free Software Foundation; either version 2 of the
    8  *  License, or (at your option) any later version.
    9  *
   10  *  This program is distributed in the hope that it will be useful,
   11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13  *  General Public License for more details.
   14  *
   15  *  You should have received a copy of the GNU General Public License
   16  *  along with this program; if not, write to the Free Software
   17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18  */
   19 /** main.c: started by the profiled program. reads and treats
   20                   the data sent by the profiled program. **/
   21 
   22 #include <limits.h>
   23 #include "fc_global.h"
   24 #include "fc_tools.h"
   25 #include "fc_com_manager.h"
   26 #include "fc_time.h"
   27 #include "fc_context.h"
   28 #include "fc_functions.h"
   29 #include "fc_graph.h"
   30 #include "fc_stack.h"
   31 #include "fc_xhash.h"
   32 #include "fc_memory_manager.h"
   33 
   34 /* well... it's the main, ya know... */
   35 int main(int argc, char*argv[])
   36 {
   37     /* data returned at each 'read' */
   38     void *function, *from, *incoming, *ptr, *where;
   39     unsigned int size, align;
   40     unsigned long long vtime;
   41     char name[1024];
   42     int shmid, id, ret, parent;
   43     char type;
   44     FC_Context *ctmp;
   45     FC_Function *func;
   46     unsigned long long ftime;
   47     /* init structure with all default values */
   48     FC_INIT init;
   49     FC_LDYN ldyn;
   50     /* special */
   51     void *call_site;
   52     char *usage = "Usage: " FC_MANAGER_NAME " is for internal used by libfc.so and automatically passed a <shared_mem_id> parameter.";
   53     /* special case for thread: indicates that QUIT is done */
   54     /*
   55     int thread_quit_main = 0, thread_id_init = 0;
   56     int thread_mode_init = 0;
   57      */
   58 
   59     /* set the prog name */
   60     fc_set_message_name(FC_MANAGER_NAME);
   61 
   62     /* check the parameters */
   63     if (argc != 2)
   64     {
   65         fc_message(usage);
   66         exit(FC_ERR_ARGS);
   67     }
   68 
   69     /* init the communication system */
   70     shmid = atoi(argv[1]);
   71     if (!fc_mcom_init(shmid, &id, &init)) /* id is the ID of the prog */
   72     {
   73         fc_message(usage);
   74         exit(FC_ERR_ARGS);
   75     }
   76 
   77     /* init messages state */
   78     fc_set_message_mode(init.verbose);
   79     fc_set_debug_mode(init.debug);
   80 
   81     /* init default values regard to the init info */
   82     fc_context_set_functions(init.function_size);
   83     fc_context_set_graph(init.graph_size);
   84     fc_context_set_stack(init.stack_size);
   85     fc_context_set_memory(init.memory_size);
   86     fc_context_set_usepid(init.use_pid);
   87     fc_context_set_name(init.dump_name);
   88     fc_context_set_path(init.dump_path);
   89     fc_memory_set_stack_size(init.memory);
   90     fc_context_set_mode(init.mode);
   91 
   92     /* if any read the list of dynamic libraries */
   93     if (init.follow)
   94     {
   95         fc_mcom_read_lib(&ldyn);
   96         while (ldyn.addr != NULL)
   97         {
   98             /* debug */
   99             fc_message("Dyn lib:   %s [0x%x]", ldyn.name[0] ? ldyn.name : "NULL", ldyn.addr);
  100             fc_ldyn_add(&ldyn);
  101             fc_mcom_read_lib(&ldyn);
  102         }
  103     }
  104     
  105     fc_message("Profile manager: running [%d]", (int) getpid());
  106 
  107     /* init the 1st context */
  108     fc_context_set(id, init.start_time);
  109 
  110     /* set starting time */
  111     fc_context_set_starttime(time(NULL));
  112 
  113     /* loop to read messages */
  114     while (1)
  115     {
  116         /* read data */
  117         /* removed. may not be useful now */
  118         /*
  119         if ((nb_children <= 0)||(thread_quit_main))
  120           {
  121           fc_message("no more children referenced. end of profiled program.");
  122           fc_context_set_stoptime(time(NULL));
  123           break;
  124           }
  125          */
  126         ret = fc_mcom_read(&function, &from, &vtime, &id, &type,
  127                            &ptr, &incoming, &where, &parent, &size, &align, name);
  128 
  129         fc_debug("%p %p %u %d %d", function, from, vtime, id, (int) type);
  130         /* ret==0 => pipe closed => all clients are over */
  131         if (!ret)
  132         {
  133             /* leave the reading loop */
  134             fc_message("communication FIFO closed. end of profiled program.");
  135             fc_context_set_stoptime(time(NULL));
  136             break;
  137         }
  138 
  139         /** special messages **/
  140         /* fork notification */
  141         if (type == FC_TYPE_FORK)
  142         {
  143             /* set the context in order to
  144                 1/  create it as it is a new one
  145                 2/  set the starting time with the good value
  146              */
  147             fc_context_set(parent, vtime);
  148 
  149             continue; /* just read next event */
  150         }
  151 
  152         /* thread creation notification */
  153         if (type == FC_TYPE_THREAD)
  154         {
  155             /* set the context in order to
  156                 1/  create it as it is a new one
  157                 2/  set the starting time with the good value
  158              */
  159             fc_context_set(parent, vtime);
  160 
  161             continue; /* just read next event */
  162         }
  163 
  164         /* set the corresponding context */
  165         fc_context_set(id, vtime);
  166 
  167         /* if QUIT event, only the time is used, so read next event */
  168         if (type == FC_TYPE_QUIT)
  169         {
  170             fc_debug("QUIT message (%d). number of children is now (not yet implemented).", id);
  171             continue;
  172             /*nb_children--;
  173             if ((thread_mode_init == FC_MODE_THREAD)&&(id == thread_id_init))
  174               {
  175               fc_debug("QUIT message from the main thread. Forced exit.");
  176               thread_quit_main = 1;
  177               }
  178             continue;
  179              */
  180         }
  181 
  182         /* set the last time found for this context */
  183         fc_current_context->ulast_time = vtime;
  184 
  185         /* test if the time loops */
  186         if (vtime < fc_current_context->ulast_time)
  187         {
  188             fc_current_context->time_pad += UINT_MAX + 1;
  189         }
  190 
  191         fc_current_context->last_time = fc_current_context->time_pad + vtime;
  192 
  193         /* special message to inform about the process aprent */
  194         if (type == FC_TYPE_PARENT)
  195         {
  196             /* information on the parent process */
  197             fc_current_context->pid = (int) parent;
  198         }
  199         else /* standard message. treat the data */
  200         {
  201             /* treat the action */
  202             if (type == FC_TYPE_ENTER)
  203             {
  204                 fc_functions_enter(function, from, fc_current_context->last_time);
  205             }
  206             else
  207                 if (type == FC_TYPE_EXIT)
  208             {
  209                 if (function != NULL) /* NULL -> just an exit from prog */
  210                 {
  211                     /* first add the arc in the call-graph */
  212                     fc_debug("add arc %p -> %p", from, function);
  213                     fc_graph_add_single(fc_current_context->graph, from, function);
  214                     fc_functions_exit(function, from, fc_current_context->last_time);
  215                 }
  216                 else
  217                 {
  218                     fc_debug("process %d is over.", id);
  219                 }
  220             }
  221             else
  222                 if (type == FC_TYPE_MALLOC)
  223             {
  224                 fc_memory_add_malloc(fc_current_context, ptr, size, where);
  225             }
  226             else
  227                 if (type == FC_TYPE_FREE)
  228             {
  229                 fc_memory_add_free(fc_current_context, ptr, where);
  230             }
  231             else
  232                 if (type == FC_TYPE_REALLOC)
  233             {
  234                 fc_memory_add_realloc(fc_current_context, ptr, incoming, size, where);
  235             }
  236             else
  237                 if (type == FC_TYPE_MEMALIGN)
  238             {
  239                 fc_memory_add_memalign(fc_current_context, ptr, align, size, where);
  240             }
  241             else
  242             {
  243                 if ((type == FC_TYPE_DLOPEN) || (type == FC_TYPE_DLCLOSE) ||
  244                         (type == FC_TYPE_DLSYM))
  245                 {
  246                     fc_message("this message type (%d) is not implemented.", (int) type);
  247                 }
  248                 else
  249                 {
  250                     fc_message("invalid message type (%d). ignored.", type);
  251                 }
  252             }
  253         }
  254     }
  255 
  256     /* for each context, flush the stack. the stack is not empty
  257        if the profiled program stops due to a crash -> all remaining
  258        functions are treated as if they exit now */
  259     ctmp = fc_context_first();
  260     while (ctmp != NULL)
  261     {
  262         fc_debug("context %p: flushing stack", ctmp);
  263         fc_current_context = ctmp;
  264         /* simulate exits for each remaining function */
  265         while (!fc_stack_empty(ctmp->stack))
  266         {
  267             fc_stack_get(ctmp->stack, &func, &ftime, &call_site);
  268             if (func->symbol != NULL)
  269             {
  270                 fc_graph_add_single(fc_current_context->graph, call_site, func->symbol);
  271                 fc_functions_exit(func->symbol, NULL, ctmp->last_time);
  272             }
  273             else
  274                 fc_stack_pop(ctmp->stack);
  275         }
  276 
  277         ctmp = fc_context_next(ctmp);
  278     }
  279 
  280     /* dump data */
  281     fc_debug("saving contexts");
  282     fc_context_save_all();
  283 
  284     /* stop communication system */
  285     fc_mcom_fini(shmid);
  286 
  287     /* exit */
  288     fc_message("Profile manager: exit");
  289     fc_debug("leaving fcmanager");
  290     return FC_ERR_OK;
  291 }