⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptt_view.c

📁 linux下的多线程调试工具
💻 C
字号:
/* Copyright (C) 2004,2005,2006  Bull S.A. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#if HAVE_CONFIG_H#include <config.h>#endif#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <assert.h>#include "types.h"#include "modules.h"extern ptt_event_data_t ptt_event_array[];extern struct export export_paje;extern struct export export_raw;extern struct export export_text;extern struct give_name give_name;extern struct read_trace read_trace;extern struct file_spliter file_spliter;extern struct interval interval;extern struct filter filter;struct export *export;static ptt_header_t head;static int accept_event [EVT_LAST] = {[0 ... EVT_LAST-1] = 1};static int paje = 0;static void error (char *err, ...) {    va_list ap;    fprintf(stderr, "Error : ");    va_start(ap, err);    vfprintf(stderr, err, ap);    va_end(ap);    fprintf(stderr, "\n");    exit (1);}static void warning (char *err, ...) {    va_list ap;    fprintf(stderr, "Warning : ");    va_start(ap, err);    vfprintf(stderr, err, ap);    va_end(ap);    fprintf(stderr, "\n");}static void list_event () {    ptt_event_t ret;    fprintf (stderr, "PTT event :\n");    for (ret = EVT_NULL+1; ret < EVT_LAST; ret++)        fprintf (stderr, "\t%s\n", ptt_event_array[ret].name);}static int eventstr2enum (int *p, int and, char * str) {    ptt_event_t ret;    int count = 0;    int len = strlen (str);    for (ret = EVT_NULL; ret < EVT_LAST; ret++) {        if (strncmp (ptt_event_array[ret].name, str, len) == 0 &&            (!and || p[ret])) { p[ret] = 1; count++; }        else if (and) p[ret] = 0;    }    if (!count) warning ("%s* no matching event, ignoring", str);    return count;}static int eventstr2enumr(int *p, int and, char * str) {    ptt_event_t ret;    int count = 0;    int len = strlen (str);    for (ret = EVT_NULL; ret < EVT_LAST; ret++) {        int len_evt = strlen (ptt_event_array[ret].name);        if (len_evt >= len && strcmp (ptt_event_array[ret].name + len_evt            - len, str) == 0 && (!and || p[ret])) { p[ret] = 1; count++; }        else if (and) p[ret] = 0;    }    if (!count) warning("*%s no matching event, ignoring", str);    return count;}static void and (int *p1d, int *p2) {    ptt_event_t ret;    for (ret = EVT_NULL; ret < EVT_LAST; ret++) if (!p2[ret]) p1d [ret] = 0;}static void usage(char * name) {    if (paje) 	fprintf (stderr,                 "%s [options] input_file\n"                 "\ninput options :\n"                 " -i file : input file name\n"                 "\noutput options :\n"                 " -o file : output file name\n"                 " -s {pid,pidx,tid} : split output\n"                 " -a alias_file : use alias to describe objects"                 "\nfilter options :\n"                 " -p pid[,pid...] : search for pid\n"                 " -n name[,name...] : search for name\n"                 " -z start:end : event filter\n"                 " -Z start:end : time filter\n"                 " -e : trace only I/O\n"                 "\ndisplay options :\n"                 " -d : show thread attribute and thread state\n"                 " -m : mask thread attribute and thread state\n"                 " no option : mask thread attribute and show thread state\n"                 , name);    else	fprintf (stderr,                 "%s [options] input_file\n"                 "\ninput options :\n"                 " -i file : input file name\n"                 "\noutput options :\n"                 " -o file : output file name\n"                 " -r : raw export\n"                 " -t : text export\n"                 " -s {pid,pidx,tid} : split output\n"                 " -a alias_file : use alias to describe objects"                 "\nfilter options :\n"                 " -e patern[,patern...] : search for paterns* event\n"                 " -E patern[,patern...] : search for *paterns event\n"                 " -l : list avaible events\n"                 " -p pid[,pid...] : search for pid\n"                 " -n name[,name...] : search for name\n"                 " -z start:end : event filter\n"                 " -Z start:end : time filter\n"                 "\ndisplay options :\n"                 " -m : mask pid\n"                 " -d : show pid\n"                 " -T : no time division\n"                 , name);    exit (1);}static int init (int argc, char ** argv) {    const char * optstring = "+e:E:rtgs:i:o:a:z:Z:dmTp:n:h::l";    signed char c;    int ret;        /* for paje : display thread state and not thread attribute     * for textual output : display pid */    int export_display = 1;    int export_time_div = 1;	    /* filter optipn */    pid_t *list_pid = NULL;    int accept_event_tmp [EVT_LAST];    char **list_names = NULL;    /* read option */    char *input_file = NULL;    int interval_mode = INT_NULL;    unsigned long long itv_min = 0, itv_max = 0;    /* output option */    char *output_file = NULL;    int output_mode = SPLIT_NULL;    char *alias_file = NULL;    /* check if we are ptt_view or ptt_paje */    int name_len = strlen (argv[0]);    if (name_len >= 8 /*strlen("ptt_paje")*/ && strcmp(argv[0] + name_len - 8,        "ptt_paje") == 0) {        paje = 1;        export = &export_paje;        optstring = "+es:i:o:a:z:Z:p:n:h::dm";    }    else export = &export_raw;    opterr = 0;    while ((c = getopt (argc, argv, optstring)) != EOF) {        switch (c) {            case 'p': {                char *pos = optarg;                int number = 2; /* there is n-1 comma + lead 0 */                if (list_pid) {                    warning ("Only one -p option is allowed"); continue;                }                /* count the number of entry */                while (*pos && (pos = strchr (pos, ','))) { number++; pos++; }                list_pid = malloc (number * sizeof (pid_t));                list_pid[--number] = 0;                while (optarg) {                    pid_t pid = atoi (strsep (&optarg ,","));                    list_pid[--number] = pid;                }                assert(number == 0);                continue;            }            case 'n': {                char *pos = optarg;                int number = 2; /* there is n-1 comma + lead 0 */                if (list_names) {                    warning("Only one -n option is allowed"); continue;                }                /* count the number of entry */                while (*pos && (pos = strchr (pos, ','))) { number++; pos++; }                list_names = malloc (number * sizeof (char*));                list_names[--number] = NULL;                while (optarg) {                    list_names[--number] = strsep (&optarg ,",");                }                assert(number == 0);                continue;            }            case 's':                if (strcmp (optarg, "pid") == 0) output_mode = SPLIT_PID;                else if (strcmp (optarg, "tid") == 0) output_mode = SPLIT_TID;                else if (strcmp (optarg, "pidx") == 0)                    output_mode = SPLIT_PID_FULL;                else error("unknow -s argument");                continue;            case 'o':                if (strcmp (optarg, "-") == 0) output_mode = SPLIT_STDOUT;                else output_file = optarg;                continue;            case 'a': alias_file = optarg; continue;            case 'i': input_file = optarg; continue;            case 'z':            case 'Z':                if (optarg[0] == ':') {                    itv_min = 0;                    if (!*(optarg+1)) {                        warning ("':' is not an interval");                        continue;                    }                    itv_max = atoll (optarg+1);                }                else {                    itv_min = atoi (strsep (&optarg ,":"));                    if (!optarg) error ("missing `:' in %c\n", c);                    if (optarg[0] == 0) itv_max = -1LL;                    else itv_max = atoll (strsep (&optarg ,":"));                }                if (c == 'z') interval_mode = INT_EVT;                else interval_mode = INT_TIME;                continue;            case 'h': usage (argv[0]); continue;            case 'd':                /* for paje : display thread attribute and thread state                 * for textual output : display pid */                export_display = 2; continue;            case 'm':                /* for paje : mask thread attribute and thread state	         * for textual output : mask pid */                export_display = 0; continue;            case 'T':                /* for paje : nothing                 * for textual output : no time division */                export_time_div = 0; continue;        }        if (paje) {            switch (c) {                case 'e':                    memset (accept_event_tmp, 0, sizeof (accept_event_tmp));                    eventstr2enumr (accept_event_tmp, 0, "_IN");                    eventstr2enumr (accept_event_tmp, 0, "_OUT");                    eventstr2enumr (accept_event_tmp, 0, "THREAD_JOIN");                    eventstr2enumr (accept_event_tmp, 0, "THREAD_SET_PD");                    eventstr2enumr (accept_event_tmp, 0, "_USER_FUNC");                    eventstr2enumr (accept_event_tmp, 0, "_INIT");                    eventstr2enumr (accept_event_tmp, 0, "_DESTROY");                    and (accept_event, accept_event_tmp);                    export_display = 0;                    break;                case '?': warning("Unknow option -%c", optopt); break;                default: warning("Unknow option -%c", c); break;            }            continue;        }        switch (c) {            case 'r': export = &export_raw;  break;            case 't': export = &export_text; break;            case 'g': export = &export_paje; break;            case 'e':                memset(accept_event_tmp, 0, sizeof (accept_event_tmp));                while (optarg)                    eventstr2enum (accept_event_tmp, 0,                                   strsep (&optarg ,","));                    and (accept_event, accept_event_tmp);                    break;            case 'E':                memset (accept_event_tmp, 0, sizeof (accept_event_tmp));                while (optarg)                    eventstr2enumr (accept_event_tmp, 0,                                    strsep (&optarg ,","));                    and (accept_event, accept_event_tmp);                    break;            case 'l': list_event (); exit (0);            case '?': warning ("Unknow option -%c", optopt); break;            default: warning ("Unknow option -%c", c); break;        }    }    /* init all module     * interval and name are used by read_trace and must be init before */    ret = interval.init (interval_mode, &itv_min, &itv_max);    if (ret < 0) return ret;    ret = give_name.init(alias_file);    if (ret < 0) return ret;    if (!input_file) input_file = argv[optind];    ret = read_trace.init(input_file, &head);    if (ret < 0) return ret;    ret = export->init(&head, export_display, export_time_div);    if (ret < 0) return ret;    ret = file_spliter.init(output_file, output_mode);    if (ret < 0) return ret;    ret = filter.init(list_pid, accept_event, list_names);    if (ret < 0) return ret;    return 0;}#define CLOSE(x) if ((x).close) (x).close()static void close_modules () {    CLOSE (filter);    CLOSE (file_spliter);    CLOSE (*export);    CLOSE (read_trace);    CLOSE (give_name);    CLOSE (interval);}	int main (int argc, char ** argv) {    long long list_longlong [PTT_MAXARG];    int list_int [PTT_MAXARG];    unsigned int list_uint [PTT_MAXARG];    char *list_name [PTT_MAXARG+1]; /* +1: array is NULL terminated */    int ret;    ptt_event_t event;    ptt_timestamp_t time;    pid_t pid;    if (init (argc, argv) < 0) { usage(argv[0]); return 1; }    while((ret = read_trace.read (&pid, &time, &event, list_name, list_int,                                   list_uint, list_longlong)) > 0) {        FILE *fd = file_spliter.getfd (pid, list_name[0], event, list_int);        if (fd == NULL) error ("file_spliter.getfd");        ret = filter.accept (pid, event, list_name);        if (ret < 0) error ("filter.accept");        else if (ret == 0) continue;        if (export->write (fd, time, pid, event, list_name, list_int,                           list_uint, list_longlong) < 0)            error ("export->write");    }    if (ret < 0) error ("read");    close_modules ();    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -