diff options
Diffstat (limited to 'dbug')
-rw-r--r-- | dbug/CMakeLists.txt | 60 | ||||
-rw-r--r-- | dbug/Makefile.am | 72 | ||||
-rw-r--r-- | dbug/dbug.c | 707 | ||||
-rwxr-xr-x | dbug/dbug_add_tags.pl | 16 | ||||
-rw-r--r-- | dbug/dbug_analyze.c | 726 | ||||
-rw-r--r-- | dbug/dbug_long.h | 16 | ||||
-rw-r--r-- | dbug/my_main.c | 17 | ||||
-rw-r--r-- | dbug/sanity.c | 13 | ||||
-rwxr-xr-x | dbug/tests-t.pl | 9 | ||||
-rw-r--r-- | dbug/tests.c | 17 | ||||
-rw-r--r-- | dbug/user.r | 102 |
11 files changed, 205 insertions, 1550 deletions
diff --git a/dbug/CMakeLists.txt b/dbug/CMakeLists.txt index fabb592dccc..a4f30f75f97 100644 --- a/dbug/CMakeLists.txt +++ b/dbug/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2006 MySQL AB +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -11,13 +11,57 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/dbug) +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/dbug + ${CMAKE_SOURCE_DIR}/include +) +SET(DBUG_SOURCES dbug.c) +ADD_CONVENIENCE_LIBRARY(dbug ${DBUG_SOURCES}) +TARGET_LINK_LIBRARIES(dbug mysys) -SET(DBUG_SOURCES dbug.c factorial.c sanity.c) +ADD_EXECUTABLE(tests tests.c) +TARGET_LINK_LIBRARIES(tests dbug) + +ADD_EXECUTABLE(factorial my_main.c factorial.c) +TARGET_LINK_LIBRARIES(factorial dbug) + +IF(NOT WIN32) + FIND_PROGRAM(GROFF groff) + FIND_PROGRAM(NROFF nroff) + SET(OUTPUT_INC output1.r output2.r output3.r output4.r output5.r) + SET(SOURCE_INC factorial.r main.r example1.r example2.r example3.r) + ADD_CUSTOM_COMMAND(OUTPUT ${OUTPUT_INC} + DEPENDS factorial + COMMAND ./factorial 1 2 3 4 5 > output1.r + COMMAND ./factorial -\#t:o 2 3 > output2.r + COMMAND ./factorial -\#d:t:o 3 > output3.r + COMMAND ./factorial -\#d,result:o 4 > output4.r + COMMAND ./factorial -\#d:f,factorial:F:L:o 3 > output5.r) + FOREACH(file ${SOURCE_INC}) + STRING(REGEX REPLACE "\\.r" ".c" srcfile ${file}) + ADD_CUSTOM_COMMAND(OUTPUT ${file} DEPENDS ${srcfile} + COMMAND sed -e 's!\\\\!\\\\\\\\!g' + <${CMAKE_CURRENT_SOURCE_DIR}/${srcfile} >${file}) + ENDFOREACH(file) + ADD_CUSTOM_COMMAND(OUTPUT dbug-t DEPENDS tests-t.pl + COMMAND cp -f ${CMAKE_CURRENT_SOURCE_DIR}/tests-t.pl dbug-t) + ADD_CUSTOM_TARGET(dbug-unit-tests ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dbug-t) + MY_ADD_TEST(dbug) + + IF(GROFF) + ADD_CUSTOM_COMMAND(OUTPUT user.ps + DEPENDS user.r ${OUTPUT_INC} ${SOURCE_INC} + COMMAND ${GROFF} -mm ${CMAKE_CURRENT_SOURCE_DIR}/user.r > user.ps || touch user.ps) + ADD_CUSTOM_TARGET(ps ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.ps) + ENDIF(GROFF) + IF(NROFF) + ADD_CUSTOM_COMMAND(OUTPUT user.t + DEPENDS user.r ${OUTPUT_INC} ${SOURCE_INC} + COMMAND ${NROFF} -mm ${CMAKE_CURRENT_SOURCE_DIR}/user.r > user.t || touch user.t) + ADD_CUSTOM_TARGET(t ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.t) + ENDIF(NROFF) + +ENDIF(NOT WIN32) -IF(NOT SOURCE_SUBLIBS) - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) - ADD_LIBRARY(dbug ${DBUG_SOURCES}) -ENDIF(NOT SOURCE_SUBLIBS) diff --git a/dbug/Makefile.am b/dbug/Makefile.am deleted file mode 100644 index e8acb0ca2c0..00000000000 --- a/dbug/Makefile.am +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (C) 2000, 2002, 2004-2006 MySQL AB -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public -# License as published by the Free Software Foundation; version 2 -# of the License. -# -# 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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 - -INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -LDADD = libdbug.a $(top_builddir)/mysys/libmysys.a $(top_builddir)/strings/libmystrings.a -pkglib_LIBRARIES = libdbug.a -noinst_LTLIBRARIES = libdbug.la -noinst_HEADERS = dbug_long.h -libdbug_la_SOURCES = dbug.c sanity.c -EXTRA_DIST = CMakeLists.txt example1.c example2.c example3.c \ - user.r monty.doc dbug_add_tags.pl \ - my_main.c main.c factorial.c dbug_analyze.c \ - CMakeLists.txt tests.c tests-t.pl -NROFF_INC = example1.r example2.r example3.r main.r \ - factorial.r output1.r output2.r output3.r \ - output4.r output5.r -CLEANFILES = $(NROFF_INC) user.t user.ps tests-t - - -# Must be linked with libs that are not compiled yet -noinst_PROGRAMS = factorial dbug_analyze tests -factorial_SOURCES = my_main.c factorial.c -tests_SOURCES = tests.c -dbug_analyze_SOURCES = dbug_analyze.c - -all: user.t user.ps tests-t - -user.t: user.r $(NROFF_INC) - -nroff -mm user.r > $@ - -user.ps: user.r $(NROFF_INC) - -groff -mm user.r > $@ - -output1.r: factorial - ./factorial 1 2 3 4 5 | cat > $@ - -output2.r: factorial - ./factorial -\#t:o 2 3 | cat >$@ - -output3.r: factorial - ./factorial -\#d:t:o 3 | cat >$@ - -output4.r: factorial - ./factorial -\#d,result:o 4 | cat >$@ - -output5.r: factorial - ./factorial -\#d:f,factorial:F:L:o 3 | cat >$@ -.c.r: - @RM@ -f $@ - @SED@ -e 's!\\!\\\\!g' $< > $@ - -# a hack to have executable in builddir, not in srcdir -tests-t: tests-t.pl - cp -f $(srcdir)/tests-t.pl ./tests-t - -libdbug_a_SOURCES= -libdbug.a: libdbug.la - $(CP) .libs/libdbug.a $@ diff --git a/dbug/dbug.c b/dbug/dbug.c index 6fa7da37504..eb7a0e9c4b6 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -53,9 +53,6 @@ * Enhanced Software Technologies, Tempe, AZ * asuvax!mcdphx!estinc!fnf * - * Binayak Banerjee (profiling enhancements) - * seismo!bpa!sjuvax!bbanerje - * * Michael Widenius: * DBUG_DUMP - To dump a block of memory. * PUSH_FLAG "O" - To be used insted of "o" if we @@ -89,19 +86,18 @@ #include <m_string.h> #include <errno.h> +#ifndef DBUG_OFF + #ifdef HAVE_FNMATCH_H #include <fnmatch.h> #else #define fnmatch(A,B,C) strcmp(A,B) #endif -#if defined(MSDOS) || defined(__WIN__) +#if defined(__WIN__) #include <process.h> #endif -#ifndef DBUG_OFF - - /* * Manifest constants which may be "tuned" if desired. */ @@ -125,17 +121,16 @@ #define DEPTH_ON (1 << 4) /* Function nest level print enabled */ #define PROCESS_ON (1 << 5) /* Process name print enabled */ #define NUMBER_ON (1 << 6) /* Number each line of output */ -#define PROFILE_ON (1 << 7) /* Print out profiling code */ #define PID_ON (1 << 8) /* Identify each line with process id */ #define TIMESTAMP_ON (1 << 9) /* timestamp every line of output */ -#define SANITY_CHECK_ON (1 << 10) /* Check safemalloc on DBUG_ENTER */ -#define FLUSH_ON_WRITE (1 << 11) /* Flush on every write */ -#define OPEN_APPEND (1 << 12) /* Open for append */ +#define FLUSH_ON_WRITE (1 << 10) /* Flush on every write */ +#define OPEN_APPEND (1 << 11) /* Open for append */ +#define SANITY_CHECK_ON (1 << 12) /* Check memory on every DBUG_ENTER/RETURN */ #define TRACE_ON ((uint)1 << 31) /* Trace enabled. MUST be the highest bit!*/ +#define sf_sanity() (0) #define TRACING (cs->stack->flags & TRACE_ON) #define DEBUGGING (cs->stack->flags & DEBUG_ON) -#define PROFILING (cs->stack->flags & PROFILE_ON) /* * Typedefs to make things more obvious. @@ -144,50 +139,16 @@ #define BOOLEAN my_bool /* - * Make it easy to change storage classes if necessary. - */ - -#define IMPORT extern /* Names defined externally */ -#define EXPORT /* Allocated here, available globally */ -#define AUTO auto /* Names to be allocated on stack */ -#define REGISTER register /* Names to be placed in registers */ - -/* - * The default file for profiling. Could also add another flag - * (G?) which allowed the user to specify this. - * - * If the automatic variables get allocated on the stack in - * reverse order from their declarations, then define AUTOS_REVERSE to 1. - * This is used by the code that keeps track of stack usage. For - * forward allocation, the difference in the dbug frame pointers - * represents stack used by the callee function. For reverse allocation, - * the difference represents stack used by the caller function. - * - */ - -#define PROF_FILE "dbugmon.out" -#define PROF_EFMT "E\t%ld\t%s\n" -#define PROF_SFMT "S\t%lx\t%lx\t%s\n" -#define PROF_XFMT "X\t%ld\t%s\n" - -#ifdef M_I386 /* predefined by xenix 386 compiler */ -#define AUTOS_REVERSE 1 -#else -#define AUTOS_REVERSE 0 -#endif - -/* * Externally supplied functions. */ #ifndef HAVE_PERROR -static void perror(); /* Fake system/library error print routine */ -#endif - -#ifdef SAFEMALLOC -IMPORT int _sanity(const char *file,uint line); /* safemalloc sanity checker */ -#else -#define _sanity(X,Y) (1) +static void perror(char *s) +{ + if (s && *s != '\0') + (void) fprintf(stderr, "%s: ", s); + (void) fprintf(stderr, "<unknown system error>\n"); +} #endif /* @@ -226,10 +187,8 @@ struct settings { uint delay; /* Delay after each output line */ uint sub_level; /* Sub this from code_state->level */ FILE *out_file; /* Current output stream */ - FILE *prof_file; /* Current profiling stream */ char name[FN_REFLEN]; /* Name of output file */ struct link *functions; /* List of functions */ - struct link *p_functions; /* List of profiled functions */ struct link *keywords; /* List of debug keywords */ struct link *processes; /* List of process names */ struct settings *next; /* Next settings in the list */ @@ -309,7 +268,7 @@ static int DoTrace(CODE_STATE *cs); #define DISABLE_TRACE 4 /* Test to see if file is writable */ -#if defined(HAVE_ACCESS) && !defined(MSDOS) +#if defined(HAVE_ACCESS) static BOOLEAN Writable(const char *pathname); /* Change file owner and group */ static void ChangeOwner(CODE_STATE *cs, char *pathname); @@ -324,48 +283,34 @@ static void Indent(CODE_STATE *cs, int indent); static void DbugFlush(CODE_STATE *); static void DbugExit(const char *why); static const char *DbugStrTok(const char *s); - -#ifndef THREAD - /* Open profile output stream */ -static FILE *OpenProfile(CODE_STATE *cs, const char *name); - /* Profile if asked for it */ -static BOOLEAN DoProfile(CODE_STATE *); - /* Return current user time (ms) */ -static unsigned long Clock(void); -#endif +static void DbugVfprintf(FILE *stream, const char* format, va_list args); /* * Miscellaneous printf format strings. */ -#define ERR_MISSING_RETURN "%s: missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n" +#define ERR_MISSING_RETURN "missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n" #define ERR_OPEN "%s: can't open debug output stream \"%s\": " #define ERR_CLOSE "%s: can't close debug file: " #define ERR_ABORT "%s: debugger aborting because %s\n" -#define ERR_CHOWN "%s: can't change owner/group of \"%s\": " /* * Macros and defines for testing file accessibility under UNIX and MSDOS. */ #undef EXISTS -#if !defined(HAVE_ACCESS) || defined(MSDOS) +#if !defined(HAVE_ACCESS) #define EXISTS(pathname) (FALSE) /* Assume no existance */ #define Writable(name) (TRUE) #else #define EXISTS(pathname) (access(pathname, F_OK) == 0) #define WRITABLE(pathname) (access(pathname, W_OK) == 0) #endif -#ifndef MSDOS -#define ChangeOwner(cs,name) -#endif - /* ** Macros to allow dbugging with threads */ -#ifdef THREAD #include <my_pthread.h> static pthread_mutex_t THR_LOCK_dbug; @@ -383,7 +328,7 @@ static CODE_STATE *code_state(void) if (!init_done) { init_done=TRUE; - pthread_mutex_init(&THR_LOCK_dbug,MY_MUTEX_INIT_FAST); + pthread_mutex_init(&THR_LOCK_dbug, NULL); bzero(&init_settings, sizeof(init_settings)); init_settings.out_file=stderr; init_settings.flags=OPEN_APPEND; @@ -396,8 +341,8 @@ static CODE_STATE *code_state(void) cs=(CODE_STATE*) DbugMalloc(sizeof(*cs)); bzero((uchar*) cs,sizeof(*cs)); cs->process= db_process ? db_process : "dbug"; - cs->func="?func"; - cs->file="?file"; + cs->func= "?func"; + cs->file= "?file"; cs->stack=&init_settings; *cs_ptr= cs; } @@ -425,59 +370,6 @@ void dbug_free_code_state(void **code_state_store) } } -#else /* !THREAD */ - -static CODE_STATE static_code_state= -{ - "dbug", "?func", "?file", NULL, &init_settings, - NullS, NullS, 0,0,0,0,0,NullS -}; - -static CODE_STATE *code_state(void) -{ - if (!init_done) - { - bzero(&init_settings, sizeof(init_settings)); - init_settings.out_file=stderr; - init_settings.flags=OPEN_APPEND; - init_done=TRUE; - } - return &static_code_state; -} - -void -dbug_swap_code_state(void **code_state_store) -{ - CODE_STATE temp, *cs; - - if (!(cs= *code_state_store)) - { - cs= (CODE_STATE *)DbugMalloc(sizeof(*cs)); - cs->process= db_process ? db_process : "dbug"; - cs->func="?func"; - cs->file="?file"; - cs->stack=&init_settings; - *code_state_store= cs; - } - memcpy(&temp, cs, sizeof(*cs)); - memcpy(cs, &static_code_state, sizeof(*cs)); - memcpy(&static_code_state, &temp, sizeof(*cs)); -} - -void -dbug_free_code_state(void **code_state_store) -{ - if (*code_state_store) - { - free(*code_state_store); - *code_state_store= NULL; - } -} - -#define pthread_mutex_lock(A) {} -#define pthread_mutex_unlock(A) {} -#endif - /* * Translate some calls among different systems. */ @@ -542,7 +434,7 @@ void _db_process_(const char *name) * 0 - a list of functions was not changed */ -int DbugParse(CODE_STATE *cs, const char *control) +static int DbugParse(CODE_STATE *cs, const char *control) { const char *end; int rel, f_used=0; @@ -559,20 +451,17 @@ int DbugParse(CODE_STATE *cs, const char *control) if (control[0] == '-' && control[1] == '#') control+=2; + rel= control[0] == '+' || control[0] == '-'; if ((!rel || (!stack->out_file && !stack->next))) { - /* If overwriting previous state, be sure to free old to avoid leak. */ - if (stack->out_file) - FreeState(cs, stack, 0); + FreeState(cs, stack, 0); stack->flags= 0; stack->delay= 0; stack->maxdepth= 0; stack->sub_level= 0; stack->out_file= stderr; - stack->prof_file= NULL; stack->functions= NULL; - stack->p_functions= NULL; stack->keywords= NULL; stack->processes= NULL; } @@ -583,20 +472,23 @@ int DbugParse(CODE_STATE *cs, const char *control) stack->maxdepth= stack->next->maxdepth; stack->sub_level= stack->next->sub_level; strcpy(stack->name, stack->next->name); - stack->out_file= stack->next->out_file; - stack->prof_file= stack->next->prof_file; if (stack->next == &init_settings) { - /* never share with the global parent - it can change under your feet */ + /* + Never share with the global parent - it can change under your feet. + + Reset out_file to stderr to prevent sharing of trace files between + global and session settings. + */ + stack->out_file= stderr; stack->functions= ListCopy(init_settings.functions); - stack->p_functions= ListCopy(init_settings.p_functions); stack->keywords= ListCopy(init_settings.keywords); stack->processes= ListCopy(init_settings.processes); } else { + stack->out_file= stack->next->out_file; stack->functions= stack->next->functions; - stack->p_functions= stack->next->p_functions; stack->keywords= stack->next->keywords; stack->processes= stack->next->processes; } @@ -606,8 +498,7 @@ int DbugParse(CODE_STATE *cs, const char *control) while (control < end) { int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0; - if (sign) - control++; + if (sign) control++; c= *control++; if (*control == ',') control++; @@ -664,15 +555,6 @@ int DbugParse(CODE_STATE *cs, const char *control) else stack->flags |= PID_ON; break; -#ifndef THREAD - case 'g': - if (OpenProfile(cs, PROF_FILE)) - { - stack->flags |= PROFILE_ON; - stack->p_functions= ListAdd(stack->p_functions, control, end); - } - break; -#endif case 'L': if (sign < 0) stack->flags &= ~LINE_ON; @@ -781,16 +663,16 @@ int DbugParse(CODE_STATE *cs, const char *control) pthread_mutex_unlock(&THR_LOCK_dbug); cs->locked= 0; } - return !rel || f_used;} + return !rel || f_used; +} - #define framep_trace_flag(cs, frp) (frp ? \ frp->level & TRACE_ON : \ (ListFlags(cs->stack->functions) & INCLUDE) ? \ 0 : (uint)TRACE_ON) -void FixTraceFlags_helper(CODE_STATE *cs, const char *func, - struct _db_stack_frame_ *framep) +static void FixTraceFlags_helper(CODE_STATE *cs, const char *func, + struct _db_stack_frame_ *framep) { if (framep->prev) FixTraceFlags_helper(cs, framep->func, framep->prev); @@ -815,7 +697,7 @@ void FixTraceFlags_helper(CODE_STATE *cs, const char *func, #define fflags(cs) cs->stack->out_file ? ListFlags(cs->stack->functions) : TRACE_ON; -void FixTraceFlags(uint old_fflags, CODE_STATE *cs) +static void FixTraceFlags(uint old_fflags, CODE_STATE *cs) { const char *func; uint new_fflags, traceon, level; @@ -900,8 +782,9 @@ yuck: * DESCRIPTION * * Given pointer to a debug control string in "control", - * parses the control string, and sets - * up a current debug settings. + * parses the control string, and sets up a current debug + * settings. Pushes a new debug settings if the current is + * set to the initial debugger settings. * */ @@ -911,6 +794,8 @@ void _db_set_(const char *control) uint old_fflags; get_code_state_or_return; old_fflags=fflags(cs); + if (cs->stack == &init_settings) + PushState(cs); if (DbugParse(cs, control)) FixTraceFlags(old_fflags, cs); } @@ -944,6 +829,7 @@ void _db_push_(const char *control) FixTraceFlags(old_fflags, cs); } + /** Returns TRUE if session-local settings have been set. */ @@ -955,7 +841,6 @@ int _db_is_pushed_() return (cs->stack != &init_settings); } - /* * FUNCTION * @@ -1006,7 +891,7 @@ void _db_pop_() get_code_state_or_return; discard= cs->stack; - if (discard->next != NULL) + if (discard != &init_settings) { old_fflags=fflags(cs); cs->stack= discard->next; @@ -1118,7 +1003,6 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len) op_list_to_buf('f', cs->stack->functions, cs->stack->functions); op_bool_to_buf('F', cs->stack->flags & FILE_ON); op_bool_to_buf('i', cs->stack->flags & PID_ON); - op_list_to_buf('g', cs->stack->p_functions, PROFILING); op_bool_to_buf('L', cs->stack->flags & LINE_ON); op_bool_to_buf('n', cs->stack->flags & DEPTH_ON); op_bool_to_buf('N', cs->stack->flags & NUMBER_ON); @@ -1226,30 +1110,14 @@ void _db_enter_(const char *_func_, const char *_file_, _stack_frame_->prev= cs->framep; _stack_frame_->level= ++cs->level | framep_trace_flag(cs, cs->framep); cs->framep= _stack_frame_; -#ifndef THREAD - if (DoProfile(cs)) - { - long stackused; - if (cs->framep->prev == NULL) - stackused= 0; - else - { - stackused= (char*)(cs->framep->prev) - (char*)(cs->framep); - stackused= stackused > 0 ? stackused : -stackused; - } - (void) fprintf(cs->stack->prof_file, PROF_EFMT , Clock(), cs->func); - (void) fprintf(cs->stack->prof_file, PROF_SFMT, (ulong) cs->framep, stackused, - AUTOS_REVERSE ? _stack_frame_->func : cs->func); - (void) fflush(cs->stack->prof_file); - } -#endif + switch (DoTrace(cs)) { case ENABLE_TRACE: cs->framep->level|= TRACE_ON; if (!TRACING) break; /* fall through */ case DO_TRACE: - if ((cs->stack->flags & SANITY_CHECK_ON) && _sanity(_file_,_line_)) + if ((cs->stack->flags & SANITY_CHECK_ON) && sf_sanity()) cs->stack->flags &= ~SANITY_CHECK_ON; if (TRACING) { @@ -1290,7 +1158,6 @@ void _db_enter_(const char *_func_, const char *_file_, * */ -/* helper macro */ void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) { int save_errno=errno; @@ -1298,34 +1165,25 @@ void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) CODE_STATE *cs; get_code_state_or_return; - if (cs->level != _slevel_) + if (cs->framep != _stack_frame_) { - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); - (void) fprintf(cs->stack->out_file, ERR_MISSING_RETURN, cs->process, - cs->func); - DbugFlush(cs); + char buf[512]; + my_snprintf(buf, sizeof(buf), ERR_MISSING_RETURN, cs->func); + DbugExit(buf); } - else + + if (DoTrace(cs) & DO_TRACE) { -#ifndef THREAD - if (DoProfile(cs)) - (void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func); -#endif - if (DoTrace(cs) & DO_TRACE) + if ((cs->stack->flags & SANITY_CHECK_ON) && sf_sanity()) + cs->stack->flags &= ~SANITY_CHECK_ON; + if (TRACING) { - if ((cs->stack->flags & SANITY_CHECK_ON) && - _sanity(_stack_frame_->file,_line_)) - cs->stack->flags &= ~SANITY_CHECK_ON; - if (TRACING) - { - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); - DoPrefix(cs, _line_); - Indent(cs, cs->level); - (void) fprintf(cs->stack->out_file, "<%s\n", cs->func); - DbugFlush(cs); - } + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); + DoPrefix(cs, _line_); + Indent(cs, cs->level); + (void) fprintf(cs->stack->out_file, "<%s\n", cs->func); + DbugFlush(cs); } } /* @@ -1415,8 +1273,7 @@ void _db_doprnt_(const char *format,...) else (void) fprintf(cs->stack->out_file, "%s: ", cs->func); (void) fprintf(cs->stack->out_file, "%s: ", cs->u_keyword); - (void) vfprintf(cs->stack->out_file, format, args); - (void) fputc('\n',cs->stack->out_file); + DbugVfprintf(cs->stack->out_file, format, args); DbugFlush(cs); errno=save_errno; } @@ -1426,6 +1283,18 @@ void _db_doprnt_(const char *format,...) va_end(args); } +/* + * This function is intended as a + * vfprintf clone with consistent, platform independent output for + * problematic formats like %p, %zd and %lld. + */ +static void DbugVfprintf(FILE *stream, const char* format, va_list args) +{ + char cvtbuf[1024]; + (void) my_vsnprintf(cvtbuf, sizeof(cvtbuf), format, args); + (void) fprintf(stream, "%s\n", cvtbuf); +} + /* * FUNCTION @@ -1442,14 +1311,13 @@ void _db_doprnt_(const char *format,...) * * DESCRIPTION * Dump N characters in a binary array. - * Is used to examine corrputed memory or arrays. + * Is used to examine corrupted memory or arrays. */ void _db_dump_(uint _line_, const char *keyword, const unsigned char *memory, size_t length) { int pos; - char dbuff[90]; CODE_STATE *cs; get_code_state_or_return; @@ -1467,9 +1335,8 @@ void _db_dump_(uint _line_, const char *keyword, { fprintf(cs->stack->out_file, "%s: ", cs->func); } - sprintf(dbuff,"%s: Memory: 0x%lx Bytes: (%ld)\n", + (void) fprintf(cs->stack->out_file, "%s: Memory: 0x%lx Bytes: (%ld)\n", keyword, (ulong) memory, (long) length); - (void) fputs(dbuff,cs->stack->out_file); pos=0; while (length-- > 0) @@ -1521,7 +1388,8 @@ static struct link *ListAddDel(struct link *head, const char *ctlp, { const char *start; struct link **cur; - int len, subdir; + size_t len; + int subdir; ctlp--; next: @@ -1531,7 +1399,7 @@ next: subdir=0; while (ctlp < end && *ctlp != ',') ctlp++; - len=ctlp-start; + len= (int) (ctlp-start); if (start[len-1] == '/') { len--; @@ -1594,7 +1462,7 @@ static struct link *ListCopy(struct link *orig) { struct link *new_malloc; struct link *head; - int len; + size_t len; head= NULL; while (orig != NULL) @@ -1688,7 +1556,7 @@ static void PushState(CODE_STATE *cs) struct settings *new_malloc; new_malloc= (struct settings *) DbugMalloc(sizeof(struct settings)); - bzero(new_malloc, sizeof(struct settings)); + bzero(new_malloc, sizeof(*new_malloc)); new_malloc->next= cs->stack; cs->stack= new_malloc; } @@ -1718,15 +1586,12 @@ static void FreeState(CODE_STATE *cs, struct settings *state, int free_state) FreeList(state->functions); if (!is_shared(state, processes)) FreeList(state->processes); - if (!is_shared(state, p_functions)) - FreeList(state->p_functions); - if (!is_shared(state, out_file) && - state->out_file != stderr && state->out_file != stdout) + + if (!is_shared(state, out_file)) DBUGCloseFile(cs, state->out_file); - (void) fflush(cs->stack->out_file); - if (state->prof_file && - state->prof_file != stderr && state->prof_file != stdout) - DBUGCloseFile(cs, state->prof_file); + else + (void) fflush(state->out_file); + if (free_state) free((void*) state); } @@ -1759,30 +1624,26 @@ void _db_end_() called after dbug was initialized */ _dbug_on_= 1; - get_code_state_or_return; + cs= code_state(); - while ((discard= cs->stack)) - { - if (discard == &init_settings) - break; - cs->stack= discard->next; - FreeState(cs, discard, 1); - } + if (cs) + while ((discard= cs->stack)) + { + if (discard == &init_settings) + break; + cs->stack= discard->next; + FreeState(cs, discard, 1); + } tmp= init_settings; - /* Use mutex lock to make it less likely anyone access out_file */ - pthread_mutex_lock(&THR_LOCK_dbug); init_settings.flags= OPEN_APPEND; init_settings.out_file= stderr; - init_settings.prof_file= stderr; init_settings.maxdepth= 0; init_settings.delay= 0; init_settings.sub_level= 0; init_settings.functions= 0; - init_settings.p_functions= 0; init_settings.keywords= 0; init_settings.processes= 0; - pthread_mutex_unlock(&THR_LOCK_dbug); FreeState(cs, &tmp, 0); } @@ -1818,36 +1679,6 @@ static int DoTrace(CODE_STATE *cs) return DONT_TRACE; } - -/* - * FUNCTION - * - * DoProfile check to see if profiling is current enabled - * - * SYNOPSIS - * - * static BOOLEAN DoProfile() - * - * DESCRIPTION - * - * Checks to see if profiling is enabled based on whether the - * user has specified profiling, the maximum trace depth has - * not yet been reached, the current function is selected, - * and the current process is selected. Returns TRUE if - * profiling is enabled, FALSE otherwise. - * - */ - -#ifndef THREAD -static BOOLEAN DoProfile(CODE_STATE *cs) -{ - return (PROFILING && - cs->level <= cs->stack->maxdepth && - InList(cs->stack->p_functions, cs->func, 0) & (INCLUDE|MATCHED) && - InList(cs->stack->processes, cs->process, 0) & (INCLUDE|MATCHED)); -} -#endif - FILE *_db_fp_(void) { CODE_STATE *cs; @@ -1907,7 +1738,7 @@ BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict) static void Indent(CODE_STATE *cs, int indent) { - REGISTER int count; + int count; indent= max(indent-1-cs->stack->sub_level,0)*INDENT; for (count= 0; count < indent ; count++) @@ -1939,7 +1770,7 @@ static void Indent(CODE_STATE *cs, int indent) static void FreeList(struct link *linkp) { - REGISTER struct link *old; + struct link *old; while (linkp != NULL) { @@ -1974,11 +1805,7 @@ static void DoPrefix(CODE_STATE *cs, uint _line_) cs->lineno++; if (cs->stack->flags & PID_ON) { -#ifdef THREAD (void) fprintf(cs->stack->out_file, "%-7s: ", my_thread_name()); -#else - (void) fprintf(cs->stack->out_file, "%5d: ", (int) getpid()); -#endif } if (cs->stack->flags & NUMBER_ON) (void) fprintf(cs->stack->out_file, "%5d: ", cs->lineno); @@ -2042,14 +1869,13 @@ static void DoPrefix(CODE_STATE *cs, uint _line_) static void DBUGOpenFile(CODE_STATE *cs, const char *name,const char *end,int append) { - REGISTER FILE *fp; - REGISTER BOOLEAN newfile; + FILE *fp; if (name != NULL) { if (end) { - int len=end-name; + size_t len=end-name; memcpy(cs->stack->name, name, len); cs->stack->name[len]=0; } @@ -2072,7 +1898,6 @@ static void DBUGOpenFile(CODE_STATE *cs, } else { - newfile= !EXISTS(name); if (!(fp= fopen(name, append ? "a+" : "w"))) { (void) fprintf(stderr, ERR_OPEN, cs->process, name); @@ -2082,77 +1907,12 @@ static void DBUGOpenFile(CODE_STATE *cs, else { cs->stack->out_file= fp; - if (newfile) - { - ChangeOwner(cs, name); - } } } } } } - -/* - * FUNCTION - * - * OpenProfile open new output stream for profiler output - * - * SYNOPSIS - * - * static FILE *OpenProfile(name) - * char *name; - * - * DESCRIPTION - * - * Given name of a new file, opens the file - * and sets the profiler output stream to the new file. - * - * It is currently unclear whether the prefered behavior is - * to truncate any existing file, or simply append to it. - * The latter behavior would be desirable for collecting - * accumulated runtime history over a number of separate - * runs. It might take some changes to the analyzer program - * though, and the notes that Binayak sent with the profiling - * diffs indicated that append was the normal mode, but this - * does not appear to agree with the actual code. I haven't - * investigated at this time [fnf; 24-Jul-87]. - */ - -#ifndef THREAD -static FILE *OpenProfile(CODE_STATE *cs, const char *name) -{ - REGISTER FILE *fp; - REGISTER BOOLEAN newfile; - - fp=0; - if (!Writable(name)) - { - (void) fprintf(cs->stack->out_file, ERR_OPEN, cs->process, name); - perror(""); - (void) Delay(cs->stack->delay); - } - else - { - newfile= !EXISTS(name); - if (!(fp= fopen(name, "w"))) - { - (void) fprintf(cs->stack->out_file, ERR_OPEN, cs->process, name); - perror(""); - } - else - { - cs->stack->prof_file= fp; - if (newfile) - { - ChangeOwner(cs, name); - } - } - } - return fp; -} -#endif - /* * FUNCTION * @@ -2172,7 +1932,7 @@ static FILE *OpenProfile(CODE_STATE *cs, const char *name) static void DBUGCloseFile(CODE_STATE *cs, FILE *fp) { - if (fp != NULL && fp != stderr && fp != stdout && fclose(fp) == EOF) + if (cs && fp && fp != stderr && fp != stdout && fclose(fp) == EOF) { if (!cs->locked) pthread_mutex_lock(&THR_LOCK_dbug); @@ -2207,7 +1967,7 @@ static void DbugExit(const char *why) CODE_STATE *cs=code_state(); (void) fprintf(stderr, ERR_ABORT, cs ? cs->process : "(null)", why); (void) fflush(stderr); - exit(1); + DBUG_ABORT(); } @@ -2234,7 +1994,7 @@ static void DbugExit(const char *why) static char *DbugMalloc(size_t size) { - register char *new_malloc; + char *new_malloc; if (!(new_malloc= (char*) malloc(size))) DbugExit("out of memory"); @@ -2275,7 +2035,7 @@ static const char *DbugStrTok(const char *s) static const char *BaseName(const char *pathname) { - register const char *base; + const char *base; base= strrchr(pathname, FN_LIBCHAR); if (base++ == NullS) @@ -2312,8 +2072,8 @@ static const char *BaseName(const char *pathname) static BOOLEAN Writable(const char *pathname) { - REGISTER BOOLEAN granted; - REGISTER char *lastslash; + BOOLEAN granted; + char *lastslash; granted= FALSE; if (EXISTS(pathname)) @@ -2337,141 +2097,11 @@ static BOOLEAN Writable(const char *pathname) } #endif - -/* - * FUNCTION - * - * ChangeOwner change owner to real user for suid programs - * - * SYNOPSIS - * - * static VOID ChangeOwner(pathname) - * - * DESCRIPTION - * - * For unix systems, change the owner of the newly created debug - * file to the real owner. This is strictly for the benefit of - * programs that are running with the set-user-id bit set. - * - * Note that at this point, the fact that pathname represents - * a newly created file has already been established. If the - * program that the debugger is linked to is not running with - * the suid bit set, then this operation is redundant (but - * harmless). - * - */ - -#ifndef ChangeOwner -static void ChangeOwner(CODE_STATE *cs, char *pathname) -{ - if (chown(pathname, getuid(), getgid()) == -1) - { - (void) fprintf(stderr, ERR_CHOWN, cs->process, pathname); - perror(""); - (void) fflush(stderr); - } -} -#endif - - -/* - * FUNCTION - * - * _db_setjmp_ save debugger environment - * - * SYNOPSIS - * - * VOID _db_setjmp_() - * - * DESCRIPTION - * - * Invoked as part of the user's DBUG_SETJMP macro to save - * the debugger environment in parallel with saving the user's - * environment. - * - */ - -#ifdef HAVE_LONGJMP - -EXPORT void _db_setjmp_() -{ - CODE_STATE *cs; - get_code_state_or_return; - - cs->jmplevel= cs->level; - cs->jmpfunc= cs->func; - cs->jmpfile= cs->file; -} - -/* - * FUNCTION - * - * _db_longjmp_ restore previously saved debugger environment - * - * SYNOPSIS - * - * VOID _db_longjmp_() - * - * DESCRIPTION - * - * Invoked as part of the user's DBUG_LONGJMP macro to restore - * the debugger environment in parallel with restoring the user's - * previously saved environment. - * - */ - -EXPORT void _db_longjmp_() -{ - CODE_STATE *cs; - get_code_state_or_return; - - cs->level= cs->jmplevel; - if (cs->jmpfunc) - cs->func= cs->jmpfunc; - if (cs->jmpfile) - cs->file= cs->jmpfile; -} -#endif - /* - * FUNCTION - * - * perror perror simulation for systems that don't have it - * - * SYNOPSIS - * - * static VOID perror(s) - * char *s; - * - * DESCRIPTION - * - * Perror produces a message on the standard error stream which - * provides more information about the library or system error - * just encountered. The argument string s is printed, followed - * by a ':', a blank, and then a message and a newline. - * - * An undocumented feature of the unix perror is that if the string - * 's' is a null string (NOT a NULL pointer!), then the ':' and - * blank are not printed. - * - * This version just complains about an "unknown system error". - * - */ - -#ifndef HAVE_PERROR -static void perror(s) -char *s; -{ - if (s && *s != '\0') - (void) fprintf(stderr, "%s: ", s); - (void) fprintf(stderr, "<unknown system error>\n"); -} -#endif /* HAVE_PERROR */ - - - /* flush dbug-stream, free mutex lock & wait delay */ - /* This is because some systems (MSDOS!!) dosn't flush fileheader */ - /* and dbug-file isn't readable after a system crash !! */ + flush dbug-stream, free mutex lock & wait delay + This is because some systems (MSDOS!!) dosn't flush fileheader + and dbug-file isn't readable after a system crash !! +*/ static void DbugFlush(CODE_STATE *cs) { @@ -2531,124 +2161,21 @@ void _db_unlock_file_() pthread_mutex_unlock(&THR_LOCK_dbug); } -/* - * Here we need the definitions of the clock routine. Add your - * own for whatever system that you have. - */ - -#ifndef THREAD -#if defined(HAVE_GETRUSAGE) - -#include <sys/param.h> -#include <sys/resource.h> - -/* extern int getrusage(int, struct rusage *); */ - -/* - * Returns the user time in milliseconds used by this process so - * far. - */ - -static unsigned long Clock() -{ - struct rusage ru; - - (void) getrusage(RUSAGE_SELF, &ru); - return ru.ru_utime.tv_sec*1000 + ru.ru_utime.tv_usec/1000; -} - -#elif defined(MSDOS) || defined(__WIN__) - -static ulong Clock() +const char* _db_get_func_(void) { - return clock()*(1000/CLOCKS_PER_SEC); -} -#elif defined(amiga) - -struct DateStamp { /* Yes, this is a hack, but doing it right */ - long ds_Days; /* is incredibly ugly without splitting this */ - long ds_Minute; /* off into a separate file */ - long ds_Tick; -}; - -static int first_clock= TRUE; -static struct DateStamp begin; -static struct DateStamp elapsed; - -static unsigned long Clock() -{ - register struct DateStamp *now; - register unsigned long millisec= 0; - extern VOID *AllocMem(); - - now= (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), 0L); - if (now != NULL) - { - if (first_clock == TRUE) - { - first_clock= FALSE; - (void) DateStamp(now); - begin= *now; - } - (void) DateStamp(now); - millisec= 24 * 3600 * (1000 / HZ) * (now->ds_Days - begin.ds_Days); - millisec += 60 * (1000 / HZ) * (now->ds_Minute - begin.ds_Minute); - millisec += (1000 / HZ) * (now->ds_Tick - begin.ds_Tick); - (void) FreeMem(now, (long) sizeof(struct DateStamp)); - } - return millisec; -} -#else -static unsigned long Clock() -{ - return 0; -} -#endif /* RUSAGE */ -#endif /* THREADS */ - -#ifdef NO_VARARGS - -/* - * Fake vfprintf for systems that don't support it. If this - * doesn't work, you are probably SOL... - */ - -static int vfprintf(stream, format, ap) -FILE *stream; -char *format; -va_list ap; -{ - int rtnval; - ARGS_DCL; - - ARG0= va_arg(ap, ARGS_TYPE); - ARG1= va_arg(ap, ARGS_TYPE); - ARG2= va_arg(ap, ARGS_TYPE); - ARG3= va_arg(ap, ARGS_TYPE); - ARG4= va_arg(ap, ARGS_TYPE); - ARG5= va_arg(ap, ARGS_TYPE); - ARG6= va_arg(ap, ARGS_TYPE); - ARG7= va_arg(ap, ARGS_TYPE); - ARG8= va_arg(ap, ARGS_TYPE); - ARG9= va_arg(ap, ARGS_TYPE); - rtnval= fprintf(stream, format, ARGS_LIST); - return rtnval; + CODE_STATE *cs; + get_code_state_or_return NULL; + return cs->func; } -#endif /* NO_VARARGS */ - #else /* - * Dummy function, workaround for MySQL bug#14420 related - * build failure on a platform where linking with an empty - * archive fails. - * - * This block can be removed as soon as a fix for bug#14420 - * is implemented. + * Dummy function, workaround for build failure on a platform where linking + * with an empty archive fails. */ int i_am_a_dummy_function() { - return 0; + return 0; } -#endif +#endif /* DBUG_OFF */ diff --git a/dbug/dbug_add_tags.pl b/dbug/dbug_add_tags.pl index 9653124cfd0..fe3637b4d12 100755 --- a/dbug/dbug_add_tags.pl +++ b/dbug/dbug_add_tags.pl @@ -1,5 +1,21 @@ #!/usr/bin/perl +# Copyright (c) 2002 MySQL AB, 2009 Sun Microsystems, Inc. +# Use is subject to license terms. +# +# This program 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; version 2 of the License. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + die "No files specified\n" unless $ARGV[0]; $ctags="exctags -x -f - --c-types=f -u"; diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c deleted file mode 100644 index 3263b2ccc59..00000000000 --- a/dbug/dbug_analyze.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Analyze the profile file (cmon.out) written out by the dbug - * routines with profiling enabled. - * - * Copyright June 1987, Binayak Banerjee - * All rights reserved. - * - * This program may be freely distributed under the same terms and - * conditions as Fred Fish's Dbug package. - * - * Compile with -- cc -O -s -o %s analyze.c - * - * Analyze will read an trace file created by the dbug package - * (when run with traceing enabled). It will then produce a - * summary on standard output listing the name of each traced - * function, the number of times it was called, the percentage - * of total calls, the time spent executing the function, the - * proportion of the total time and the 'importance'. The last - * is a metric which is obtained by multiplying the proportions - * of calls and the proportions of time for each function. The - * greater the importance, the more likely it is that a speedup - * could be obtained by reducing the time taken by that function. - * - * Note that the timing values that you obtain are only rough - * measures. The overhead of the dbug package is included - * within. However, there is no need to link in special profiled - * libraries and the like. - * - * CHANGES: - * - * 2-Mar-89: fnf - * Changes to support tracking of stack usage. This required - * reordering the fields in the profile log file to make - * parsing of different record types easier. Corresponding - * changes made in dbug runtime library. Also used this - * opportunity to reformat the code more to my liking (my - * apologies to Binayak Banerjee for "uglifying" his code). - * - * 24-Jul-87: fnf - * Because I tend to use functions names like - * "ExternalFunctionDoingSomething", I've rearranged the - * printout to put the function name last in each line, so - * long names don't screw up the formatting unless they are - * *very* long and wrap around the screen width... - * - * 24-Jul-87: fnf - * Modified to put out table very similar to Unix profiler - * by default, but also puts out original verbose table - * if invoked with -v flag. - */ - -#include <my_global.h> -#include <m_string.h> -#include <my_pthread.h> - -static char *my_name; -static int verbose; - -/* - * Structure of the stack. - */ - -#define PRO_FILE "dbugmon.out" /* Default output file name */ -#define STACKSIZ 100 /* Maximum function nesting */ -#define MAXPROCS 10000 /* Maximum number of function calls */ - -# ifdef BSD -# include <sysexits.h> -# else -# define EX_SOFTWARE 1 -# define EX_DATAERR 1 -# define EX_USAGE 1 -# define EX_OSERR 1 -# define EX_IOERR 1 -#ifndef EX_OK -# define EX_OK 0 -#endif -# endif - -#define __MERF_OO_ "%s: Malloc Failed in %s: %d\n" - -#define MALLOC(Ptr,Num,Typ) do /* Malloc w/error checking & exit */ \ - if (!(Ptr = (Typ *)malloc((Num)*(sizeof(Typ))))) \ - {fprintf(stderr,__MERF_OO_,my_name,__FILE__,__LINE__);\ - exit(EX_OSERR);} while(0) - -#define Malloc(Ptr,Num,Typ) do /* Weaker version of above */\ - if (!(Ptr = (Typ *)malloc((Num)*(sizeof(Typ))))) \ - fprintf(stderr,__MERF_OO_,my_name,__FILE__,__LINE__);\ - while(0) - -#define FILEOPEN(Fp,Fn,Mod) do /* File open with error exit */ \ - if (!(Fp = fopen(Fn,Mod)))\ - {fprintf(stderr,"%s: Couldn't open %s\n",my_name,Fn);\ - exit(EX_IOERR);} while(0) - -#define Fileopen(Fp,Fn,Mod) do /* Weaker version of above */ \ - if(!(Fp = fopen(Fn,Mod))) \ - fprintf(stderr,"%s: Couldn't open %s\n",my_name,Fn);\ - while(0) - - -struct stack_t { - unsigned int pos; /* which function? */ - unsigned long time; /* Time that this was entered */ - unsigned long children; /* Time spent in called funcs */ -}; - -static struct stack_t fn_stack[STACKSIZ+1]; - -static unsigned int stacktop = 0; /* Lowest stack position is a dummy */ - -static unsigned long tot_time = 0; -static unsigned long tot_calls = 0; -static unsigned long highstack = 0; -static unsigned long lowstack = (ulong) ~0; - -/* - * top() returns a pointer to the top item on the stack. - * (was a function, now a macro) - */ - -#define top() &fn_stack[stacktop] - -/* - * Push - Push the given record on the stack. - */ - -void push (name_pos, time_entered) -register unsigned int name_pos; -register unsigned long time_entered; -{ - register struct stack_t *t; - - DBUG_ENTER("push"); - if (++stacktop > STACKSIZ) { - fprintf (DBUG_FILE,"%s: stack overflow (%s:%d)\n", - my_name, __FILE__, __LINE__); - exit (EX_SOFTWARE); - } - DBUG_PRINT ("push", ("%d %ld",name_pos,time_entered)); - t = &fn_stack[stacktop]; - t -> pos = name_pos; - t -> time = time_entered; - t -> children = 0; - DBUG_VOID_RETURN; -} - -/* - * Pop - pop the top item off the stack, assigning the field values - * to the arguments. Returns 0 on stack underflow, or on popping first - * item off stack. - */ - -unsigned int pop (name_pos, time_entered, child_time) -register unsigned int *name_pos; -register unsigned long *time_entered; -register unsigned long *child_time; -{ - register struct stack_t *temp; - register unsigned int rtnval; - - DBUG_ENTER ("pop"); - - if (stacktop < 1) { - rtnval = 0; - } else { - temp = &fn_stack[stacktop]; - *name_pos = temp->pos; - *time_entered = temp->time; - *child_time = temp->children; - DBUG_PRINT ("pop", ("%d %lu %lu",*name_pos,*time_entered,*child_time)); - rtnval = stacktop--; - } - DBUG_RETURN (rtnval); -} - -/* - * We keep the function info in another array (serves as a simple - * symbol table) - */ - -struct module_t { - char *name; - unsigned long m_time; - unsigned long m_calls; - unsigned long m_stkuse; -}; - -static struct module_t modules[MAXPROCS]; - -/* - * We keep a binary search tree in order to look up function names - * quickly (and sort them at the end. - */ - -struct bnode { - unsigned int lchild; /* Index of left subtree */ - unsigned int rchild; /* Index of right subtree */ - unsigned int pos; /* Index of module_name entry */ -}; - -static struct bnode s_table[MAXPROCS]; - -static unsigned int n_items = 0; /* No. of items in the array so far */ - -/* - * Need a function to allocate space for a string and squirrel it away. - */ - -char *strsave (s) -char *s; -{ - register char *retval; - register unsigned int len; - - DBUG_ENTER ("strsave"); - DBUG_PRINT ("strsave", ("%s",s)); - if (!s || (len = strlen (s)) == 0) { - DBUG_RETURN (0); - } - MALLOC (retval, ++len, char); - strcpy (retval, s); - DBUG_RETURN (retval); -} - -/* - * add() - adds m_name to the table (if not already there), and returns - * the index of its location in the table. Checks s_table (which is a - * binary search tree) to see whether or not it should be added. - */ - -unsigned int add (m_name) -char *m_name; -{ - register unsigned int ind = 0; - register int cmp; - - DBUG_ENTER ("add"); - if (n_items == 0) { /* First item to be added */ - s_table[0].pos = ind; - s_table[0].lchild = s_table[0].rchild = MAXPROCS; - addit: - modules[n_items].name = strsave (m_name); - modules[n_items].m_time = 0; - modules[n_items].m_calls = 0; - modules[n_items].m_stkuse = 0; - DBUG_RETURN (n_items++); - } - while ((cmp = strcmp (m_name,modules[ind].name))) { - if (cmp < 0) { /* In left subtree */ - if (s_table[ind].lchild == MAXPROCS) { - /* Add as left child */ - if (n_items >= MAXPROCS) { - fprintf (DBUG_FILE, - "%s: Too many functions being profiled\n", - my_name); - exit (EX_SOFTWARE); - } - s_table[n_items].pos = s_table[ind].lchild = n_items; - s_table[n_items].lchild = s_table[n_items].rchild = MAXPROCS; -#ifdef notdef - modules[n_items].name = strsave (m_name); - modules[n_items].m_time = modules[n_items].m_calls = 0; - DBUG_RETURN (n_items++); -#else - goto addit; -#endif - - } - ind = s_table[ind].lchild; /* else traverse l-tree */ - } else { - if (s_table[ind].rchild == MAXPROCS) { - /* Add as right child */ - if (n_items >= MAXPROCS) { - fprintf (DBUG_FILE, - "%s: Too many functions being profiled\n", - my_name); - exit (EX_SOFTWARE); - } - s_table[n_items].pos = s_table[ind].rchild = n_items; - s_table[n_items].lchild = s_table[n_items].rchild = MAXPROCS; -#ifdef notdef - modules[n_items].name = strsave (m_name); - modules[n_items].m_time = modules[n_items].m_calls = 0; - DBUG_RETURN (n_items++); -#else - goto addit; -#endif - - } - ind = s_table[ind].rchild; /* else traverse r-tree */ - } - } - DBUG_RETURN (ind); -} - -/* - * process() - process the input file, filling in the modules table. - */ - -void process (inf) -FILE *inf; -{ - char buf[BUFSIZ]; - char fn_name[64]; /* Max length of fn_name */ - unsigned long fn_time; - unsigned long fn_sbot; - unsigned long fn_ssz; - unsigned long lastuse; - unsigned int pos; - unsigned long local_time; - unsigned int oldpos; - unsigned long oldtime; - unsigned long oldchild; - struct stack_t *t; - - DBUG_ENTER ("process"); - while (fgets (buf,BUFSIZ,inf) != NULL) { - switch (buf[0]) { - case 'E': - sscanf (buf+2, "%ld %64s", &fn_time, fn_name); - DBUG_PRINT ("erec", ("%ld %s", fn_time, fn_name)); - pos = add (fn_name); - push (pos, fn_time); - break; - case 'X': - sscanf (buf+2, "%ld %64s", &fn_time, fn_name); - DBUG_PRINT ("xrec", ("%ld %s", fn_time, fn_name)); - pos = add (fn_name); - /* - * An exited function implies that all stacked - * functions are also exited, until the matching - * function is found on the stack. - */ - while (pop (&oldpos, &oldtime, &oldchild)) { - DBUG_PRINT ("popped", ("%lu %lu", oldtime, oldchild)); - local_time = fn_time - oldtime; - t = top (); - t -> children += local_time; - DBUG_PRINT ("update", ("%s", modules[t -> pos].name)); - DBUG_PRINT ("update", ("%lu", t -> children)); - local_time -= oldchild; - modules[oldpos].m_time += local_time; - modules[oldpos].m_calls++; - tot_time += local_time; - tot_calls++; - if (pos == oldpos) { - goto next_line; /* Should be a break2 */ - } - } - /* - * Assume that item seen started at time 0. - * (True for function main). But initialize - * it so that it works the next time too. - */ - t = top (); - local_time = fn_time - t -> time - t -> children; - t -> time = fn_time; t -> children = 0; - modules[pos].m_time += local_time; - modules[pos].m_calls++; - tot_time += local_time; - tot_calls++; - break; - case 'S': - sscanf (buf+2, "%lx %lx %64s", &fn_sbot, &fn_ssz, fn_name); - DBUG_PRINT ("srec", ("%lx %lx %s", fn_sbot, fn_ssz, fn_name)); - pos = add (fn_name); - lastuse = modules[pos].m_stkuse; -#if 0 - /* - * Needs further thought. Stack use is determined by - * difference in stack between two functions with DBUG_ENTER - * macros. If A calls B calls C, where A and C have the - * macros, and B doesn't, then B's stack use will be lumped - * in with either A's or C's. If somewhere else A calls - * C directly, the stack use will seem to change. Just - * take the biggest for now... - */ - if (lastuse > 0 && lastuse != fn_ssz) { - fprintf (stderr, - "warning - %s stack use changed (%lx to %lx)\n", - fn_name, lastuse, fn_ssz); - } -#endif - if (fn_ssz > lastuse) { - modules[pos].m_stkuse = fn_ssz; - } - if (fn_sbot > highstack) { - highstack = fn_sbot; - } else if (fn_sbot < lowstack) { - lowstack = fn_sbot; - } - break; - default: - fprintf (stderr, "unknown record type '%c'\n", buf[0]); - break; - } - next_line:; - } - - /* - * Now, we've hit eof. If we still have stuff stacked, then we - * assume that the user called exit, so give everything the exited - * time of fn_time. - */ - while (pop (&oldpos,&oldtime,&oldchild)) { - local_time = fn_time - oldtime; - t = top (); - t -> children += local_time; - local_time -= oldchild; - modules[oldpos].m_time += local_time; - modules[oldpos].m_calls++; - tot_time += local_time; - tot_calls++; - } - DBUG_VOID_RETURN; -} - -/* - * out_header () -- print out the header of the report. - */ - -void out_header (outf) -FILE *outf; -{ - DBUG_ENTER ("out_header"); - if (verbose) { - fprintf (outf, "Profile of Execution\n"); - fprintf (outf, "Execution times are in milliseconds\n\n"); - fprintf (outf, " Calls\t\t\t Time\n"); - fprintf (outf, " -----\t\t\t ----\n"); - fprintf (outf, "Times\tPercentage\tTime Spent\tPercentage\n"); - fprintf (outf, "Called\tof total\tin Function\tof total Importance\tFunction\n"); - fprintf (outf, "======\t==========\t===========\t========== ==========\t========\t\n"); - } else { - fprintf (outf, "%ld bytes of stack used, from %lx down to %lx\n\n", - highstack - lowstack, highstack, lowstack); - fprintf (outf, - " %%time sec #call ms/call %%calls weight stack name\n"); - } - DBUG_VOID_RETURN; -} - -/* - * out_trailer () - writes out the summary line of the report. - */ - -void out_trailer (outf,sum_calls,sum_time) -FILE *outf; -unsigned long int sum_calls, sum_time; -{ - DBUG_ENTER ("out_trailer"); - if (verbose) - { - fprintf(outf, "======\t==========\t===========\t==========\t========\n"); - fprintf(outf, "%6ld\t%10.2f\t%11ld\t%10.2f\t\t%-15s\n", - sum_calls, 100.0, sum_time, 100.0, "Totals"); - } - DBUG_VOID_RETURN; -} - -/* - * out_item () - prints out the output line for a single entry, - * and sets the calls and time fields appropriately. - */ - -void out_item (outf, m,called,timed) -FILE *outf; -register struct module_t *m; -unsigned long int *called, *timed; -{ - char *name = m -> name; - register unsigned int calls = m -> m_calls; - register unsigned long local_time = m -> m_time; - register unsigned long stkuse = m -> m_stkuse; - unsigned int import; - double per_time = 0.0; - double per_calls = 0.0; - double ms_per_call, local_ftime; - - DBUG_ENTER ("out_item"); - - if (tot_time > 0) { - per_time = (double) (local_time * 100) / (double) tot_time; - } - if (tot_calls > 0) { - per_calls = (double) (calls * 100) / (double) tot_calls; - } - import = (unsigned int) (per_time * per_calls); - - if (verbose) { - fprintf (outf, "%6d\t%10.2f\t%11ld\t%10.2f %10d\t%-15s\n", - calls, per_calls, local_time, per_time, import, name); - } else { - ms_per_call = local_time; - ms_per_call /= calls; - local_ftime = local_time; - local_ftime /= 1000; - fprintf(outf, "%8.2f%8.3f%8u%8.3f%8.2f%8u%8lu %-s\n", - per_time, local_ftime, calls, ms_per_call, per_calls, import, - stkuse, name); - } - *called = calls; - *timed = local_time; - DBUG_VOID_RETURN; -} - -/* - * out_body (outf, root,s_calls,s_time) -- Performs an inorder traversal - * on the binary search tree (root). Calls out_item to actually print - * the item out. - */ - -void out_body (outf, root,s_calls,s_time) -FILE *outf; -register unsigned int root; -register unsigned long int *s_calls, *s_time; -{ - unsigned long int calls, local_time; - - DBUG_ENTER ("out_body"); - DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time)); - if (root == MAXPROCS) { - DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time)); - } else { - while (root != MAXPROCS) { - out_body (outf, s_table[root].lchild,s_calls,s_time); - out_item (outf, &modules[s_table[root].pos],&calls,&local_time); - DBUG_PRINT ("out_body", ("-- %lu -- %lu --", calls, local_time)); - *s_calls += calls; - *s_time += local_time; - root = s_table[root].rchild; - } - DBUG_PRINT ("out_body", ("%lu,%lu", *s_calls, *s_time)); - } - DBUG_VOID_RETURN; -} - -/* - * output () - print out a nice sorted output report on outf. - */ - -void output (outf) -FILE *outf; -{ - unsigned long int sum_calls = 0; - unsigned long int sum_time = 0; - - DBUG_ENTER ("output"); - if (n_items == 0) { - fprintf (outf, "%s: No functions to trace\n", my_name); - exit (EX_DATAERR); - } - out_header (outf); - out_body (outf, 0,&sum_calls,&sum_time); - out_trailer (outf, sum_calls,sum_time); - DBUG_VOID_RETURN; -} - - -#define usage() fprintf (DBUG_FILE,"Usage: %s [-v] [prof-file]\n",my_name) - -#ifdef MSDOS -extern int getopt(int argc, char **argv, char *opts); -#endif -extern int optind; -extern char *optarg; - -int main (int argc, char **argv) -{ - register int c; - int badflg = 0; - FILE *infile; - FILE *outfile = {stdout}; - -#ifdef THREAD -#if defined(HAVE_PTHREAD_INIT) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif - my_thread_global_init(); -#endif /* THREAD */ - { - DBUG_ENTER ("main"); - DBUG_PROCESS (argv[0]); - my_name = argv[0]; - while ((c = getopt (argc,argv,"#:v")) != EOF) { - switch (c) { - case '#': /* Debugging Macro enable */ - DBUG_PUSH (optarg); - break; - case 'v': /* Verbose mode */ - verbose++; - break; - default: - badflg++; - break; - } - } - if (badflg) { - usage (); - DBUG_RETURN (EX_USAGE); - } - if (optind < argc) { - FILEOPEN (infile, argv[optind], "r"); - } else { - FILEOPEN (infile, PRO_FILE, "r"); - } - process (infile); - output (outfile); - DBUG_RETURN (EX_OK); -} -} - -#ifdef MSDOS - -/* - * From std-unix@ut-sally.UUCP (Moderator, John Quarterman) Sun Nov 3 14:34:15 1985 - * Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site gatech.CSNET - * Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP - * Path: gatech!akgua!mhuxv!mhuxt!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!ut-sally!std-unix - * From: std-unix@ut-sally.UUCP (Moderator, John Quarterman) - * Newsgroups: mod.std.unix - * Subject: public domain AT&T getopt source - * Message-ID: <3352@ut-sally.UUCP> - * Date: 3 Nov 85 19:34:15 GMT - * Date-Received: 4 Nov 85 12:25:09 GMT - * Organization: IEEE/P1003 Portable Operating System Environment Committee - * Lines: 91 - * Approved: jsq@ut-sally.UUCP - * - * Here's something you've all been waiting for: the AT&T public domain - * source for getopt(3). It is the code which was given out at the 1985 - * UNIFORUM conference in Dallas. I obtained it by electronic mail - * directly from AT&T. The people there assure me that it is indeed - * in the public domain. - * - * There is no manual page. That is because the one they gave out at - * UNIFORUM was slightly different from the current System V Release 2 - * manual page. The difference apparently involved a note about the - * famous rules 5 and 6, recommending using white space between an option - * and its first argument, and not grouping options that have arguments. - * Getopt itself is currently lenient about both of these things White - * space is allowed, but not mandatory, and the last option in a group can - * have an argument. That particular version of the man page evidently - * has no official existence, and my source at AT&T did not send a copy. - * The current SVR2 man page reflects the actual behavor of this getopt. - * However, I am not about to post a copy of anything licensed by AT&T. - * - * I will submit this source to Berkeley as a bug fix. - * - * I, personally, make no claims or guarantees of any kind about the - * following source. I did compile it to get some confidence that - * it arrived whole, but beyond that you're on your own. - * - */ - -/*LINTLIBRARY*/ - -int opterr = 1; -int optind = 1; -int optopt; -char *optarg; - -static void _ERR(s,c,argv) -char *s; -int c; -char *argv[]; -{ - char errbuf[3]; - - if (opterr) { - errbuf[0] = c; - errbuf[1] = '\n'; - (void) fprintf(stderr, "%s", argv[0]); - (void) fprintf(stderr, "%s", s); - (void) fprintf(stderr, "%s", errbuf); - } -} - -int getopt(argc, argv, opts) -int argc; -char **argv, *opts; -{ - static int sp = 1; - register int c; - register char *cp; - - if(sp == 1) - if(optind >= argc || - argv[optind][0] != '-' || argv[optind][1] == '\0') - return(EOF); - else if(strcmp(argv[optind], "--") == 0) { - optind++; - return(EOF); - } - optopt = c = argv[optind][sp]; - if(c == ':' || (cp=strchr(opts, c)) == NULL) { - _ERR(": illegal option -- ", c, argv); - if(argv[optind][++sp] == '\0') { - optind++; - sp = 1; - } - return('?'); - } - if(*++cp == ':') { - if(argv[optind][sp+1] != '\0') - optarg = &argv[optind++][sp+1]; - else if(++optind >= argc) { - _ERR(": option requires an argument -- ", c, argv); - sp = 1; - return('?'); - } else - optarg = argv[optind++]; - sp = 1; - } else { - if(argv[optind][++sp] == '\0') { - sp = 1; - optind++; - } - optarg = NULL; - } - return(c); -} - -#endif /* !unix && !xenix */ diff --git a/dbug/dbug_long.h b/dbug/dbug_long.h index 829df181ef1..e77218b29b7 100644 --- a/dbug/dbug_long.h +++ b/dbug/dbug_long.h @@ -116,16 +116,10 @@ # define DBUG_VOID_RETURN return # define DBUG_EXECUTE(keyword,a1) # define DBUG_PRINT(keyword,arglist) -# define DBUG_2(keyword,format) /* Obsolete */ -# define DBUG_3(keyword,format,a1) /* Obsolete */ -# define DBUG_4(keyword,format,a1,a2) /* Obsolete */ -# define DBUG_5(keyword,format,a1,a2,a3) /* Obsolete */ # define DBUG_PUSH(a1) # define DBUG_POP() # define DBUG_PROCESS(a1) # define DBUG_FILE (stderr) -# define DBUG_SETJMP setjmp -# define DBUG_LONGJMP longjmp # define DBUG_DUMP(keyword,a1) # else # define DBUG_ENTER(a) \ @@ -142,19 +136,9 @@ {if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}} # define DBUG_PRINT(keyword,arglist) \ {if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}} -# define DBUG_2(keyword,format) \ - DBUG_PRINT(keyword,(format)) /* Obsolete */ -# define DBUG_3(keyword,format,a1) \ - DBUG_PRINT(keyword,(format,a1)) /* Obsolete */ -# define DBUG_4(keyword,format,a1,a2) \ - DBUG_PRINT(keyword,(format,a1,a2)) /* Obsolete */ -# define DBUG_5(keyword,format,a1,a2,a3) \ - DBUG_PRINT(keyword,(format,a1,a2,a3)) /* Obsolete */ # define DBUG_PUSH(a1) _db_push_ (a1) # define DBUG_POP() _db_pop_ () # define DBUG_PROCESS(a1) (_db_process_ = a1) # define DBUG_FILE (_db_fp_) -# define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1)) -# define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2)) # define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2) # endif diff --git a/dbug/my_main.c b/dbug/my_main.c index 31c15aa67aa..2b3e92b53cc 100644 --- a/dbug/my_main.c +++ b/dbug/my_main.c @@ -3,11 +3,8 @@ fixed so that it could compile and run in MySQL source tree */ -#ifdef DBUG_OFF /* We are testing dbug */ -#undef DBUG_OFF -#endif - #include <my_global.h> /* This includes dbug.h */ +#include <my_sys.h> #include <my_pthread.h> int main (argc, argv) @@ -16,12 +13,8 @@ char *argv[]; { register int result, ix; extern int factorial(int); -#if defined(HAVE_PTHREAD_INIT) && defined(THREAD) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif -#ifdef THREAD - my_thread_global_init(); -#endif + MY_INIT(argv[0]); + { DBUG_ENTER ("main"); DBUG_PROCESS (argv[0]); @@ -37,6 +30,8 @@ char *argv[]; result = factorial (atoi(argv[ix])); printf ("%d\n", result); } - DBUG_RETURN (0); + DBUG_LEAVE; } + my_end(0); + exit(0); } diff --git a/dbug/sanity.c b/dbug/sanity.c deleted file mode 100644 index df43fc14ba9..00000000000 --- a/dbug/sanity.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Declarate _sanity() if not declared in main program */ - -#include <my_global.h> - -extern int _sanity(const char *file,uint line); - -#if defined(SAFEMALLOC) && !defined(MASTER) /* Avoid errors in MySQL */ -int _sanity(const char * file __attribute__((unused)), - uint line __attribute__((unused))) -{ - return 0; -} -#endif diff --git a/dbug/tests-t.pl b/dbug/tests-t.pl index de9ed6f6ab9..4803627eda2 100755 --- a/dbug/tests-t.pl +++ b/dbug/tests-t.pl @@ -8,8 +8,9 @@ use Test::More; $exe=$0; +$exe =~ s@[^/]+$@tests@; -die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /; +die unless -x $exe; # load tests @tests=(); @@ -28,7 +29,7 @@ plan skip_all => "because dbug is disabled" if system $exe; plan tests => scalar(@tests); for (@tests) { - $t=$exe . shift @$_; + $t=$exe . ' ' . shift @$_; chomp($t); open F, '-|', $t or die "open($t|): $!"; local $"; @@ -200,7 +201,7 @@ func2: info: s=ko | | <func3 <main % ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P -dbug: >main +dbug-tests: >main dbug-tests: | >func1 dbug-tests: | | | >func3 dbug-tests: | | | <func3 @@ -215,7 +216,7 @@ dbug-tests: | | >func3 dbug-tests: | | <func3 dbug-tests: <main % ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P:F -dbug: tests.c: >main +dbug-tests: tests.c: >main dbug-tests: tests.c: | >func1 dbug-tests: tests.c: | | | >func3 dbug-tests: tests.c: | | | <func3 diff --git a/dbug/tests.c b/dbug/tests.c index d76266d34a3..5950c5fa583 100644 --- a/dbug/tests.c +++ b/dbug/tests.c @@ -5,6 +5,7 @@ char *push1=0; #include <my_global.h> /* This includes dbug.h */ +#include <my_sys.h> #include <my_pthread.h> #include <string.h> @@ -16,7 +17,7 @@ const char *func3() void func2() { - const char *s; + const char *s __attribute__((unused)); DBUG_ENTER("func2"); s=func3(); DBUG_PRINT("info", ("s=%s", s)); @@ -44,12 +45,8 @@ int main (int argc, char *argv[]) if (argc == 1) return 0; -#if defined(HAVE_PTHREAD_INIT) && defined(THREAD) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif -#ifdef THREAD - my_thread_global_init(); -#endif + MY_INIT("dbug-tests"); + dup2(1, 2); for (i = 1; i < argc; i++) { @@ -60,7 +57,6 @@ int main (int argc, char *argv[]) } { DBUG_ENTER ("main"); - DBUG_PROCESS ("dbug-tests"); func1(); DBUG_EXECUTE_IF("dump", { @@ -82,6 +78,9 @@ int main (int argc, char *argv[]) DBUG_PRINT("explain", ("dbug explained: %s", s)); } func2(); - DBUG_RETURN (0); + DBUG_LEAVE; } + DBUG_SET(""); /* to not have my_end() in the traces */ + my_end(0); + return 0; } diff --git a/dbug/user.r b/dbug/user.r index 847ad80b30f..8d8a9ce6910 100644 --- a/dbug/user.r +++ b/dbug/user.r @@ -823,28 +823,6 @@ number of bytes to dump. .SP 1 EX: \fCDBUG_DBUG\ ("net",\ packet,\ len);\fR .SP 1 -.LI DBUG_SETJMP\ -Used in place of the setjmp() function to first save the current -debugger state and then execute the standard setjmp call. -This allows to the debugger to restore its state when the -DBUG_LONGJMP macro is used to invoke the standard longjmp() call. -Currently all instances of DBUG_SETJMP must occur within the -same function and at the same function nesting level. -.SP 1 -EX: \fCDBUG_SETJMP\ (env);\fR -.SP 1 -.LI DBUG_LONGJMP\ -Used in place of the longjmp() function to first restore the -previous debugger state at the time of the last DBUG_SETJMP -and then execute the standard longjmp() call. -Note that currently all DBUG_LONGJMP macros restore the state -at the time of the last DBUG_SETJMP. -It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP -pairs by having the debugger runtime support module use the first -argument to differentiate the pairs. -.SP 1 -EX: \fCDBUG_LONGJMP\ (env,val);\fR -.SP 1 .LI DBUG_LOCK_FILE\ Used in multi-threaded environment to lock DBUG_FILE stream. It can be used, for example, in functions that need to write something to a @@ -971,15 +949,6 @@ containing the macro causing the output. .LI i Mark each debugger output line with the PID (or thread ID) of the current process. -.LI g,[functions] -Enable profiling for the specified list of functions. -Every function can be a -.I glob(7) -pattern. -An empty list of functions enables profiling for all functions. -See -.B PROFILING\ WITH\ DBUG -below. .LI L Mark each debugger output line with the source file line number of the macro causing the output. @@ -1022,7 +991,7 @@ debugger state. .LI S When compiled with .I safemalloc -this flag forces "sanity" memory checks (for overwrites/underwrites) +this flag invokes "sanity" memory checks (for overwrites/underwrites) on each .B DBUG_ENTER and @@ -1086,76 +1055,7 @@ all writes to a file are always followed by a flush. .SK .B -PROFILING WITH DBUG -.R -.P -With -.I dbug -one can do profiling in a machine independent fashion, -without a need for profiled version of system libraries. -For this, -.I dbug -can write out a file -called -.B dbugmon.out -(by default). This is an ascii file containing lines of the form: -.DS CB N -\fC<function-name> E <time-entered> -<function-name> X <time-exited> -.DE - -.P -A second program (\fBanalyze\fR) reads this file, and produces a report on -standard output. - -.P -Profiling is enabled through the -.B g -flag. It can take a list of -function names for which profiling is enabled. By default, it -profiles all functions. - -.P -The profile file is opened for appending. This -is in order that one can run a program several times, and get the -sum total of all the times, etc. - -.P -An example of the report generated follows: -.DS CB N -\fC - Profile of Execution - Execution times are in milliseconds - - Calls Time - ----- ---- - Times Percentage Time Spent Percentage -Function Called of total in Function of total Importance -======== ====== ========== =========== ========== ========== -factorial 5 83.33 30 100.00 8333 -main 1 16.67 0 0.00 0 -======== ====== ========== =========== ========== -Totals 6 100.00 30 100.00 -.DE -.P -As you can see, it's quite self-evident. The -.B Importance -column is a -metric obtained by multiplying the percentage of the calls and the percentage -of the time. Functions with higher 'importance' benefit the most from -being sped up. - -.P -As a limitation - setjmp/longjmp, or child processes, are ignored -for the time being. Also, profiling does not work -in a multi-threaded environment. - -.P -Profiling code is (c) Binayak Banerjee. - -.SK -.B HINTS AND MISCELLANEOUS .R |