summaryrefslogtreecommitdiffstats
path: root/src/config.h
blob: 28215f127fcbccfee048181fd5e28776b6c7eabb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
/*
  Copyright (C) 2008, 2009, 2010 Jiri Olsa <olsajiri@gmail.com>

  This file is part of the latrace.

  The latrace 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 of the License, or
  (at your option) any later version.

  The latrace 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.

  You should have received a copy of the GNU General Public License
  along with the latrace (file COPYING).  If not, see 
  <http://www.gnu.org/licenses/>.
*/


#ifndef CONFIG_H
#define CONFIG_H

#include <stdio.h>
#include <search.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <stdint.h>
#include <unistd.h>

#include "audit.h"
#include "list.h"
#include "error.h"

#ifdef CONFIG_ARCH_HAVE_ARGS
#include "args.h"
#endif

#ifdef __GNUC__
#define NORETURN __attribute__((__noreturn__))
#else
#define NORETURN
#ifndef __attribute__
#define __attribute__(x)
#endif
#endif

#define LT_NAMES_MAX  50
#define LT_NAMES_SEP  ','

#define LT_SYM_HMAX    1000

#define LT_ARGS_DEF_STRUCT_NUM  1000
#define LT_ARGS_DEF_TYPEDEF_NUM 1000
#define LT_ARGS_DEF_ENUM_NUM    1000


enum { 
	LT_CSORT_TIME = 0,
	LT_CSORT_PERCENT, 
	LT_CSORT_CALL, 
	LT_CSORT_UCALL, 
	LT_CSORT_LIB,
	LT_CSORT_SYM
};

struct lt_config_tv {
	int type;
	char *name;
};

enum {
	LT_OPT_HEADERS = 1,
	LT_OPT_PIPE,
	LT_OPT_INDENT_SYM,
	LT_OPT_TIMESTAMP,
	LT_OPT_FRAMESIZE,
	LT_OPT_FRAMESIZE_CHECK,
	LT_OPT_HIDE_TID,
	LT_OPT_FOLLOW_FORK,
	LT_OPT_FOLLOW_EXEC,
	LT_OPT_DEMANGLE,
	LT_OPT_BRACES,
	LT_OPT_ENABLE_ARGS,
	LT_OPT_DETAIL_ARGS,
	LT_OPT_OUTPUT_TTY,
	LT_OPT_LIBS,
	LT_OPT_LIBS_TO,
	LT_OPT_LIBS_FROM,
	LT_OPT_SYM,
	LT_OPT_SYM_OMIT,
	LT_OPT_SYM_BELOW,
	LT_OPT_SYM_NOEXIT,
	LT_OPT_ARGS_STRING_POINTER_LENGTH,
};

struct lt_config_opt {
	int idx;
	char *sval;
	unsigned long nval;
	struct lt_list_head list;
};

struct lt_config_shared {
#define LT_CONFIG_VERSION	1
#define LT_CONFIG_MAGIC		((LT_CONFIG_VERSION << 16) + 0xdead)
	unsigned int magic;

#define LT_LIBS_MAXSIZE     200
	char libs_to[LT_LIBS_MAXSIZE];
	char libs_both[LT_LIBS_MAXSIZE];
	char libs_from[LT_LIBS_MAXSIZE];

	char libs_subst[LT_LIBS_MAXSIZE];

#define LT_SYMBOLS_MAXSIZE  200
	char symbols[LT_SYMBOLS_MAXSIZE];
	char symbols_omit[LT_SYMBOLS_MAXSIZE];
	char symbols_noexit[LT_SYMBOLS_MAXSIZE];

	char flow_below[LT_SYMBOLS_MAXSIZE];

#define LT_MAXFILE 200
	char output[LT_MAXFILE];
	FILE *fout;

	char args_def[LT_MAXFILE];
	char args_enabled;
	char args_detailed;
	char args_string_pointer_length;
#define LR_ARGS_MAXLEN 1000
	int  args_maxlen;
#define LR_ARGS_DETAIL_MAXLEN 1000
	int  args_detail_maxlen;
#define LT_ARGS_TAB 10000
	struct hsearch_data args_tab;

	int disabled;
	int ctl_config;
	int verbose;
	int timestamp;
	int debug;
	int indent_sym;
	int indent_size;
	int braces;
	int demangle;
	int counts;
	int pipe;
	int hide_tid;
	int not_follow_exec;
	int not_follow_fork;
	int framesize_check;
	unsigned int framesize;
	int global_symbols;
	int error_sim;

	/* for 'not_follow_fork' */
	pid_t pid;

	/* XXX feel like an idiot.. find another way!!! */
	struct lt_config_shared *sh;
};

struct lt_config_app {
	/*
	 * This is to copy the lt_config_audit, so we can use
	 * one PRINT_VERBOSE only.
	 */
	struct lt_config_shared *sh;
	struct lt_config_shared sh_storage;

	char *prog;
#define LT_NUM_ARG 500
	char *arg[LT_NUM_ARG];
	int arg_num;

	FILE *fstat;
	int csort;

	int  output_tty;
	int  output_tty_fd;
	char output_tty_file[LT_MAXFILE];

	struct lt_thread *threads;
	struct lt_thread *iter;

	int notify_fd;
	int notify_fd_watch;

	struct lt_list_head process_funcs;

	/* current error */
	struct lt_error_app *error_app;
	/* list of defined errors */
	struct lt_list_head  error_apps;

	/* error definition (error_sim = 1 in shared config) */
	struct lt_error_config *error_config;
	char *error_symbols;
	int error_symbols_size_names;
	int error_symbols_size_total;

	struct lt_list_head error_symbols_all;
	struct lt_list_head error_symbols_current;
	int error_symbols_all_cnt;
	int error_finished;
	int error_automated_symbol_index;
};

struct lt_config_ctl {
	struct lt_config_shared *sh;
	char *config;

	int set_disabled;
	int disabled;
};

enum {
	LT_OS_PATH = 1,  /* '=' */
	LT_OS_PTN,       /* '%' */
	LT_OS_PTN2PATH,  /* '~' */
};

struct lt_objsearch {
	int   type;
	char *src;
	char *dst;
};

struct lt_config_audit {

	/*
	 * Normally sh points to the sh_storage. When using
	 * ctl-config feature, the shared config is stored
	 * in mmaped area.
        */
	struct lt_config_shared *sh;
	struct lt_config_shared sh_storage;

	char *libs_to[LT_NAMES_MAX];
	int libs_to_cnt;

	char *libs_from[LT_NAMES_MAX];
	int libs_from_cnt;

	char *libs_both[LT_NAMES_MAX];
	int libs_both_cnt;

	char *symbols[LT_NAMES_MAX];
	int symbols_cnt;

	char *symbols_omit[LT_NAMES_MAX];
	int symbols_omit_cnt;

	char *symbols_noexit[LT_NAMES_MAX];
	int symbols_noexit_cnt;

	char *flow_below[LT_NAMES_MAX];
	int flow_below_cnt;

	struct lt_objsearch subst[LT_NAMES_MAX];
	int subst_cnt;

	char *dir;
	int init_ok;

	/* error definition (error_sim = 1 in shared config) */
	struct lt_error_config *error_config;
};

enum {
	LT_CONFIG_LN_NAME,
	LT_CONFIG_LN_VALUE,
};

/* config - list name support */
struct lt_config_ln {
	union {
		char *name;
		long val;
	};
	int type;
	struct lt_list_head list;
};

#define lt_sh(cfg, field) ((cfg)->sh->field)

#define LT_FIFO_MSG_MAXLEN 2000

enum {
	LT_FIFO_MTYPE_ENTRY = 1,
	LT_FIFO_MTYPE_EXIT,
	LT_FIFO_MTYPE_TEXT,
};

/* common message data */
struct lt_fifo_mbase {
	uint32_t type;
	struct timeval tv;
	pid_t tid;
	int len; /* the rest of the message size */
};

/* symbol message */
struct lt_fifo_msym {
	struct lt_fifo_mbase h;

	long info;
	int sym;
	int lib;
	int arg;
	int argd;
	char data[0];
};

/* text message */
struct lt_fifo_mtext {
	struct lt_fifo_mbase h;

	char text[0];
};

struct lt_stats_sym {
        char *name;
        char *sym;
        char *lib;

        struct timeval tv_cur;
        struct timeval tv_all;

        unsigned int call;

        /* post mortem statistics */
        float percent;
        unsigned int usec_call;
};

struct lt_thread {
	/* global */
	int fifo_fd;
        pid_t tid;

	int indent_depth;

	/* start/stop time */
	struct timeval tv_start;
	struct timeval tv_stop;

	/* symbol statistics */
        struct lt_stats_sym **sym_array;
        struct hsearch_data sym_htab;
        unsigned int sym_cnt;
        unsigned int sym_max;

	struct lt_thread *next;
};

struct lt_symbol {
	struct lt_args_sym  *args;
	struct lt_error_sym *error;

	/* symbol name */
	const char *name;
	/* symbol address */
	void *ptr;
};

typedef int (*lt_process_cb)(struct lt_config_app *cfg,
			     struct lt_thread *t,
			     struct lt_fifo_mbase *mbase);

struct lt_process_func {
	lt_process_cb cb;
	struct lt_list_head list;
};

/* ctl */
int main_ctl(int argc, char **argv);

/* global */
int lt_config(struct lt_config_app *cfg, int argc, char **argv);
int lt_run(struct lt_config_app *cfg);

/* fifo */
int lt_fifo_create(struct lt_config_shared *cfg, char *dir);
int lt_fifo_open(struct lt_config_shared *cfg, char *dir, char *name);
int lt_fifo_notify_init(struct lt_config_app *cfg, char *dir);
void lt_fifo_notify_cleanup(struct lt_config_app *cfg);
int lt_fifo_send(struct lt_config_shared *cfg, int fd, char *buf, int len);
int lt_fifo_recv(struct lt_config_shared *cfg, struct lt_thread *t,
		 void *buf, int bufsize);
int lt_fifo_msym_get(struct lt_config_shared *cfg, char *buf, int type,
		     struct timeval *tv, char *symname, char *libto,
		     char *arg, char *argd, long info);
int lt_fifo_mtext_get(struct lt_config_shared *cfg, char *buf,
		      struct timeval *tv, char *text);

/* counts */
int lt_stats_init(struct lt_config_app *cfg);
int lt_stats_sym(struct lt_config_app *cfg, struct lt_thread *t, 
		struct lt_fifo_msym* m);
int lt_stats_alloc(struct lt_config_app *cfg, struct lt_thread *t);
int lt_stats_show(struct lt_config_app *cfg);

/* thread */
struct lt_thread *lt_thread_add(struct lt_config_app *cfg, int fd, pid_t pid);
struct lt_thread *lt_thread_first(struct lt_config_app *cfg);
struct lt_thread *lt_thread_next(struct lt_config_app *cfg);

/* output */
int lt_out_entry(struct lt_config_shared *cfg, struct timeval *tv,
		pid_t tid, int indent_depth,
		const char *symname, char *lib_to,
		char *argbuf, char *argdbuf);
int lt_out_exit(struct lt_config_shared *cfg, struct timeval *tv,
		pid_t tid, int indent_depth,
		const char *symname, char *lib_to,
		char *argbuf, char *argdbuf);
int lt_out_text(struct lt_config_shared *cfg, struct timeval *tv,
		pid_t pid, char *text);

/* la_objsearch */
int lt_objsearch_init(struct lt_config_audit *cfg, char **ptr, int cnt);
char* lt_objsearch(struct lt_config_audit *cfg, const char *name, 
		uintptr_t *cookie, unsigned int flag);

/* stack */
int lt_stack_framesize(struct lt_config_audit *cfg, La_regs *regs);

/* symbol */
struct lt_symbol* lt_symbol_bind(struct lt_config_audit *cfg,
				void *ptr, const char *name);
struct lt_symbol* lt_symbol_get(struct lt_config_audit *cfg,
				void *ptr, const char *name);

/* config options */
struct lt_config_opt *lt_config_opt_new(struct lt_config_app *cfg,
					int idx, char *sval, long nval);
int lt_config_opt_process(struct lt_config_app *cfg, struct lt_list_head *list);
int lt_config_ln_add(struct lt_list_head *head, char *name, long val, int type);
int lt_config_ln_fill_buf(struct lt_list_head *head, char *buf, int size);
char **lt_config_ln_fill_array(struct lt_list_head *head);

/* tty */
int tty_master(struct lt_config_app *cfg);
int tty_init(struct lt_config_app *cfg, int master);
int tty_restore(struct lt_config_app *cfg);
int tty_process(struct lt_config_app *cfg, int master);
void tty_close(struct lt_config_app *cfg);

/* process functions registration */
int lt_process_register(struct lt_config_app *cfg, lt_process_cb cb);
int lt_process_unregister(struct lt_config_app *cfg, lt_process_cb cb);

/* error simulation app */
int lt_error_app(struct lt_config_app *cfg, struct lt_error_app *error_app);
int lt_error_set(struct lt_config_app *cfg, char *error);
int lt_error_run(struct lt_config_app *cfg);

/* error simulation lib */
int lt_error_init(struct lt_config_audit *cfg);
struct lt_error_sym* lt_error_sym_get(struct lt_config_audit *cfg,
				      const char *name);
int lt_error_sym_exit(struct lt_config_audit *cfg,
		      const char *symname,
		      struct lt_symbol *sym,
		      struct timeval *tv,
		      struct link_map *lr,
		      const La_regs *inregs,
		      La_retval *outregs,
		      long *info);
int lt_error_set_retval(struct lt_config_audit *cfg,
			unsigned long ret, La_retval *outregs);
void lt_error_get_retaddr(struct lt_config_audit *cfg,
			  void **ret_addr, const La_regs *inregs);

#define PRINT(fmt, args...) \
do { \
	char lpbuf[1024]; \
	sprintf(lpbuf, "[%d %s:%05d] %s", \
		(pid_t) syscall(SYS_gettid), \
		__FUNCTION__, \
		__LINE__, \
		fmt); \
	printf(lpbuf, ## args); \
	fflush(NULL); \
} while(0)

#define PRINT_VERBOSE(cfg, cond, fmt, args...) \
do { \
	if (cond > (cfg)->sh->verbose) \
		break; \
	PRINT(fmt, ## args); \
} while(0)

#define PRINT_STATUS(cfg, fmt, args...) \
do { \
	if (!(cfg)->fstat) \
		break; \
	fprintf((cfg)->fstat, fmt, args); \
	fflush(NULL); \
} while(0)

#define BUG() \
do { \
	printf("BUG in %s:%d %s\n", \
		__FILE__, \
		__LINE__, \
		__FUNCTION__); \
} while(0)

#define BUG_ON(condition) do { if (condition) BUG(); } while(0)

#if defined(__x86_64)
#include "sysdeps/x86_64/args.h"
#endif

#endif // !CONFIG_H