source: svn/branches/kctv/newcon3bcm2_21bu/magnum/basemodules/dbg/bdbg.c @ 76

Last change on this file since 76 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 47.2 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2011, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bdbg.c $
11 * $brcm_Revision: Hydra_Software_Devel/67 $
12 * $brcm_Date: 10/5/11 12:58p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/basemodules/dbg/bdbg.c $
19 *
20 * Hydra_Software_Devel/67   10/5/11 12:58p vsilyaev
21 * SW7405-4477: Fixed typo
22 *
23 * Hydra_Software_Devel/66   6/20/11 11:06a vsilyaev
24 * SW7405-5221: Fixed Enter/Leave function
25 *
26 * Hydra_Software_Devel/65   6/16/11 1:40p vsilyaev
27 * SW7425-729,SW7400-3012: Added LOG level
28 *
29 * Hydra_Software_Devel/64   6/6/11 3:27p vsilyaev
30 * SW7405-4477: Routed all debug output through buffer and use external
31 * application to extract and print debug output
32 *
33 * Hydra_Software_Devel/63   4/13/11 7:00p vsilyaev
34 * SW7405-5221: Route BERR_TRACE through the debug log
35 *
36 * Hydra_Software_Devel/62   4/5/11 11:35a vsilyaev
37 * SW7405-5221: Fixed typo
38 *
39 * Hydra_Software_Devel/61   4/4/11 6:14p vsilyaev
40 * SW7405-5221: Added option to forward debug output to FIFO
41 *
42 * Hydra_Software_Devel/60   1/5/11 6:31p vsilyaev
43 * SW7405-4477: Backed up code that acquires lock for duration of
44 * BKNI_Printf
45 *
46 * Hydra_Software_Devel/59   11/3/10 10:00a erickson
47 * SW7405-4477: add lock/unlock to BDBG_P_TestAndPrint so that task/isr
48 * DBG output is not interleaved
49 *
50 * Hydra_Software_Devel/58   10/11/10 5:23p jgarrett
51 * SW7125-630: Merge to main branch
52 *
53 * Hydra_Software_Devel/SW7125-630/2   10/11/10 1:46p mward
54 * SW7125-630:  Merge from main.
55 *
56 * Hydra_Software_Devel/57   8/3/10 11:41a erickson
57 * SW7400-2857: reduce stack usage by BDBG_OBJECT_ASSERT
58 *
59 * Hydra_Software_Devel/SW7125-630/1   10/1/10 5:47p jgarrett
60 * SW7125-630: Removing potential malloc with BDBG_Lock held
61 *
62 * Hydra_Software_Devel/56   7/13/10 12:59p vsilyaev
63 * SW7420-867, SW7408-106: Properly register new modules in
64 * BDBG_P_GetModuleByName
65 *
66 * Hydra_Software_Devel/55   6/30/10 10:40a vsilyaev
67 * SW7420-867: Don't allocate memory while holding DBG_Lock
68 *
69 * Hydra_Software_Devel/54   6/25/10 6:26p jgarrett
70 * SW7408-88: Removing implicit global from BDBG_OBJECT_DESTROY
71 *
72 * Hydra_Software_Devel/53   10/14/09 6:52p vsilyaev
73 * SW7405-3211: Use constant pointers in  BDBG_Object_Assert
74 *
75 * Hydra_Software_Devel/52   9/22/09 5:08p erickson
76 * SW3548-2493: allow compile-time and run-time debug levels to change
77 * free from each other.
78 *
79 * Hydra_Software_Devel/51   7/21/09 12:36p nilesh
80 * PR56629: Resolve variable namespace conflict with local scope variables
81 * defined in BLST macros
82 *
83 * Hydra_Software_Devel/50   7/15/09 10:58a nilesh
84 * PR56629: Fixed memory leak introduced when reusing debug instance
85 *
86 * Hydra_Software_Devel/49   7/13/09 11:31a nilesh
87 * PR56629: Reuse unregistered debug instances to prevent memory leak
88 *
89 * Hydra_Software_Devel/48   7/1/09 4:55p vsilyaev
90 * PR 53778: Always define bdbg_id__bdbg_invalid
91 *
92 * Hydra_Software_Devel/47   6/24/09 2:26p mphillip
93 * PR54926: Merge DBG extension to /main
94 *
95 * Hydra_Software_Devel/PR54926/1   5/18/09 6:57p vsilyaev
96 * PR 54926: Added interface to capture debug output
97 *
98 * Hydra_Software_Devel/46   4/10/09 2:51p katrep
99 * PR53778: Compiler warning
100 *
101 * Hydra_Software_Devel/45   4/10/09 11:33a vsilyaev
102 * PR 53778: Protect dereference symbols only defined in the debug build
103 *
104 * Hydra_Software_Devel/44   4/9/09 1:35p vsilyaev
105 * PR 53778: Keep a history of free'ed objects for better debug facilities
106 *
107 * Hydra_Software_Devel/43   4/2/09 11:30a erickson
108 * PR53778: integrate BKNI_TRACK_MALLOCS with BDBG_OBJECT_ASSERT for more
109 * debug information
110 *
111 * Hydra_Software_Devel/42   2/19/09 6:45p vsilyaev
112 * PR 52320: Added BDBG_RELEASE macro to unwind module from BDBG
113 *
114 * Hydra_Software_Devel/41   2/12/09 5:17p vsilyaev
115 * PR 51891: Removed possible memory allocation in
116 * BDBG_P_InstTestAndPrint
117 *
118 * Hydra_Software_Devel/40   2/3/09 12:42p shyam
119 * PR51819 : Add timestamp prints to BDBG_ENTER and LEAVE functions
120 *
121 * Hydra_Software_Devel/39   1/26/09 10:33a erickson
122 * PR51415: rework bdbg_os_priv interface to not suggest BKNI_EventHandle
123 * usage in BDBG_P_Lock, which must lock in both task and isr contexts
124 *
125 * Hydra_Software_Devel/38   1/23/09 2:47p vsilyaev
126 * PR 50746: Fixed warnings for 64-bit build
127 *
128 * Hydra_Software_Devel/37   12/29/08 1:32p erickson
129 * PR50746: make BDBG_OBJECT_ASSERT failures more helpful
130 *
131 * Hydra_Software_Devel/36   8/6/08 10:02a erickson
132 * PR45459: fix release build
133 *
134 * Hydra_Software_Devel/35   7/22/08 4:46p nilesh
135 * PR44846: In BDBG_P_InstTestAndPrint(), use the dbg_module name to
136 * lookup the internal module instead of using dbg_module directly
137 *
138 * Hydra_Software_Devel/34   7/22/08 2:03p nilesh
139 * PR44846: Instance name is now checked if not null before comparison
140 *
141 * Hydra_Software_Devel/33   7/22/08 12:30p nilesh
142 * PR44846: Added support for setting instance levels on a per module
143 * basis
144 *
145 * Hydra_Software_Devel/32   11/1/07 2:14p vsilyaev
146 * PR 36199: Fixed gate for instance level debug output
147 *
148 * Hydra_Software_Devel/31   10/22/07 2:57p vsilyaev
149 * PR 36199: Fixed handling of instances and accounting of module debug
150 * level
151 *
152 * Hydra_Software_Devel/30   10/11/07 1:28p vishk
153 * PR 35967: Coverity Defect ID:3955 CHECKED_RETURN
154 *
155 * Hydra_Software_Devel/29   8/15/07 2:25p vsilyaev
156 * PR 34089: Optimized executuion speed and code size
157 *
158 * Hydra_Software_Devel/28   5/10/07 11:57a vsilyaev
159 * PR 25469: Fixed error for release build
160 *
161 * Hydra_Software_Devel/27   5/4/07 12:14p vsilyaev
162 * PR 25469: Added function BDBG_EnumerateAll
163 *
164 * Hydra_Software_Devel/26   1/30/07 11:03a vsilyaev
165 * PR 27425: Proofread documentation and expaned BDBG_OBJECT portion
166 *
167 * Hydra_Software_Devel/25   9/7/06 5:06p vsilyaev
168 * PR 24154: Added simple wildcard support
169 *
170 * Hydra_Software_Devel/24   7/21/06 11:28a vsilyaev
171 * PR 22695: Changes in the BDBG module to make it run-time compatible
172 * between debug and release builds
173 *
174 * Hydra_Software_Devel/23   5/31/06 5:11p vsilyaev
175 * PR 21756: Make a copy of the module name if new module descriptor is
176 * allocated from the heap
177 *
178 * Hydra_Software_Devel/22   4/27/06 10:07a vle
179 * PR 21065: rework BDBG_LOCK and BDBG_UNLOCK to be OS specific
180 * implementation.
181 *
182 * Hydra_Software_Devel/21   2/28/06 10:50a vsilyaev
183 * PR 19917: Fixed typo
184 *
185 * Hydra_Software_Devel/20   2/27/06 5:12p vsilyaev
186 * PR 19917: Added API to check object types at runtime
187 *
188 * Hydra_Software_Devel/19   11/29/05 3:15p vle
189 * PR18319: add timestamp to debug messages
190 *
191 * Hydra_Software_Devel/18   11/21/05 3:08p vsilyaev
192 * PR 18217: Fixed handling of instance level debug messages
193 *
194 * Hydra_Software_Devel/17   6/28/05 9:03a erickson
195 * PR16033: verify that BDBG_Init is calld
196 *
197 * Hydra_Software_Devel/16   11/13/03 1:53p vsilyaev
198 * Added Trace level to use by BDBG_ENTER and BDBG_LEAVE.
199 *
200 * Hydra_Software_Devel/15   11/13/03 9:33a vsilyaev
201 * Tag malloced and statically allocated memory, so only malloced will be
202 * free'ed at UnInit time.
203 *
204 * Hydra_Software_Devel/14   11/12/03 2:23p vsilyaev
205 * Use statically alllocated data for internal structures, it solves
206 * dilemma of malloc and interrupt.
207 *
208 * Hydra_Software_Devel/14   11/12/03 2:14p vsilyaev
209 * Use statically alllocated data for internal structures, it solves
210 * dilemma of malloc and interrupt.
211 *
212 * Hydra_Software_Devel/13   10/2/03 4:00p erickson
213 * removed warning and added explicit typecasts for malloc
214 *
215 * Hydra_Software_Devel/12   9/5/03 11:13a jasonh
216 * Wrapped BSTD_UNUSED around unused arguments.
217 *
218 * Hydra_Software_Devel/11   4/8/03 6:04p vsilyaev
219 * Removed timeout from the BDBG_AcquireMutex.
220 *
221 * Hydra_Software_Devel/10   4/1/03 7:32p vsilyaev
222 * Fixed false trigraph '???' case.
223 *
224 * Hydra_Software_Devel/9   3/28/03 5:57p vsilyaev
225 * Fixed format string for unknown instance.
226 *
227 * Hydra_Software_Devel/8   3/25/03 8:24p vsilyaev
228 * Fixed potentional race conditions in the BDGB_GetModule function.
229 *
230 * Hydra_Software_Devel/7   3/20/03 1:02p erickson
231 * removed unused local variables
232 *
233 * Hydra_Software_Devel/6   3/14/03 7:52p vsilyaev
234 * Updated to work with new list implementation.
235 *
236 * Hydra_Software_Devel/5   3/12/03 4:39p vsilyaev
237 * Integrated with new header file.
238 *
239 * Hydra_Software_Devel/4   3/11/03 9:54p vsilyaev
240 * Update for the new kernel interface.
241 *
242 * Hydra_Software_Devel/3   3/10/03 6:36p vsilyaev
243 * Fixed BDBG_P_PrintError.
244 *
245 * Hydra_Software_Devel/2   3/10/03 10:43a vsilyaev
246 * Integration with berr.h
247 *
248 * Hydra_Software_Devel/1   3/10/03 10:03a vsilyaev
249 * O/S inspecific part of the debug interface.
250 *
251 ***************************************************************************/
252
253#include "bstd.h"
254#include "bkni.h"
255#include "bdbg_os_priv.h"
256#include "bdbg_log.h"
257#include "blst_slist.h"
258#include "bdbg_priv.h"
259
260/* max number of instances per module */
261#define MAX_MODULE_INSTANCES   32
262#define BDBG_P_MAX_MODULE_NAME_LENGTH   64
263
264#undef BDBG_SetLevel
265#undef BDBG_GetLevel
266#undef BDBG_SetModuleLevel
267#undef BDBG_GetModuleLevel
268#undef BDBG_SetInstanceLevel
269#undef BDBG_GetInstanceLevel
270#undef BDBG_SetInstanceName
271#undef BDBG_EnumerateAll
272#undef BDBG_GetModuleInstanceLevel
273#undef BDBG_SetModuleInstanceLevel
274
275struct BDBG_DebugInstModule {
276      BLST_S_ENTRY(BDBG_DebugInstModule) link;
277
278      BDBG_pDebugModuleFile pModule; /* pointer to module */
279      BDBG_Level eLevel;
280};
281
282struct BDBG_DebugModuleInst {
283      BLST_S_ENTRY(BDBG_DebugModuleInst) link;
284      BDBG_Instance handle;
285      BDBG_Level level;
286      const char *name;
287      BDBG_pDebugModuleFile module; /* pointer to module */
288
289      BLST_S_HEAD(BDBG_DebugInstModuleHead, BDBG_DebugInstModule) modules;
290};
291
292typedef struct BDBG_P_LogEntry {
293    unsigned long tag; /* tag is value of stack pointer and LSB  used to indicate header or body */
294    int16_t rc; /* result from printf */
295    char str[256-sizeof(uint32_t)-sizeof(void *)-sizeof(int16_t)];
296} BDBG_P_LogEntry;
297
298
299static struct {
300    BLST_S_HEAD(BDBG_DebugModuleHead, BDBG_DebugModuleFile) modules;  /* sorted list of modules */
301    BLST_S_HEAD(BDBG_DebugInstHead, BDBG_DebugModuleInst) instances;  /* sorted list of instances */
302    BLST_S_HEAD(BDBG_DebugUnregInstHead, BDBG_DebugModuleInst) unregistered_instances;  /* list of unregistered instances */
303    BDBG_Level level;
304    BDBG_Fifo_Handle dbgLog;
305} gDbgState = {
306   BLST_S_INITIALIZER(BDBG_DebugModuleFile),
307   BLST_S_INITIALIZER(BDBG_DebugModuleInst),
308   BLST_S_INITIALIZER(BDBG_DebugModuleInst),
309   BDBG_eWrn, /* default level is a warning level */
310   NULL
311};
312
313static const char gDbgPrefix[][4] =
314{
315   "",
316   "...",
317   "---",
318   "***",
319   "###",
320   "   "
321};
322
323
324static struct BDBG_DebugModuleInst * BDBG_P_GetInstance(BDBG_Instance handle);
325static const char *BDBG_P_GetPrefix(BDBG_Level level);
326static BERR_Code BDBG_P_RegisterModuleFile(BDBG_pDebugModuleFile dbg_module);
327static bool BDBG_P_TestModule(BDBG_pDebugModuleFile dbg_module, BDBG_Level level);
328static BDBG_pDebugModuleFile BDBG_P_GetModuleByName(const char *name);
329static BDBG_pDebugModuleFile BDBG_P_GetModuleByName_sync(const char *name, BDBG_pDebugModuleFile module /* optional placeholder */ );
330static int BDBG_P_StrCmp(const char *str1, const char *str2);
331static BERR_Code BDBG_P_CheckDebugLevel(BDBG_Level level);
332
333static struct BDBG_DebugInstModule * BDBG_P_GetInstanceModule(struct BDBG_DebugModuleInst *pInstance, BDBG_pDebugModuleFile pModule);
334static struct BDBG_DebugInstModule * BDBG_P_GetInstanceModule_sync(struct BDBG_DebugModuleInst *pInstance, BDBG_pDebugModuleFile pModule);
335static BERR_Code BDBG_P_SetInstanceModuleLevel(struct BDBG_DebugModuleInst *pInstance, BDBG_pDebugModuleFile pModule, BDBG_Level eLevel);
336static struct BDBG_DebugModuleInst * BDBG_P_GetInstanceByName(const char *name);
337static struct BDBG_DebugModuleInst * BDBG_P_GetInstanceByName_sync(const char *name);
338static void BDBG_P_Dequeue_FreeMemory(void);
339
340static const char *
341BDBG_P_GetPrefix(BDBG_Level level)
342{
343   BDBG_CASSERT(sizeof(gDbgPrefix)/sizeof(*gDbgPrefix) == BDBG_P_eLastEntry);
344   if (level<BDBG_P_eLastEntry) {
345      return gDbgPrefix[level];
346   } else {
347      return gDbgPrefix[0];
348   }
349}
350
351static int
352BDBG_P_StrCmp(const char *str1, const char *str2)
353{
354   int ch1, ch2, diff;
355
356   for(;;) {
357      ch1 = *str1++;
358      ch2 = *str2++;
359      if (ch1=='*' || ch2=='*') {
360         return 0;
361      }
362      diff = ch1 - ch2;
363      if (diff) {
364         return diff;
365      } else if (ch1=='\0') {
366         return 0;
367      }
368   }
369}
370
371char * BDBG_P_StrnCpy(char *dest, const char *src, size_t num)
372{
373   char *p = dest;
374
375   /* Always set the last character to NULL in the destination */
376   num--;
377   dest[num] = '\0';
378
379   while (num-- && (*dest++ = *src++));
380
381   return p;
382}
383
384char * BDBG_P_StrChrNul(const char *str, int c)
385{
386   char *p = (char *) str;
387   while ((*p != '\0') && (*p != c)) p++;
388
389   return p;
390}
391
392static BERR_Code
393BDBG_P_CheckDebugLevel(BDBG_Level level)
394{
395    if(level>=BDBG_P_eLastEntry) {
396        return BERR_TRACE(BERR_INVALID_PARAMETER);
397    }
398    return BERR_SUCCESS;
399}
400
401static BERR_Code
402BDBG_P_RegisterModuleFile(BDBG_pDebugModuleFile dbg_module)
403{
404   BDBG_pDebugModuleFile module;
405   BERR_Code rc = BERR_SUCCESS;
406   BDBG_pDebugModuleFile prev;
407
408   BDBG_P_Lock();
409   /* test if module has been already registered */
410   if (dbg_module->level!=BDBG_P_eUnknown) {
411      goto done; /* module was already registered */
412   }
413
414   module = BDBG_P_GetModuleByName_sync(dbg_module->name, dbg_module);
415   if (!module) {
416      rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
417      goto done;
418   }
419   /* check whether new file exists in the module chain */
420   for(prev=module; module!=NULL && dbg_module!=module ; module = BLST_S_NEXT(module, link)) {
421      if(BDBG_P_StrCmp(dbg_module->name, module->name)!=0) {
422         break;
423      }
424   }
425   if(dbg_module!=module) {
426      /* file not in the chain, add it */
427      /* 1. copy level information */
428      dbg_module->level = prev->level;
429      dbg_module->module_level = prev->module_level;
430      dbg_module->module_print = prev->module_print;
431      /* 2. add into the sorted list */
432      BLST_S_INSERT_AFTER(&gDbgState.modules, prev, dbg_module, link);
433   }
434  done:
435   BDBG_P_Unlock();
436   return rc;
437}
438
439static struct BDBG_DebugModuleInst *
440BDBG_P_GetInstance_sync(BDBG_Instance handle)
441{
442   struct BDBG_DebugModuleInst *instance;
443
444   for(instance = BLST_S_FIRST(&gDbgState.instances); instance ; instance = BLST_S_NEXT(instance, link)) {
445      if ((uint8_t *)instance->handle >= (uint8_t *)handle) {
446         break;
447      }
448   }
449   if(instance && instance->handle!=handle) {
450      instance = NULL;
451   }
452   return instance;
453}
454
455static struct BDBG_DebugModuleInst *
456BDBG_P_GetInstance(BDBG_Instance handle)
457{
458   struct BDBG_DebugModuleInst *instance;
459
460   BDBG_P_Lock();
461   instance = BDBG_P_GetInstance_sync(handle);
462   BDBG_P_Unlock();
463   return instance;
464}
465
466static bool
467BDBG_P_TestModule(BDBG_pDebugModuleFile dbg_module, BDBG_Level level)
468{
469   BERR_Code rc;
470
471   /*
472    * try do a trick don't acquire mutex on first test, and use double test techinques.
473    * Note: this technique would have a race condition on the SMP systems
474    */
475   if (dbg_module->level==BDBG_P_eUnknown) {
476      /* register module file in the system */
477      rc = BDBG_P_RegisterModuleFile(dbg_module);
478      if (rc!=BERR_SUCCESS) {
479         return false;
480      }
481   }
482   return (int)level >= dbg_module->level;
483}
484
485static size_t
486BDBG_P_strlen(const char *str)
487{
488   size_t len;
489   for(len=0;*str++!='\0';len++) { }
490   return len;
491}
492
493/* should be called with mutex already held */
494static BDBG_pDebugModuleFile
495BDBG_P_GetModuleByName_sync(const char *name, BDBG_pDebugModuleFile new_module)
496{
497   BDBG_pDebugModuleFile module, prev;
498   int cmp=-1;
499
500   BDBG_CASSERT(sizeof(char)==1); /* prerequesite for the block allocation */
501
502   /* traverse all known modules */
503   for(prev=NULL, module = BLST_S_FIRST(&gDbgState.modules); module ; module = BLST_S_NEXT(module, link)) {
504      cmp = BDBG_P_StrCmp(name, module->name);
505      if(cmp>=0) {
506         break;
507      }
508      prev = module;
509   }
510   if(cmp==0) { /* exact match */
511      goto done;
512   }
513   /* else insert new module */
514   module = new_module;
515   if(module==NULL) { goto done; }
516   module->module_alloc = false;
517   module->module_print = NULL;
518   module->level = gDbgState.level;
519   module->module_level = gDbgState.level;
520   module->name = name;
521   if(prev) {
522      BLST_S_INSERT_AFTER(&gDbgState.modules, prev, module, link);
523   } else {
524      BLST_S_INSERT_HEAD(&gDbgState.modules, module, link);
525   }
526
527  done:
528   return module;
529}
530
531
532static BDBG_pDebugModuleFile
533BDBG_P_GetModuleByName(const char *name)
534{
535    BDBG_pDebugModuleFile old_module;
536    BDBG_pDebugModuleFile new_module;
537    size_t name_len;
538    char *copy_name;
539
540    /* we can't allocate memory inside BDBG_P_GetModuleByName_sync, so try to find existing module first */
541    BDBG_P_Lock();
542    old_module = BDBG_P_GetModuleByName_sync(name, NULL);
543    BDBG_P_Unlock();
544    if(old_module) {goto done;}
545    /* and if it fails allocate memory, copy string and prepapre to free allocated memory if returned something else */
546
547    name_len=BDBG_P_strlen(name)+1; /* string length plus trailing 0 */
548    /* this code should never executed at the interrupt time */
549    new_module = BKNI_Malloc(sizeof(*new_module)+name_len);
550    if (!new_module) {
551        return NULL;
552    }
553    copy_name = (char *)new_module + sizeof(*new_module);
554    BKNI_Memcpy(copy_name, name, name_len); /* copy name */
555
556    BDBG_P_Lock();
557    old_module = BDBG_P_GetModuleByName_sync(copy_name, new_module);
558    if(old_module==new_module) {
559        new_module->module_alloc = true;
560    }
561    BDBG_P_Unlock();
562
563    if(old_module!=new_module) {
564        BKNI_Free(new_module);
565    }
566done:
567    return old_module;
568}
569
570static struct BDBG_DebugModuleInst *
571BDBG_P_GetInstanceByName_sync(const char *name)
572{
573   struct BDBG_DebugModuleInst *pInstance;
574
575   /* traverse all known instances */
576   for(pInstance = BLST_S_FIRST(&gDbgState.instances); pInstance ; pInstance = BLST_S_NEXT(pInstance, link))
577   {
578      if (pInstance->name)
579      {
580         if (BDBG_P_StrCmp(name, pInstance->name) == 0)
581         {
582            return pInstance;
583         }
584      }
585   }
586
587   return NULL;
588}
589
590static struct BDBG_DebugModuleInst *
591BDBG_P_GetInstanceByName(const char *name)
592{
593   struct BDBG_DebugModuleInst * pInstance;
594
595   BDBG_P_Lock();
596
597   pInstance = BDBG_P_GetInstanceByName_sync(name);
598
599   BDBG_P_Unlock();
600   return pInstance;
601}
602
603#define BDBG_P_Vprintf_module(kind, instance, _level, dbg_module, fmt, ap) do { \
604    BDBG_DebugModule_Print module_print = dbg_module->module_print; \
605    bool normal_print = instance || (module_print==NULL ? ((int)_level >= dbg_module->level) : ((int)_level >= -dbg_module->level)); \
606    if(module_print) { module_print(kind, _level, dbg_module, fmt, ap); } \
607    if(normal_print) { BDBG_P_Vprintf_Log(kind, fmt, ap); } \
608} while(0)
609
610int
611BDBG_P_Vprintf_Log(BDBG_ModulePrintKind kind, const char *fmt, va_list ap)
612{
613    int rc = 0;
614    BDBG_Fifo_Handle dbgLog = gDbgState.dbgLog;
615    if(dbgLog) {
616        BDBG_Fifo_Token token;
617        BDBG_P_LogEntry *log = BDBG_Fifo_GetBuffer(dbgLog, &token);
618        if(log) {
619            log->tag = (unsigned long)&token | kind;
620            rc = BKNI_Vsnprintf(log->str, sizeof(log->str), fmt, ap);
621            log->rc = rc;
622            BDBG_Fifo_CommitBuffer(&token);
623        }
624    } else {
625            rc = BKNI_Vprintf(fmt, ap);
626        if(kind==BDBG_ModulePrintKind_eHeaderAndBody  || kind==BDBG_ModulePrintKind_eBody ) {
627            BKNI_Printf("\n");
628        }
629    }
630    return 0;
631}
632
633static void
634BDBG_P_PrintHeader(bool instance, BDBG_Level level, BDBG_pDebugModuleFile dbg_module, const char *fmt, ...)
635{
636    va_list ap;
637    va_start(ap, fmt);
638    BDBG_P_Vprintf_module(BDBG_ModulePrintKind_eHeader, instance, level, dbg_module, fmt, ap);
639    va_end( ap );
640    return;
641}
642
643
644static void
645BDBG_P_VprintBody(bool instance, BDBG_Level level, BDBG_pDebugModuleFile dbg_module, const char *fmt, va_list ap)
646{
647    BDBG_P_Vprintf_module(BDBG_ModulePrintKind_eBody, instance, level, dbg_module, fmt, ap);
648    return;
649}
650
651static void
652BDBG_P_PrintTrace(BDBG_pDebugModuleFile dbg_module, const char *fmt, ...)
653{
654    va_list ap;
655
656    va_start(ap, fmt);
657    BDBG_P_Vprintf_module(BDBG_ModulePrintKind_eHeaderAndBody, false, BDBG_eTrace, dbg_module, fmt, ap);
658    va_end( ap );
659    return;
660}
661
662
663void /* only used externally if BDBG_P_UNWRAP is undefined */
664BDBG_P_PrintWithNewLine(const char *fmt, ...)
665{
666   va_list ap;
667
668   va_start(ap, fmt);
669   BDBG_P_Vprintf_Log(BDBG_ModulePrintKind_eBody, fmt, ap);
670   va_end( ap );
671   return;
672}
673
674
675bool
676BDBG_P_TestAndPrint(BDBG_Level level, BDBG_pDebugModuleFile dbg_module, const char *fmt, ...)
677{
678   if( BDBG_P_TestModule(dbg_module, level)) {
679      char timeStamp[20];
680     
681      BDBG_P_GetTimeStamp(timeStamp, sizeof(timeStamp));
682      BDBG_P_PrintHeader(false, level, dbg_module, "%s %s %s: ", BDBG_P_GetPrefix(level), timeStamp, dbg_module->name);
683      if(fmt) { /* also print body */
684          va_list ap;
685
686          va_start(ap, fmt);
687          BDBG_P_VprintBody(false, level, dbg_module, fmt, ap);
688          va_end( ap );
689      }
690      return true;
691   }
692   return false;
693}
694
695bool
696BDBG_P_InstTestAndPrint(BDBG_Level level, BDBG_pDebugModuleFile dbg_module, BDBG_Instance handle, const char *fmt, ...)
697{
698   struct BDBG_DebugInstModule *pInstanceModule = NULL;
699   struct BDBG_DebugModuleInst *instance;
700   bool module_result = BDBG_P_TestModule(dbg_module, level);
701   bool instance_result;
702
703   BDBG_P_Lock();
704   instance = BDBG_P_GetInstance_sync(handle);
705
706   if (instance) {
707      BDBG_pDebugModuleFile pModule = BDBG_P_GetModuleByName_sync(dbg_module->name, dbg_module);
708      if(pModule) {
709        pInstanceModule = BDBG_P_GetInstanceModule_sync(instance, pModule);
710      }
711   }
712   BDBG_P_Unlock();
713
714   instance_result = (instance && level >= instance->level) || (pInstanceModule && level >= pInstanceModule->eLevel);
715   if(module_result || instance_result) {
716      char timeStamp[20];
717
718      BDBG_P_GetTimeStamp(timeStamp, sizeof(timeStamp));
719      if(instance && instance->name) {
720         BDBG_P_PrintHeader(instance_result, level, dbg_module, "%s %s %s(%s): ", BDBG_P_GetPrefix(level), timeStamp, dbg_module->name, instance->name);
721      } else {
722         BDBG_P_PrintHeader(instance_result, level, dbg_module, "%s %s %s(%#lx): ", BDBG_P_GetPrefix(level), timeStamp, dbg_module->name, (unsigned long)handle);
723      }
724      if(fmt) { /* also print body */
725          va_list ap;
726
727          va_start(ap, fmt);
728          BDBG_P_VprintBody(instance_result, level, dbg_module, fmt, ap);
729          va_end( ap );
730      }
731      return true;
732   }
733   return false;
734}
735
736static BDBG_pDebugModuleFile
737BDBG_P_GetModule(BDBG_pDebugModuleFile module)
738{
739   /* This return value is not checked intentionally */
740   /* coverity[check_return] */
741   /* coverity[unchecked_value] */
742   BDBG_P_TestModule(module, BDBG_eTrace);
743   return module;
744}
745
746void
747BDBG_P_RegisterInstance(BDBG_Instance handle, BDBG_pDebugModuleFile dbg_module)
748{
749   BDBG_pDebugModuleFile module;
750   struct BDBG_DebugModuleInst *instance = NULL;
751   struct BDBG_DebugModuleInst *previous, *current;
752   struct BDBG_DebugInstModule *pInstanceModule = NULL;
753
754   module = BDBG_P_GetModule(dbg_module);
755   if (!module) {
756      return;
757   }
758
759   /* PR56629: Search for and re-use the previously
760    * unregistered instance to prevent memory leak */
761   BDBG_P_Lock();
762   for(current = BLST_S_FIRST(&gDbgState.unregistered_instances); current ; current = BLST_S_NEXT(current, link))
763   {
764      if ( ( current->module == module )
765           && (current->handle == handle ) )
766      {
767         /* We found a previously unregistered instance */
768         BLST_S_REMOVE(&gDbgState.unregistered_instances, current, BDBG_DebugModuleInst, link);
769         instance = current;
770
771         /* Remove and free each module instance */
772         while( (pInstanceModule = BLST_S_FIRST(&instance->modules)) != NULL ) {
773            BLST_S_REMOVE_HEAD(&instance->modules,link);
774            BDBG_P_Unlock();
775            BKNI_Free(pInstanceModule);
776            BDBG_P_Lock();
777         }
778
779         break;
780      }
781   }
782
783   if ( NULL == instance )
784   {
785      BDBG_P_Unlock();
786      instance = BKNI_Malloc(sizeof(*instance));
787      if(!instance) {
788         /* too bad */
789         return;
790      }
791      BDBG_P_Lock();
792   }
793
794   instance->module = module;
795   instance->name = NULL;
796   instance->level = module->module_level;
797   instance->handle = handle;
798   BLST_S_INIT(&instance->modules);
799
800   /* 1. Find spot in the sorted list */
801   for(previous=NULL, current = BLST_S_FIRST(&gDbgState.instances); current ; current = BLST_S_NEXT(current, link)) {
802      if ((uint8_t *)current->handle >= (uint8_t *)handle) {
803         break;
804      }
805      previous=current;
806   }
807   if(previous) {
808      BLST_S_INSERT_AFTER(&gDbgState.instances, previous, instance, link);
809   } else {
810      BLST_S_INSERT_HEAD(&gDbgState.instances, instance, link);
811   }
812   BDBG_P_Unlock();
813
814   return;
815}
816
817void
818BDBG_P_UnRegisterInstance(BDBG_Instance handle, BDBG_pDebugModuleFile dbg_module)
819{
820   struct BDBG_DebugModuleInst *instance;
821
822   BSTD_UNUSED(dbg_module);
823
824   instance = BDBG_P_GetInstance(handle);
825   if(instance) {
826      BDBG_P_Lock();
827      BLST_S_REMOVE(&gDbgState.instances, instance, BDBG_DebugModuleInst, link);
828
829      /* Add instance to unregistered instance list to be freed later
830       * during BDBG_Uninit() */
831      BLST_S_INSERT_HEAD(&gDbgState.unregistered_instances, instance, link);
832      BDBG_P_Unlock();
833   }
834   return;
835}
836
837static void
838BDBG_P_EnterLeaveFunction(BDBG_pDebugModuleFile dbg_module, const char *function, const char *kind)
839{
840   if(BDBG_P_TestModule(dbg_module, BDBG_eTrace)) {
841      char timeStamp[20];
842      BDBG_P_GetTimeStamp(timeStamp, sizeof(timeStamp));
843
844      BDBG_P_PrintTrace(dbg_module, "%s %s %s: %s", gDbgPrefix[BDBG_eTrace], timeStamp, kind, function);
845   }
846}
847
848void
849BDBG_EnterFunction(BDBG_pDebugModuleFile dbg_module, const char *function)
850{
851   BDBG_P_EnterLeaveFunction(dbg_module, function, "Enter");
852   return;
853}
854
855void
856BDBG_LeaveFunction(BDBG_pDebugModuleFile dbg_module, const char *function)
857{
858   BDBG_P_EnterLeaveFunction(dbg_module, function, "Leave");
859   return;
860}
861
862
863BERR_Code
864BDBG_SetLevel(BDBG_Level level)
865{
866   BERR_Code rc = BDBG_P_CheckDebugLevel(level);
867   BDBG_pDebugModuleFile module;
868
869   if (rc!=BERR_SUCCESS) {
870      return BERR_TRACE(rc);
871   }
872
873   gDbgState.level = level;
874   /* traverse all known modules */
875   BDBG_P_Lock();
876   for(module = BLST_S_FIRST(&gDbgState.modules); module ; module = BLST_S_NEXT(module, link)) {
877      module->level = (level < module->module_level)?level:module->module_level; /* update current module level with smallest of global level and module level */
878   }
879   BDBG_P_Unlock();
880   return BERR_SUCCESS;
881}
882
883BERR_Code
884BDBG_GetLevel(BDBG_Level *level)
885{
886   *level = gDbgState.level;
887   return BERR_SUCCESS;
888}
889
890
891
892BERR_Code
893BDBG_SetInstanceLevel(BDBG_Instance handle, BDBG_Level level)
894{
895   struct BDBG_DebugModuleInst *instance;
896
897   BERR_Code rc = BDBG_P_CheckDebugLevel(level);
898
899   if (rc!=BERR_SUCCESS) {
900      return BERR_TRACE(rc);
901   }
902
903   instance = BDBG_P_GetInstance(handle);
904   if (!instance) {
905      return BERR_TRACE(BERR_INVALID_PARAMETER);
906   }
907   instance->level = level;
908
909   return BERR_SUCCESS;
910}
911
912BERR_Code
913BDBG_GetInstanceLevel(BDBG_Instance handle, BDBG_Level *level)
914{
915   struct BDBG_DebugModuleInst *instance;
916
917   instance = BDBG_P_GetInstance(handle);
918   if (!instance) {
919      return BERR_TRACE(BERR_INVALID_PARAMETER);
920   }
921   *level = instance->level;
922
923   return BERR_SUCCESS;
924}
925
926BERR_Code
927BDBG_SetInstanceName(BDBG_Instance handle, const char *name)
928{
929   struct BDBG_DebugModuleInst *instance;
930
931   instance = BDBG_P_GetInstance(handle);
932   if (!instance) {
933      return BERR_TRACE(BERR_INVALID_PARAMETER);
934   }
935   instance->name = name;
936
937   return BERR_SUCCESS;
938}
939
940static struct BDBG_DebugInstModule *
941BDBG_P_GetInstanceModule_sync(struct BDBG_DebugModuleInst *pInstance, BDBG_pDebugModuleFile pModule)
942{
943   struct BDBG_DebugInstModule * pInstanceModule;
944   for(pInstanceModule = BLST_S_FIRST(&pInstance->modules); pInstanceModule ; pInstanceModule = BLST_S_NEXT(pInstanceModule, link)) {
945      if (pInstanceModule->pModule >= pModule) break;
946   }
947   if (pInstanceModule && (pInstanceModule->pModule != pModule)) pInstanceModule = NULL;
948   return pInstanceModule;
949}
950
951static struct BDBG_DebugInstModule *
952BDBG_P_GetInstanceModule(struct BDBG_DebugModuleInst *pInstance, BDBG_pDebugModuleFile pModule)
953{
954   struct BDBG_DebugInstModule * pInstanceModule;
955
956   BDBG_P_Lock();
957   pInstanceModule = BDBG_P_GetInstanceModule_sync(pInstance, pModule);
958   BDBG_P_Unlock();
959   return pInstanceModule;
960}
961
962BERR_Code
963BDBG_P_SetInstanceModuleLevel(struct BDBG_DebugModuleInst *pInstance, BDBG_pDebugModuleFile pModule, BDBG_Level eLevel)
964{
965   struct BDBG_DebugInstModule *pInstanceModule, *pCurInstanceModule, *pPrevInstanceModule;
966
967   pInstanceModule = BDBG_P_GetInstanceModule(pInstance, pModule);
968
969   if (pInstanceModule == NULL)
970   {
971      /* Add instance to instance module list */
972      pInstanceModule = BKNI_Malloc(sizeof(struct BDBG_DebugInstModule));
973      if (pInstanceModule)
974      {
975         pInstanceModule->pModule = pModule;
976
977         BDBG_P_Lock();
978
979         /* 1. Find spot in the sorted list */
980         for(pPrevInstanceModule=NULL, pCurInstanceModule = BLST_S_FIRST(&pInstance->modules); pCurInstanceModule ; pCurInstanceModule = BLST_S_NEXT(pCurInstanceModule, link)) {
981            if ((uint8_t *)pCurInstanceModule->pModule >= (uint8_t *)pModule) {
982               break;
983            }
984            pPrevInstanceModule=pCurInstanceModule;
985         }
986         if(pPrevInstanceModule) {
987            BLST_S_INSERT_AFTER(&pInstance->modules, pPrevInstanceModule, pInstanceModule, link);
988         } else {
989            BLST_S_INSERT_HEAD(&pInstance->modules, pInstanceModule, link);
990         }
991
992         BDBG_P_Unlock();
993      }
994   }
995
996   if (pInstanceModule != NULL)
997   {
998      pInstanceModule->eLevel = eLevel;
999      return BERR_SUCCESS;
1000   }
1001   else
1002   {
1003      return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
1004   }
1005}
1006
1007BERR_Code
1008BDBG_GetModuleInstanceLevel(const char *name, BDBG_Instance handle, BDBG_Level *level)
1009{
1010   struct BDBG_DebugModuleInst *pInstance;
1011   BDBG_pDebugModuleFile pModule;
1012   struct BDBG_DebugInstModule *pInstanceModule;
1013
1014   /* Find the instance struct using the handle */
1015   pInstance = BDBG_P_GetInstance(handle);
1016   if (!pInstance)
1017   {
1018      return BERR_TRACE(BERR_INVALID_PARAMETER);
1019   }
1020
1021   /* Find the module struct using the name */
1022   pModule = BDBG_P_GetModuleByName(name);
1023   if (!pModule) {
1024      return BERR_TRACE(BERR_INVALID_PARAMETER);
1025   }
1026
1027   /* Fine the instance module struct using the instance and module */
1028   pInstanceModule = BDBG_P_GetInstanceModule(pInstance, pModule);
1029   if (!pInstanceModule)
1030   {
1031      /* An instance module level wasn't set, so we return the
1032       * instance's level instead */
1033      *level = pInstance->level;
1034   }
1035   else
1036   {
1037      *level = pInstanceModule->eLevel;
1038   }
1039
1040   return BERR_SUCCESS;
1041}
1042
1043BERR_Code
1044BDBG_SetModuleInstanceLevel(const char *name, BDBG_Instance handle, BDBG_Level level)
1045{
1046   struct BDBG_DebugModuleInst *pInstance;
1047   BDBG_pDebugModuleFile pModule;
1048
1049   /* Find the instance struct using the handle */
1050   pInstance = BDBG_P_GetInstance(handle);
1051   if (!pInstance)
1052   {
1053      return BERR_TRACE(BERR_INVALID_PARAMETER);
1054   }
1055
1056   /* Find the module struct using the name */
1057   pModule = BDBG_P_GetModuleByName(name);
1058   if (!pModule) {
1059      return BERR_TRACE(BERR_INVALID_PARAMETER);
1060   }
1061
1062   /* Set instance module level using the instance and module */
1063   return BDBG_P_SetInstanceModuleLevel(pInstance, pModule, level);
1064}
1065
1066BERR_Code
1067BDBG_SetModuleLevel(const char *name, BDBG_Level level)
1068{
1069   BDBG_pDebugModuleFile module;
1070   struct BDBG_DebugModuleInst *pInstance;
1071   char module_name[BDBG_P_MAX_MODULE_NAME_LENGTH];
1072   char *instance_name = NULL;
1073   BERR_Code rc = BDBG_P_CheckDebugLevel(level);
1074
1075   if (rc!=BERR_SUCCESS) {
1076      return BERR_TRACE(rc);
1077   }
1078
1079   BDBG_P_StrnCpy(module_name, name, BDBG_P_MAX_MODULE_NAME_LENGTH);
1080   instance_name = BDBG_P_StrChrNul(module_name, ':');
1081   if (*instance_name != '\0')
1082   {
1083      *instance_name = '\0';
1084      instance_name++;
1085   }
1086
1087   pInstance = BDBG_P_GetInstanceByName(instance_name);
1088
1089   if (pInstance)
1090   {
1091      module = BDBG_P_GetModuleByName(module_name);
1092      if (!module) {
1093         return BERR_TRACE(BERR_INVALID_PARAMETER);
1094      }
1095
1096      BDBG_P_SetInstanceModuleLevel(pInstance, module, level);
1097   }
1098   else
1099   {
1100      module = BDBG_P_GetModuleByName(name);
1101      if (!module) {
1102         return BERR_TRACE(BERR_INVALID_PARAMETER);
1103      }
1104
1105      /* We set the module level */
1106      /* traverse all files of given module */
1107      BDBG_P_Lock();
1108      for(; module ; module = BLST_S_NEXT(module, link)) {
1109         if(BDBG_P_StrCmp(name, module->name)!=0) {
1110            break;
1111         }
1112         module->module_level = level;
1113         module->level = (gDbgState.level < level)?gDbgState.level:level; /* update current module level with smallest  of global level and module level */
1114      }
1115      BDBG_P_Unlock();
1116   }
1117
1118   return BERR_SUCCESS;
1119}
1120
1121BERR_Code
1122BDBG_GetModuleLevel(const char *name, BDBG_Level *level)
1123{
1124   BDBG_pDebugModuleFile module;
1125   struct BDBG_DebugModuleInst *pInstance;
1126   struct BDBG_DebugInstModule *pInstanceModule = NULL;
1127   char module_name[BDBG_P_MAX_MODULE_NAME_LENGTH];
1128   char *instance_name = NULL;
1129
1130   BDBG_P_StrnCpy(module_name, name, BDBG_P_MAX_MODULE_NAME_LENGTH);
1131   instance_name = BDBG_P_StrChrNul(module_name, ':');
1132   if (*instance_name != '\0')
1133   {
1134      *instance_name = '\0';
1135      instance_name++;
1136   }
1137
1138   pInstance = BDBG_P_GetInstanceByName(instance_name);
1139
1140   if (pInstance)
1141   {
1142      module = BDBG_P_GetModuleByName(module_name);
1143      if (!module) {
1144         return BERR_TRACE(BERR_INVALID_PARAMETER);
1145      }
1146
1147      /* Fine the instance module struct using the instance and module */
1148      pInstanceModule = BDBG_P_GetInstanceModule(pInstance, module);
1149      if (!pInstanceModule)
1150      {
1151         /* An instance module level wasn't set, so we return the
1152          * instance's level instead */
1153         *level = pInstance->level;
1154      }
1155      else
1156      {
1157         *level = pInstanceModule->eLevel;
1158      }
1159   }
1160   else
1161   {
1162      module = BDBG_P_GetModuleByName(name);
1163      if (!module) {
1164         return BERR_TRACE(BERR_INVALID_PARAMETER);
1165      }
1166      *level = module->level;
1167   }
1168   return BERR_SUCCESS;
1169}
1170
1171BERR_Code
1172BDBG_Init(void)
1173{
1174   BDBG_P_InitializeTimeStamp();
1175   return BDBG_P_OsInit();
1176}
1177
1178void
1179BDBG_Uninit(void)
1180{
1181   BDBG_pDebugModuleFile module ;
1182   struct BDBG_DebugModuleInst *instance;
1183   struct BDBG_DebugInstModule *pInstanceModule = NULL;
1184
1185   while( (module = BLST_S_FIRST(&gDbgState.modules)) != NULL ) {
1186      BLST_S_REMOVE_HEAD(&gDbgState.modules,link);
1187      if (module->module_alloc) {
1188         BKNI_Free(module);
1189      }
1190   }
1191   while( (instance = BLST_S_FIRST(&gDbgState.instances)) != NULL ) {
1192      BLST_S_REMOVE_HEAD(&gDbgState.instances,link);
1193
1194      /* Remove and free each module instance */
1195      while( (pInstanceModule = BLST_S_FIRST(&instance->modules)) != NULL ) {
1196         BLST_S_REMOVE_HEAD(&instance->modules,link);
1197         BKNI_Free(pInstanceModule);
1198      }
1199
1200      BKNI_Free(instance);
1201   }
1202
1203   while( (instance = BLST_S_FIRST(&gDbgState.unregistered_instances)) != NULL ) {
1204      BLST_S_REMOVE_HEAD(&gDbgState.unregistered_instances,link);
1205
1206      /* Remove and free each module instance */
1207      while( (pInstanceModule = BLST_S_FIRST(&instance->modules)) != NULL ) {
1208         BLST_S_REMOVE_HEAD(&instance->modules,link);
1209         BKNI_Free(pInstanceModule);
1210      }
1211
1212      BKNI_Free(instance);
1213   }
1214   BDBG_P_Dequeue_FreeMemory();
1215
1216   BDBG_P_OsUninit();
1217
1218   return;
1219}
1220
1221/* BDBG_OBJECT_ID(bdbg_invalid); */
1222static const char bdbg_id__bdbg_invalid[]="invalid";
1223
1224
1225void
1226BDBG_Object_Init(void *ptr, size_t size, struct bdbg_obj *obj, const char *id)
1227{
1228   unsigned i;
1229
1230   if ( NULL == id )
1231   {
1232       id = bdbg_id__bdbg_invalid;
1233   }
1234
1235   for(i=0; i+3 < size; i+=4) {
1236      *(uint32_t*)(((uint8_t *)ptr)+i)=0xDEADBEEF;
1237   }
1238   obj->bdbg_obj_id=id;
1239   return;
1240}
1241
1242void
1243BDBG_Object_Assert(const void *ptr, size_t size, const struct bdbg_obj *obj, const char *id, const char *file, unsigned line) {
1244    static char message[128]; /* if used, this will be terminal. so use a static array to avoid stack blowout. */
1245
1246    BSTD_UNUSED(size);
1247
1248    if (ptr && obj->bdbg_obj_id==id) {
1249        return;
1250    }
1251
1252#if BKNI_TRACK_MALLOCS
1253    if(ptr) {
1254        BKNI_MallocEntryInfo entry;
1255
1256        if(BKNI_GetMallocEntryInfo(ptr, &entry)==BERR_SUCCESS) {
1257            message[0] = '\0';
1258            if(!entry.alive) {
1259                BKNI_Snprintf(message, sizeof(message), "and freed at %s:%u", entry.free_file, entry.free_line);
1260            }
1261            BDBG_P_PrintString("BDBG_OBJECT_ASSERT on object %#lx (%u:%u bytes) was allocated at %s:%u %s\n", (unsigned long)ptr, entry.size, size, entry.malloc_file, entry.malloc_line, message);
1262        }
1263    }
1264#endif
1265    message[0] = '\0';
1266    if(ptr==NULL) {
1267        BKNI_Snprintf(message, sizeof(message), "NULL pointer was used as %s", id);
1268    } else {
1269        if (obj->bdbg_obj_id == bdbg_id__bdbg_invalid) {
1270            BKNI_Snprintf(message, sizeof(message), "Recycled pointer was used %s:%#lx", id, (unsigned long)ptr);
1271        } else {
1272            /* This can be caused by a closed or otherwise invalid handle */
1273            BKNI_Snprintf(message, sizeof(message), "Bad object of expected type %s:%#lx (%#lx:%#lx)", id, (unsigned long)ptr, (unsigned long)obj->bdbg_obj_id, (unsigned long)id);
1274        }
1275    }
1276
1277    BDBG_P_AssertFailed(message, file, line);
1278    return;
1279}
1280
1281void
1282BDBG_EnumerateAll(void (*callback)(void *cntx, const char *module, BDBG_Instance instance, const char *inst_name), void *cntx)
1283{
1284   struct BDBG_DebugModuleInst *instance=NULL;
1285   BDBG_pDebugModuleFile module;
1286   const char *last_name;
1287
1288   BDBG_P_Lock();
1289   for(last_name=NULL, module = BLST_S_FIRST(&gDbgState.modules); module ; module = BLST_S_NEXT(module, link)) {
1290      if(last_name==NULL || BDBG_P_StrCmp(last_name, module->name)!=0) {
1291         last_name = module->name;
1292         callback(cntx, module->name, NULL, NULL);
1293      }
1294   }
1295   for(instance = BLST_S_FIRST(&gDbgState.instances); instance ; instance = BLST_S_NEXT(instance, link)) {
1296      callback(cntx, instance->module->name, instance->handle, instance->name);
1297   }
1298   BDBG_P_Unlock();
1299   return ;
1300}
1301
1302void
1303BDBG_P_Release(BDBG_pDebugModuleFile dbg_module)
1304{
1305   BDBG_P_Lock();
1306   if(dbg_module->level!=BDBG_P_eUnknown) {
1307        BLST_S_REMOVE(&gDbgState.modules, dbg_module, BDBG_DebugModuleFile, link);
1308        dbg_module->level = BDBG_P_eUnknown;
1309   }
1310   BDBG_P_Unlock();
1311   return;
1312}
1313
1314
1315BERR_Code
1316BDBG_SetModulePrintFunction(const char *name, BDBG_DebugModule_Print module_print)
1317{
1318#if defined(BDBG_P_UNWRAP)
1319    BDBG_pDebugModuleFile module;
1320
1321    module = BDBG_P_GetModuleByName(name);
1322    if (!module) {
1323        return BERR_TRACE(BERR_INVALID_PARAMETER);
1324    }
1325
1326    /* We set the module level */
1327    /* traverse all files of given module */
1328    BDBG_P_Lock();
1329    for(; module ; module = BLST_S_NEXT(module, link)) {
1330        if(BDBG_P_StrCmp(name, module->name)!=0) {
1331            break;
1332        }
1333        module->level = (gDbgState.level < module->module_level)?gDbgState.level:module->module_level; /* update current module level with smallest  of global level and module level */
1334        module->module_print = module_print;
1335        if(module_print) {
1336            module->level = -module->level; /* make it negative so it'd always pass test */
1337        }
1338    }
1339    BDBG_P_Unlock();
1340
1341    return BERR_SUCCESS;
1342#else
1343    BSTD_UNUSED(name);
1344    BSTD_UNUSED(module_print);
1345    return BERR_TRACE(BERR_NOT_SUPPORTED);
1346#endif
1347}
1348
1349typedef struct BDBG_P_Dequeue_Context {
1350    bool used;
1351    uint16_t hdr_len;
1352    uint32_t tag;
1353    char *header_buf;
1354    size_t header_buf_size;
1355} BDBG_P_Dequeue_Context;
1356#define BDBG_P_DEQUEUE_MAX_CONTEXTS 16
1357static struct {
1358    unsigned last_used;
1359    unsigned nodata_count;
1360    BDBG_P_Dequeue_Context contexts[BDBG_P_DEQUEUE_MAX_CONTEXTS];
1361} BDBG_P_Dequeue_State;
1362
1363#define BDBG_P_CONTEXT_THRESHOLD    256
1364
1365static BDBG_P_Dequeue_Context *BDBG_P_Dequeue_FindContext(unsigned long tag)
1366{
1367    unsigned i;
1368    for(i=0;i<BDBG_P_Dequeue_State.last_used;i++) {
1369        BDBG_P_Dequeue_Context *context = BDBG_P_Dequeue_State.contexts+i;
1370        if(context->used) {
1371            long diff = tag - context->tag;
1372            if( -BDBG_P_CONTEXT_THRESHOLD < diff && diff < BDBG_P_CONTEXT_THRESHOLD) {
1373                return context;
1374            }
1375        }
1376    }
1377    return NULL;
1378}
1379
1380static BDBG_P_Dequeue_Context *BDBG_P_Dequeue_FindFree(size_t hdr_len)
1381{
1382    unsigned i;
1383    BDBG_P_Dequeue_Context *context=NULL;
1384
1385    for(i=0;i<BDBG_P_Dequeue_State.last_used;i++) {
1386        BDBG_P_Dequeue_Context *cur_context = BDBG_P_Dequeue_State.contexts+i;
1387        if(!cur_context->used) {
1388            context = cur_context;
1389            break;
1390        }
1391    }
1392    if(context == NULL) {
1393        if(BDBG_P_Dequeue_State.last_used >= BDBG_P_DEQUEUE_MAX_CONTEXTS) {
1394            return NULL;
1395        }
1396        context = BDBG_P_Dequeue_State.contexts+BDBG_P_Dequeue_State.last_used;
1397        BDBG_P_Dequeue_State.last_used++;
1398        context->used = false;
1399        context->tag = 0;
1400        context->header_buf = NULL;
1401        context->header_buf_size = 0;
1402    }
1403    if(context->header_buf_size < hdr_len)  {
1404        if(context->header_buf) {
1405            context->header_buf_size = 0;
1406            BKNI_Free(context->header_buf);
1407        }
1408        context->header_buf = BKNI_Malloc(hdr_len);
1409        if(context->header_buf==NULL) {
1410            return NULL;
1411        }
1412        context->header_buf_size = hdr_len;
1413    }
1414    return context;
1415}
1416
1417static void BDBG_P_Dequeue_FreeMemory(void)
1418{
1419    unsigned i;
1420    for(i=0;i<BDBG_P_Dequeue_State.last_used;i++) {
1421        BDBG_P_Dequeue_Context *context = BDBG_P_Dequeue_State.contexts+i;
1422        if(context->header_buf) {
1423            BKNI_Free(context->header_buf);
1424            context->used = false;
1425            context->header_buf = NULL;
1426            context->header_buf_size = 0;
1427        }
1428    }
1429    BDBG_P_Dequeue_State.nodata_count = 0;
1430    BDBG_P_Dequeue_State.last_used = 0;
1431    return;
1432}
1433
1434typedef struct BDBG_P_StrBuf {
1435    char *str;
1436    size_t size;
1437    unsigned len;
1438}BDBG_P_StrBuf;
1439
1440
1441static void BDBG_P_StrBuf_Printf( BDBG_P_StrBuf *buf, const char *fmt, ...)
1442{
1443    int rc;
1444    size_t size = buf->size - buf->len;
1445    va_list ap;
1446    va_start(ap, fmt);
1447    rc = BKNI_Vsnprintf(buf->str, size, fmt, ap);
1448    va_end( ap );
1449    if(rc>0) {
1450        buf->len = (unsigned)rc<size  ? buf->len + rc : buf->size - 1;
1451    }
1452    return;
1453}
1454
1455#if 0
1456static void BDBG_P_StrBuf_PrintChar( BDBG_P_StrBuf *buf, char c)
1457{
1458    if(buf->len + 1 > buf->size) {
1459        buf->str[buf->len]=c;
1460        buf->len++;
1461        buf->str[buf->len]='\0';
1462    }
1463    return;
1464}
1465#endif
1466
1467static void BDBG_P_StrBuf_Memcpy( BDBG_P_StrBuf *buf, const void *b, size_t len)
1468{
1469    if(buf->len + len + 1 < buf->size) {
1470        /* buffer large enough, do nothing, keep going */
1471    } else if(buf->len + 1 < buf->size) {
1472        /* there is a space for at least one character */
1473        len = buf->size  - (buf->len + 1);
1474    } else {
1475        /* there is no space */
1476        return;
1477    }
1478    BKNI_Memcpy(buf->str+buf->len, b, len);
1479    buf->len += len;
1480    buf->str[buf->len]='\0';
1481    return;
1482}
1483
1484static void BDBG_P_StrBuf_AddLog( BDBG_P_StrBuf *buf, const BDBG_P_LogEntry *log)
1485{
1486    size_t len;
1487    if(log->rc>0) {
1488        len = (unsigned)log->rc < sizeof(log->str) ? (unsigned)log->rc : sizeof(log->str)-1;
1489        BDBG_P_StrBuf_Memcpy(buf, log->str, len);
1490    }
1491}
1492
1493static void BDBG_P_Dequeue_Flush(BDBG_P_StrBuf *buf)
1494{
1495    unsigned i;
1496
1497    BDBG_P_StrBuf_Printf(buf, "___  OVERFLOW ___");
1498    for(i=0;i<BDBG_P_Dequeue_State.last_used;i++) {
1499        BDBG_P_Dequeue_Context *context = BDBG_P_Dequeue_State.contexts+i;
1500        if(context->used) {
1501            BDBG_P_StrBuf_Printf(buf, "\n___ %s ### OVERFLOW ###");
1502        }
1503    }
1504    return;
1505}
1506
1507static void
1508BDBG_P_Dequeue_FilterString(char *str)
1509{
1510    /* remove control character */
1511    for(;;) {
1512        char ch = *str;
1513        if(ch=='\0') {
1514            break;
1515        }
1516        switch(ch) {
1517        case '\r':
1518        case '\n':
1519        case '\b':
1520        case '\f':
1521        case '\a':
1522        case 27: /* escape */
1523        case 127: /* delete */
1524            *str = ' ';
1525            break;
1526        default:
1527            break;
1528        }
1529        str++;
1530    }
1531}
1532
1533BERR_Code
1534BDBG_Log_Dequeue(BDBG_FifoReader_Handle logReader, unsigned *timeout, char *str, size_t str_size, size_t *str_len)
1535{
1536    BERR_Code rc;
1537    BDBG_ModulePrintKind kind;
1538    BDBG_P_LogEntry logEntry;
1539    BDBG_P_Dequeue_Context *context;
1540    BDBG_P_StrBuf buf;
1541    size_t hdr_len;
1542
1543    BDBG_ASSERT(timeout);
1544    BDBG_ASSERT(str);
1545    BDBG_ASSERT(str_len);
1546
1547    *timeout = 0;
1548    *str_len = 0;
1549    *str = '\0';
1550    buf.str = str;
1551    buf.len = 0;
1552    buf.size = str_size;
1553    rc = BDBG_FifoReader_Read(logReader, &logEntry, sizeof(logEntry));
1554    switch(rc) {
1555    case BERR_SUCCESS:
1556        break;
1557    case BERR_FIFO_NO_DATA:
1558        *timeout = 5;
1559        if(BDBG_P_Dequeue_State.nodata_count<16) {
1560            BDBG_P_Dequeue_State.nodata_count++;
1561            if(BDBG_P_Dequeue_State.nodata_count<4) {
1562                *timeout = 0;
1563            }
1564            *timeout = 1;
1565        }
1566        return BERR_SUCCESS;
1567    case BERR_FIFO_BUSY:
1568        *timeout = 1;
1569        return BERR_SUCCESS;
1570    case BERR_FIFO_OVERFLOW:
1571        BDBG_P_Dequeue_Flush(&buf);
1572        *str_len = buf.len;
1573        BDBG_FifoReader_Resync(logReader);
1574        BDBG_P_Dequeue_State.nodata_count = 0;
1575        return BERR_SUCCESS;
1576    default:
1577        return BERR_TRACE(rc);
1578    }
1579    BDBG_P_Dequeue_State.nodata_count = 0;
1580    kind = logEntry.tag & 0x03;
1581    switch(kind) {
1582    case BDBG_ModulePrintKind_eString:
1583    case BDBG_ModulePrintKind_eHeaderAndBody:
1584        BDBG_P_Dequeue_FilterString(logEntry.str);
1585        BDBG_P_StrBuf_AddLog(&buf, &logEntry);
1586        break;
1587    case BDBG_ModulePrintKind_eHeader:
1588        context = BDBG_P_Dequeue_FindContext(logEntry.tag);
1589        if(context) {
1590            BDBG_P_StrBuf_Printf(&buf, "___ %s ### MISSING ###", context->header_buf);
1591            context->used = false;
1592        }
1593        if(logEntry.rc>0) {
1594            hdr_len = (unsigned)logEntry.rc < sizeof(logEntry.str) ? (unsigned)logEntry.rc +1 : sizeof(logEntry.str);
1595            context = BDBG_P_Dequeue_FindFree(hdr_len);
1596            if(context) {
1597                context->hdr_len = hdr_len;
1598                context->used = true;
1599                context->tag = logEntry.tag;
1600                BKNI_Memcpy(context->header_buf, logEntry.str, hdr_len);
1601            }
1602        } 
1603        break;
1604    case BDBG_ModulePrintKind_eBody:
1605        context = BDBG_P_Dequeue_FindContext(logEntry.tag);
1606        if(context) {
1607            BDBG_P_Dequeue_FilterString(logEntry.str);
1608            BDBG_P_StrBuf_Memcpy(&buf, context->header_buf, context->hdr_len-1);
1609            BDBG_P_StrBuf_AddLog(&buf, &logEntry);
1610            context->used = false;
1611        } else {
1612            BDBG_P_StrBuf_Printf(&buf, "___ ### MISSING ### %s", logEntry.str);
1613        }
1614        break;
1615    default:
1616        break;
1617    }
1618    *str_len = buf.len;
1619    return BERR_SUCCESS;
1620}
1621
1622void 
1623BDBG_Log_GetElementSize( size_t *elementSize )
1624{
1625    BDBG_ASSERT(elementSize);
1626    *elementSize = sizeof(BDBG_P_LogEntry);
1627    return;
1628}
1629
1630void
1631BDBG_Log_SetFifo(BDBG_Fifo_Handle fifo)
1632{
1633    gDbgState.dbgLog = fifo;
1634    return;
1635}
1636
1637
1638
1639char* strrchr(char *s,int c)
1640{
1641    int len = strlen(s);
1642    char* lptr = &s[len];
1643
1644    while (len) {
1645        if (*lptr == (char)c) {
1646            return lptr;
1647        }
1648                len--;
1649                lptr--;
1650    }
1651    return NULL;
1652}
1653
Note: See TracBrowser for help on using the repository browser.