1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     dbg_Break.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 48011 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/Result.h>
17 #include <nn/dbg/dbg_Break.h>
18 #include <nn/dbg/dbg_DebugString.h>
19 #include <nn/svc.h>
20 #include <nn/config.h>
21 #include <cstdarg>
22 
23 using namespace nn::dbg;
24 
25 namespace
26 {
27     nn::dbg::BreakHandler  s_pBreakHandler = NULL;
28 
PrintErrorMessageHeader(nndbgBreakReason reason,const char * filename,int lineno)29     void PrintErrorMessageHeader(nndbgBreakReason reason, const char* filename, int lineno)
30     {
31         detail::TPrintf("----\n");
32         if( reason == NN_DBG_BREAK_REASON_ASSERT )
33         {
34             detail::TPrintf("Assertion failure at %s:%d\n  ", filename, lineno);
35         }
36         else
37         {
38             detail::TPrintf("Panic at %s:%d\n  ", filename, lineno);
39         }
40     }
41 
CallBreakHandler(BreakReason reason,nn::Result * pResult,const char * filename,int lineno,const char * fmt,std::va_list args)42     void CallBreakHandler(BreakReason reason, nn::Result* pResult, const char* filename, int lineno, const char* fmt, std::va_list args)
43     {
44         nn::dbg::BreakHandler  pBreakHandler = s_pBreakHandler;
45 
46         if( pBreakHandler != NULL )
47         {
48             s_pBreakHandler = NULL;
49             pBreakHandler(reason, pResult, filename, lineno, fmt, args);
50         }
51     }
52 
CallBreakHandler(nndbgBreakReason reason,nnResult result,const char * filename,int lineno,const char * fmt,std::va_list args)53     void CallBreakHandler(nndbgBreakReason reason, nnResult result, const char* filename, int lineno, const char* fmt, std::va_list args)
54     {
55         nn::Result resultCpp = result;
56         CallBreakHandler(static_cast<BreakReason>(reason), &resultCpp, filename, lineno, fmt, args);
57     }
58 
CallBreakHandler(nndbgBreakReason reason,const char * filename,int lineno,const char * fmt,std::va_list args)59     void CallBreakHandler(nndbgBreakReason reason, const char* filename, int lineno, const char* fmt, std::va_list args)
60     {
61         CallBreakHandler(static_cast<BreakReason>(reason), NULL, filename, lineno, fmt, args);
62     }
63 
CallBreakHandler(BreakReason reason)64     void CallBreakHandler(BreakReason reason)
65     {
66         std::va_list args;
67         CallBreakHandler(reason, NULL, NULL, 0, NULL, args);
68     }
69 }
70 
71 extern "C" {
72 
nndbgBreak(int reason)73     nnResult nndbgBreak(int reason)
74     {
75         return nn::dbg::Break(static_cast<nn::dbg::BreakReason>(reason));
76     }
77 
nndbgPanic()78     void nndbgPanic()
79     {
80         Panic();
81     }
82 
nndbgBreakWithMessage_(nndbgBreakReason reason,const char * filename,int lineno,const char * fmt,...)83     void nndbgBreakWithMessage_ (nndbgBreakReason reason, const char* filename, int lineno, const char* fmt, ...)
84     {
85         va_list arg;
86         va_start(arg, fmt);
87         PrintErrorMessageHeader(reason, filename, lineno);
88         detail::VPrintf(fmt, arg);
89         detail::TPrintf("\n");
90         va_end(arg);
91 
92         va_start(arg, fmt);
93         CallBreakHandler(reason, filename, lineno, fmt, arg);
94         va_end(arg);
95 
96         Break(static_cast<BreakReason>(reason));
97     }
98 
nndbgBreakWithTMessage_(nndbgBreakReason reason,const char * filename,int lineno,const char * fmt,...)99     void nndbgBreakWithTMessage_(nndbgBreakReason reason, const char* filename, int lineno, const char* fmt, ...)
100     {
101         va_list arg;
102         va_start(arg, fmt);
103         PrintErrorMessageHeader(reason, filename, lineno);
104         detail::TVPrintf(fmt, arg);
105         detail::TPrintf("\n");
106         va_end(arg);
107 
108         va_start(arg, fmt);
109         CallBreakHandler(reason, filename, lineno, fmt, arg);
110         va_end(arg);
111 
112         Break(static_cast<BreakReason>(reason));
113     }
114 
nndbgBreakWithResultMessage_(nndbgBreakReason reason,nnResult result,const char * filename,int lineno,const char * fmt,...)115     void nndbgBreakWithResultMessage_ (nndbgBreakReason reason, nnResult result, const char* filename, int lineno, const char* fmt, ...)
116     {
117         va_list arg;
118         va_start(arg, fmt);
119         PrintErrorMessageHeader(reason, filename, lineno);
120         detail::VPrintf(fmt, arg);
121         detail::TPrintf("\n");
122         detail::PrintResult(result);
123         va_end(arg);
124 
125         va_start(arg, fmt);
126         CallBreakHandler(reason, result, filename, lineno, fmt, arg);
127         va_end(arg);
128 
129         Break(static_cast<BreakReason>(reason));
130     }
131 
nndbgBreakWithResultTMessage_(nndbgBreakReason reason,nnResult result,const char * filename,int lineno,const char * fmt,...)132     void nndbgBreakWithResultTMessage_(nndbgBreakReason reason, nnResult result, const char* filename, int lineno, const char* fmt, ...)
133     {
134         va_list arg;
135         va_start(arg, fmt);
136         PrintErrorMessageHeader(reason, filename, lineno);
137         detail::TVPrintf(fmt, arg);
138         detail::TPrintf("\n");
139         detail::PrintResult(result);
140         va_end(arg);
141 
142         va_start(arg, fmt);
143         CallBreakHandler(reason, result, filename, lineno, fmt, arg);
144         va_end(arg);
145 
146         Break(static_cast<BreakReason>(reason));
147     }
148 }
149 
150 namespace nn { namespace dbg {
151 
Break(BreakReason reason)152     Result Break(BreakReason reason)
153     {
154         CallBreakHandler(reason);
155         return nn::svc::Break(reason, NULL, 0);
156     }
157 
Panic()158     void Panic()
159     {
160         Break(BREAK_REASON_PANIC);
161     }
162 
SetBreakHandler(BreakHandler handler)163     void SetBreakHandler(BreakHandler handler)
164     {
165         NN_POINTER_TASSERT_(handler);
166         s_pBreakHandler = handler;
167     }
168 
169     namespace detail
170     {
NotifyDllLoadedToDebugger(const void * pDllInfo,size_t size)171         Result NotifyDllLoadedToDebugger(const void* pDllInfo, size_t size)
172         {
173             return nn::svc::Break(BREAK_REASON_LOAD_RO, pDllInfo, size);
174         }
175 
NotifyDllUnloadingToDebugger(const void * pDllInfo,size_t size)176         Result NotifyDllUnloadingToDebugger(const void* pDllInfo, size_t size)
177         {
178             return nn::svc::Break(BREAK_REASON_UNLOAD_RO, pDllInfo, size);
179         }
180     }
181 
182 }}
183