From: compudj Date: Mon, 6 Mar 2006 23:44:42 +0000 (+0000) Subject: add func instrumentation X-Git-Tag: v0.12.20~1899 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=e90c7b86b16bf45ae7114266f4e48f3e2debd30c;p=lttv.git add func instrumentation git-svn-id: http://ltt.polymtl.ca/svn@1590 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/usertrace-generic/Makefile b/usertrace-generic/Makefile index f3e52e1a..e4cab2f6 100644 --- a/usertrace-generic/Makefile +++ b/usertrace-generic/Makefile @@ -2,7 +2,7 @@ CC=gcc INCLUDE_DIR=/usr/include -all: sample-thread sample sample-highspeed sample-printf +all: sample-thread sample sample-highspeed sample-printf sample-instrument-fct sample-thread: sample-thread.c ltt-facility-loader-user_generic.c $(CC) $(CFLAGS) -lpthread -o $@ $^ @@ -16,6 +16,10 @@ sample-highspeed: sample-highspeed.c ltt-facility-loader-user_generic.c sample-printf: sample-printf.c ltt-facility-loader-user_generic.c $(CC) $(CFLAGS) -o $@ $^ +sample-instrument-fct: sample-instrument-fct.c ltt-facility-loader-user_generic.c ltt-instrument-functions.c + $(CC) $(CFLAGS) -g -finstrument-functions -o $@ $^ + + .PHONY : clean install install: @@ -23,5 +27,5 @@ install: cp -f ltt/*.h $(INCLUDE_DIR)/ltt clean: - rm -fr *.o *~ sample-thread sample sample-highspeed sample-printf + rm -fr *.o *~ sample-thread sample sample-highspeed sample-printf sample-instrument-fct diff --git a/usertrace-generic/README b/usertrace-generic/README index b8c23018..9d471ebe 100644 --- a/usertrace-generic/README +++ b/usertrace-generic/README @@ -161,4 +161,36 @@ It will show, for example : user_myfacility.myevent: 39507.805584526 (/cpu_1), 15829, 15736, SYSCALL { "myapp.c", "main", 8, 1234, 0xf0f0f0f0 } +* Fun feature : function instrumentation + +Here is how to generate a full trace of you program function calls. +See the sample-instrument-fct.c example program. + +- Compile your application with at least these parameters to gcc (it is splitted + on two lines, joined by a "\") : +gcc -g -I /usr/src/usertrace-generic -o myapp myapp.c \ + /usr/src/usertrace-generic/ltt-facility-loader-user_myfacility.c \ + /usr/src/usertrace-generic/ltt-instrument-functions.c + +To see what the final result looks like : +- Start tracing +- Start your application +- Stop tracing +Then, to see only the function_entry and function_exit events : +lttv -m textDump -t /tmp/trace1 -e "event.facility=user_generic & (event.name=function_entry & event.name=function_exit)" + +It will show, for example : +user_generic.function_entry: 59329.709939111 (/cpu_0), 19250, 18581, SYSCALL { +0x8048454, 0x80484c2 } +user_generic.function_exit: 59329.709944613 (/cpu_0), 19250, 18581, SYSCALL { 0 +x8048454, 0x80484c2 } + +you can then use (from the binutils package) +addr2line -e sample-instrument-fct -i -f 0x8048454 +Which shows : +test_function +/usr/src/usertrace-generic/sample-instrument-fct.c:12 + +The lookup in LTTV through libbfd has not been implemented yet. + diff --git a/usertrace-generic/ltt-facility-loader-user_generic.h b/usertrace-generic/ltt-facility-loader-user_generic.h index 9c6b6fc5..1f93d1e3 100644 --- a/usertrace-generic/ltt-facility-loader-user_generic.h +++ b/usertrace-generic/ltt-facility-loader-user_generic.h @@ -5,11 +5,11 @@ #include ltt_facility_t ltt_facility_user_generic; -ltt_facility_t ltt_facility_user_generic_FB850A80; +ltt_facility_t ltt_facility_user_generic_F583779E; #define LTT_FACILITY_SYMBOL ltt_facility_user_generic -#define LTT_FACILITY_CHECKSUM_SYMBOL ltt_facility_user_generic_FB850A80 -#define LTT_FACILITY_CHECKSUM 0xFB850A80 +#define LTT_FACILITY_CHECKSUM_SYMBOL ltt_facility_user_generic_F583779E +#define LTT_FACILITY_CHECKSUM 0xF583779E #define LTT_FACILITY_NAME "user_generic" #define LTT_FACILITY_NUM_EVENTS facility_user_generic_num_events diff --git a/usertrace-generic/ltt-instrument-functions.c b/usertrace-generic/ltt-instrument-functions.c new file mode 100644 index 00000000..5d1b2761 --- /dev/null +++ b/usertrace-generic/ltt-instrument-functions.c @@ -0,0 +1,28 @@ +/**************************************************************************** + * ltt-instrument-functions.c + * + * Mathieu Desnoyers + * March 2006 + */ + +#define LTT_TRACE +#define LTT_BLOCKING 1 +#include + + +void __attribute__((no_instrument_function)) __cyg_profile_func_enter ( + void *this_fn, + void *call_site) +{ + /* don't care about the return value */ + trace_user_generic_function_entry(this_fn, call_site); +} + +void __attribute__((no_instrument_function)) __cyg_profile_func_exit ( + void *this_fn, + void *call_site) +{ + /* don't care about the return value */ + trace_user_generic_function_exit(this_fn, call_site); +} + diff --git a/usertrace-generic/ltt/ltt-facility-id-user_generic.h b/usertrace-generic/ltt/ltt-facility-id-user_generic.h index 4b42a0e5..87205eb3 100644 --- a/usertrace-generic/ltt/ltt-facility-id-user_generic.h +++ b/usertrace-generic/ltt/ltt-facility-id-user_generic.h @@ -6,7 +6,7 @@ /**** facility handle ****/ -extern ltt_facility_t ltt_facility_user_generic_FB850A80; +extern ltt_facility_t ltt_facility_user_generic_F583779E; extern ltt_facility_t ltt_facility_user_generic; @@ -16,6 +16,8 @@ enum user_generic_event { event_user_generic_string, event_user_generic_string_pointer, event_user_generic_slow_printf, + event_user_generic_function_entry, + event_user_generic_function_exit, facility_user_generic_num_events }; diff --git a/usertrace-generic/ltt/ltt-facility-user_generic.h b/usertrace-generic/ltt/ltt-facility-user_generic.h index b793559a..ca890b66 100644 --- a/usertrace-generic/ltt/ltt-facility-user_generic.h +++ b/usertrace-generic/ltt/ltt-facility-user_generic.h @@ -97,7 +97,7 @@ static inline int trace_user_generic_string( *len = 0; } - ret = ltt_trace_generic(ltt_facility_user_generic_FB850A80, event_user_generic_string, buffer, reserve_size, LTT_BLOCKING); + ret = ltt_trace_generic(ltt_facility_user_generic_F583779E, event_user_generic_string, buffer, reserve_size, LTT_BLOCKING); } return ret; @@ -226,7 +226,7 @@ static inline int trace_user_generic_string_pointer( *len = 0; } - ret = ltt_trace_generic(ltt_facility_user_generic_FB850A80, event_user_generic_string_pointer, buffer, reserve_size, LTT_BLOCKING); + ret = ltt_trace_generic(ltt_facility_user_generic_F583779E, event_user_generic_string_pointer, buffer, reserve_size, LTT_BLOCKING); } return ret; @@ -289,9 +289,213 @@ static inline int trace_user_generic_slow_printf_param_buffer( #else { int ret = 0; - reserve_size += ltt_align(reserve_size, sizeof(void *)); + reserve_size = ltt_align(reserve_size, sizeof(void *)); { - ret = ltt_trace_generic(ltt_facility_user_generic_FB850A80, event_user_generic_slow_printf, buffer, reserve_size, LTT_BLOCKING); + ret = ltt_trace_generic(ltt_facility_user_generic_F583779E, event_user_generic_slow_printf, buffer, reserve_size, LTT_BLOCKING); + } + + return ret; + +} +#endif //LTT_TRACE + +/* Event function_entry structures */ + +/* Event function_entry logging function */ +static inline __attribute__((no_instrument_function)) int trace_user_generic_function_entry( + const void * lttng_param_this_fn, + const void * lttng_param_call_site) +#ifndef LTT_TRACE +{ +} +#else +{ + int ret = 0; + void *buffer = NULL; + size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */ + size_t *to_base = &real_to_base; + size_t real_to = 0; + size_t *to = &real_to; + size_t real_len = 0; + size_t *len = &real_len; + size_t reserve_size; + size_t slot_size; + size_t align; + const void *real_from; + const void **from = &real_from; + /* For each field, calculate the field size. */ + /* size = *to_base + *to + *len */ + /* Assume that the padding for alignment starts at a + * sizeof(void *) address. */ + + *from = <tng_param_this_fn; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + *from = <tng_param_call_site; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + reserve_size = *to_base + *to + *len; + { + char stack_buffer[reserve_size]; + buffer = stack_buffer; + + *to_base = *to = *len = 0; + + *from = <tng_param_this_fn; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + /* Flush pending memcpy */ + if(*len != 0) { + memcpy(buffer+*to_base+*to, *from, *len); + *to += *len; + *len = 0; + } + + *from = <tng_param_call_site; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + /* Flush pending memcpy */ + if(*len != 0) { + memcpy(buffer+*to_base+*to, *from, *len); + *to += *len; + *len = 0; + } + + ret = ltt_trace_generic(ltt_facility_user_generic_F583779E, event_user_generic_function_entry, buffer, reserve_size, LTT_BLOCKING); + } + + return ret; + +} +#endif //LTT_TRACE + +/* Event function_exit structures */ + +/* Event function_exit logging function */ +static inline __attribute__((no_instrument_function)) int trace_user_generic_function_exit( + const void * lttng_param_this_fn, + const void * lttng_param_call_site) +#ifndef LTT_TRACE +{ +} +#else +{ + int ret = 0; + void *buffer = NULL; + size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */ + size_t *to_base = &real_to_base; + size_t real_to = 0; + size_t *to = &real_to; + size_t real_len = 0; + size_t *len = &real_len; + size_t reserve_size; + size_t slot_size; + size_t align; + const void *real_from; + const void **from = &real_from; + /* For each field, calculate the field size. */ + /* size = *to_base + *to + *len */ + /* Assume that the padding for alignment starts at a + * sizeof(void *) address. */ + + *from = <tng_param_this_fn; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + *from = <tng_param_call_site; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + reserve_size = *to_base + *to + *len; + { + char stack_buffer[reserve_size]; + buffer = stack_buffer; + + *to_base = *to = *len = 0; + + *from = <tng_param_this_fn; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + /* Flush pending memcpy */ + if(*len != 0) { + memcpy(buffer+*to_base+*to, *from, *len); + *to += *len; + *len = 0; + } + + *from = <tng_param_call_site; + align = sizeof(const void *); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */ + } + + *len += sizeof(const void *); + + /* Flush pending memcpy */ + if(*len != 0) { + memcpy(buffer+*to_base+*to, *from, *len); + *to += *len; + *len = 0; + } + + ret = ltt_trace_generic(ltt_facility_user_generic_F583779E, event_user_generic_function_exit, buffer, reserve_size, LTT_BLOCKING); } return ret; diff --git a/usertrace-generic/ltt/ltt-generic.h b/usertrace-generic/ltt/ltt-generic.h index efa338c3..5f5010c6 100644 --- a/usertrace-generic/ltt/ltt-generic.h +++ b/usertrace-generic/ltt/ltt-generic.h @@ -57,22 +57,27 @@ struct user_facility_info { size_t size_t_size; }; -static inline _syscall5(int, ltt_trace_generic, unsigned int, facility_id, - unsigned int, event_id, void *, data, size_t, data_size, int, blocking) -static inline _syscall2(int, ltt_register_generic, unsigned int *, facility_id, const struct user_facility_info *, info) +static inline __attribute__((no_instrument_function)) +_syscall5(int, ltt_trace_generic, unsigned int, facility_id, + unsigned int, event_id, void *, data, size_t, data_size, int, blocking) +static inline __attribute__((no_instrument_function)) +_syscall2(int, ltt_register_generic, unsigned int *, facility_id, + const struct user_facility_info *, info) #ifndef LTT_PACK /* Calculate the offset needed to align the type */ -static inline unsigned int ltt_align(size_t align_drift, - size_t size_of_type) +static inline unsigned int __attribute__((no_instrument_function)) + ltt_align(size_t align_drift, + size_t size_of_type) { size_t alignment = min(sizeof(void*), size_of_type); return ((alignment - align_drift) & (alignment-1)); } #else -static inline unsigned int ltt_align(size_t align_drift, - size_t size_of_type) +static inline unsigned int __attribute__((no_instrument_function)) + ltt_align(size_t align_drift, + size_t size_of_type) { return 0; } diff --git a/usertrace-generic/sample-instrument-fct.c b/usertrace-generic/sample-instrument-fct.c new file mode 100644 index 00000000..37140da8 --- /dev/null +++ b/usertrace-generic/sample-instrument-fct.c @@ -0,0 +1,26 @@ + + +#include +#include + +#define LTT_TRACE +#define LTT_BLOCKING 1 +#include + + +void test_function(void) +{ + printf("we are in a test function\n"); +} + + +int main(int argc, char **argv) +{ + while(1) { + test_function(); + sleep(1); + } + + return 0; +} + diff --git a/usertrace-generic/user_generic.xml b/usertrace-generic/user_generic.xml index a7000285..6e555bbc 100644 --- a/usertrace-generic/user_generic.xml +++ b/usertrace-generic/user_generic.xml @@ -17,4 +17,16 @@ + + Entry in a function + + + + + + Exit from a function + + + +