/* * backtrace.c * Function backtracing code (original code by Balloon) * --------------------------------------------------------------------------- */ #include <stdio.h> #include <ctype.h> #include <time.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <memory.h> #include <unistd.h> #include <sys/stat.h> #include <stdarg.h> #include "include/config.h" #include "include/player.h" #include "include/proto.h" #define MAX_DEBUG_LEN 50 #define MAX_DEPTH 250 #define MAX_MARK_LEN 250 struct FunctionTrack { char File[MAX_DEBUG_LEN]; int Line; char Function[MAX_DEBUG_LEN]; char MarkMessage[MAX_MARK_LEN]; int MarkLine; }; static int TrackingDepth = -1; static int ActualDepth = -1; static struct FunctionTrack Tracks[MAX_DEPTH]; void EnterFunction(int Line, char *File, char *Function) { if (sys_flags & DONT_TRACE) return; sys_flags |= DONT_TRACE; if (TrackingDepth == -1) memset(Tracks, 0, MAX_DEPTH * sizeof(struct FunctionTrack)); if (TrackingDepth == MAX_DEPTH) { if (TrackingDepth == ActualDepth++) LOGF("error", "Gone deeper than tracking allows!"); sys_flags &= ~DONT_TRACE; return; } TrackingDepth++; ActualDepth++; strncpy(Tracks[TrackingDepth].File, File, MAX_DEBUG_LEN); strncpy(Tracks[TrackingDepth].Function, Function, MAX_DEBUG_LEN); Tracks[TrackingDepth].Line = Line; Tracks[TrackingDepth].MarkMessage[0] = 0; sys_flags &= ~DONT_TRACE; } void ExitFunction(int Line, char *File, char *Function) { int temp; if (sys_flags & DONT_TRACE) return; sys_flags |= DONT_TRACE; if (ActualDepth > TrackingDepth) { if ((ActualDepth - 1) == TrackingDepth) LOGF("error", "Leaving function (too deep)"); ActualDepth--; sys_flags &= ~DONT_TRACE; return; } if (TrackingDepth < 0) { LOGF("error", "Leaving : %s : %s : Line %d", File, Function, Line); LOGF("error", "Tracking claims not to be in any function!"); sys_flags &= ~DONT_TRACE; return; } if ((strncmp(File, Tracks[TrackingDepth].File, MAX_DEBUG_LEN)) || (strncmp(Function, Tracks[TrackingDepth].Function, MAX_DEBUG_LEN))) { LOGF("error", "Leaving : %s : %s : Line %d", File, Function, Line); LOGF("error", "Not left : %s : %s : Line %d", Tracks[TrackingDepth].Function, Tracks[TrackingDepth].File, Tracks[TrackingDepth].Line); temp = TrackingDepth; while ((temp > -1) && ((strncmp(File, Tracks[temp].File, MAX_DEBUG_LEN)) || (strncmp(Function, Tracks[temp].Function, MAX_DEBUG_LEN)))) temp--; if (temp > -1) { LOGF("error","Hopefully recovered tracking."); TrackingDepth = temp - 1; ActualDepth = TrackingDepth; } else LOGF("error","Not recovered as yet."); } Tracks[TrackingDepth].File[0] = 0; Tracks[TrackingDepth].Function[0] = 0; Tracks[TrackingDepth].Line = 0; Tracks[TrackingDepth].MarkMessage[0] = 0; TrackingDepth--; ActualDepth--; sys_flags &= ~DONT_TRACE; } void MarkFunction(int Line, char *File, char *Function, char *Format, ...) { int temp; va_list ap; if (sys_flags & DONT_TRACE) return; sys_flags |= DONT_TRACE; if (ActualDepth > TrackingDepth) { LOGF("error", "Marking : %s : %s : Line %d", File, Function, Line); LOGF("error", "Too deep to Mark function."); sys_flags &= ~DONT_TRACE; return; } if (TrackingDepth < 0) { LOGF("error", "Marking : %s : %s : Line %d", File, Function, Line); LOGF("error", "Tracking claims not to be in any function!"); sys_flags &= ~DONT_TRACE; return; } temp = TrackingDepth; if ((strncmp(File, Tracks[TrackingDepth].File, MAX_DEBUG_LEN)) || (strncmp(Function, Tracks[TrackingDepth].Function, MAX_DEBUG_LEN))) { LOGF("error", "Marking : %s : %s : Line %d", File, Function, Line); LOGF("error", "Actually in : %s : %s : Line %d", Tracks[TrackingDepth].Function, Tracks[TrackingDepth].File, Tracks[TrackingDepth].Line); while ((temp > -1) && ((strncmp(File, Tracks[temp].File, MAX_DEBUG_LEN)) || (strncmp(Function, Tracks[temp].Function, MAX_DEBUG_LEN)))) temp--; if (temp > -1) LOGF("error","Hopefully found correct function to mark."); else LOGF("error","Cant find correct function to mark."); } if (temp > -1) { /* It's safe to do the mark. */ va_start(ap, Format); vsnprintf(Tracks[temp].MarkMessage, MAX_MARK_LEN, Format, ap); va_end(ap); Tracks[temp].MarkMessage[MAX_MARK_LEN - 1] = 0; Tracks[temp].MarkLine = Line; } sys_flags &= ~DONT_TRACE; } void DumpTraceInfo(char *logfile) { int temp; if (sys_flags & DONT_TRACE) return; sys_flags |= DONT_TRACE; LOGF(logfile, "==== Showing last function calls"); for (temp = 0; temp <= TrackingDepth; temp++) { LOGF(logfile, " %s : %s : Line %d", Tracks[temp].Function, Tracks[temp].File, Tracks[temp].Line); if (Tracks[temp].MarkMessage[0]) LOGF(logfile, " -- %s : Line %d", Tracks[temp].MarkMessage, Tracks[temp].MarkLine); } LOGF(logfile, "==== End of function calls"); sys_flags &= ~DONT_TRACE; }