1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     dbg_Argument.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:$
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn.h>
17 #include <nn/dbg/dbg_Argument.h>
18 #include <nn/dbg/dbg_ArgumentPrivate.h>
19 
20 #ifdef NN_CTR_ARG_AVAILABLE
21 
22 using namespace nn::dbg::CTR;
23 
24 namespace
25 {
26     //---- argument buffer
27     bit8 s_ArgBuffer[ NN_DBG_ARG_BUFFER_SIZE ] = {1}; // The default data is dummy data. So it won't be set to the bss region
28 
29     //---- current argument buffer
30     const void* s_pCurrentArgBuffer;
31     size_t      s_CurrentArgBufferSize;
32 
33     //---- argv[0] equivalent string
34     const char* s_pApplicationStr = NN_DBG_ARG_ARGV0_STRING;
35 
36     //---- argumento information structure (fixed region)
37     const nn::dbg::CTR::ArgArea s_ArgInfo __attribute__((section(".ARM.__at_0x100ff0"))) =
38     {
39         NN_DBG_ARG_MAGIC_NUM,
40         reinterpret_cast<const void*>(&s_ArgBuffer),
41         sizeof(s_ArgBuffer),
42         NN_DBG_ARG_MAGIC_NUM,
43     };
44 
45     //---- argc, argv information
46     int         s_Argc = 0;
47     const char* s_pArgv = NULL;
48     bool        s_IsInitialized = false;
49 
50     //---- binary information
51     const void* s_pBinaryArea = NULL;
52     size_t      s_BinaryAreaSize = 0;
53 
54     //---- for option parsing
55     const char* s_pOptArg = NULL;
56     int         s_OptInd  = 1;
57     int         s_OptOpt  = 0;
58 }
59 
60 //#define offsetof(type, member) ((size_t)&(type*)0->member)
61 
62 namespace nn {
63 namespace dbg {
64 namespace CTR {
65     static const char *match_opt(int optchar, const char *optstring);
66 
67     //----------------------------------------------------------------
Setup(const void * pBuffer,size_t size)68     static void Setup( const void* pBuffer, size_t size )
69     {
70         if ( ! s_IsInitialized )
71         {
72             s_Argc = 0;
73             s_pArgv = NULL;
74             s_pBinaryArea = NULL;
75             s_BinaryAreaSize = 0;
76 
77             s_pOptArg = NULL;
78             s_OptInd = 1;
79             s_OptOpt = 0;
80 
81             s_pCurrentArgBuffer = pBuffer;
82             s_CurrentArgBufferSize = size;
83 
84             // Magic number check
85             const ArgInfoHeader* pHeader = reinterpret_cast<const ArgInfoHeader*>(pBuffer);
86             if ( pHeader->magic == NN_DBG_ARG_MAGIC_NUM_ARG )
87             {
88                 // Gets information from the obtained buffer
89                 s_pArgv = reinterpret_cast<const char*>( reinterpret_cast<const bit8*>(pHeader) + pHeader->argStart );
90                 s_Argc = pHeader->argNum + 1; // +1 since includes self
91                 s_pBinaryArea = reinterpret_cast<const void*>( reinterpret_cast<const bit8*>(pHeader) + pHeader->binaryStart );
92                 s_BinaryAreaSize = pHeader->binarySize;
93             }
94 
95             s_IsInitialized = true;
96         }
97     }
98     //----------------------------------------------------------------
Setup(void)99     static void Setup(void)
100     {
101         if ( ! s_IsInitialized )
102         {
103             // Magic number check
104             if ( s_ArgInfo.magic1 == NN_DBG_ARG_MAGIC_NUM && s_ArgInfo.magic2 == NN_DBG_ARG_MAGIC_NUM )
105             {
106                 Setup( s_ArgInfo.pArgArea, s_ArgInfo.areaSize );
107             }
108         }
109     }
110     //----------------------------------------------------------------
Reset(void)111     static void Reset(void)
112     {
113         s_IsInitialized = false;
114     }
115 
116     //----------------------------------------------------------------
117     // Gets as a binary
GetArgBinary(void)118     const void* GetArgBinary( void )
119     {
120         Setup();
121         return s_pBinaryArea;
122     }
123     //----------------------------------------------------------------
124     // Gets as a binary
GetArgBinarySize(void)125     size_t GetArgBinarySize( void )
126     {
127         Setup();
128         return s_BinaryAreaSize;
129     }
130 
131     //----------------------------------------------------------------
132     // Gets the number of arguments
133     //     For example, return value is 3 when "-T 123" is given
134     //     1 when there are no arguments
135     //     0 when there is no argument information region
GetArgc(void)136     int GetArgc(void)
137     {
138         Setup();
139         return s_Argc;
140     }
141 
142     //----------------------------------------------------------------
143     // Gets arguments
144     //    For example, when "-T 123" is set in the arguments
145     //    argv[0]=Arg0String argv[1]="-T" argv[2]="123"
146     //    When there is no argument information region, NULL is returned regardless of the index
GetArgv(int index)147     const char* GetArgv( int index )
148     {
149         Setup();
150         int argc = GetArgc();
151 
152         // When specification is outside the argument range or when there is no argument buffer
153         if ( index < 0 || index >= argc || ! s_pArgv )
154         {
155             return NULL;
156         }
157 
158         // When argv[0] is acquired
159         if ( index == 0 )
160         {
161             return s_pApplicationStr;
162         }
163 
164         const char* p = s_pArgv;
165         for( index--; index>0; index-- )
166         {
167             int argsize = *(p + offsetof(ArgvFormat, size)) + *(p + offsetof(ArgvFormat, size) + 1)*256;
168             p += 2 + argsize + 1; // Advances size information 2 bytes + string + "\0"
169         }
170 
171         return (p + offsetof(ArgvFormat, string));
172     }
173 
174     //----------------------------------------------------------------
175     // Option analysis
GetOpt(const char * optstring)176     int GetOpt( const char *optstring )
177     {
178         Setup();
179 
180         static bool end_of_option = false;
181         int     optchar;
182         const char *arg;
183         const char *opt;
184         const char *optarg;
185 
186         s_pOptArg = NULL;
187         s_OptOpt = 0;
188 
189         // Reset if optstring is NULL
190         if (optstring == NULL)
191         {
192             s_OptInd = 1;
193             end_of_option = false;
194             return 0;
195         }
196 
197         // Get command line arguments
198         arg = GetArgv(s_OptInd);
199 
200         if (arg == NULL)
201         {
202             return -1;
203         }
204 
205         if (optstring[0] == '-')           // Minus Mode
206         {
207             s_OptInd++;                  // Consume arguments
208 
209             // Normal argument when it does not start with '-'
210             if (end_of_option || arg[0] != '-')
211             {
212                 s_pOptArg = arg;          // Normal arguments are also set to OptArg.
213                 return 1;
214             }
215 
216             // Option analysis
217             optchar = arg[1];
218 
219             if (optchar == '-')            // End of options when '--' is encountered
220             {
221                 end_of_option = true;      // Normal arguments from here on
222                 return GetOpt(optstring);
223             }
224         }
225         else                               // normal mode
226         {
227             // Normal argument when it does not start with '-'
228             if (end_of_option || arg[0] != '-')
229             {
230                 return -1;                 // OptArg remains NULL
231             }
232 
233             s_OptInd++;                  // Consume arguments
234 
235             // Option analysis
236             optchar = arg[1];
237 
238             if (optchar == '-')            // End of options when '--' is encountered
239             {
240                 end_of_option = true;      // Normal arguments from here on
241                 return -1;
242             }
243 
244         }
245 
246         opt = match_opt(optchar, optstring);
247 
248         if (opt == NULL)
249         {
250             s_OptOpt = optchar;                // Unknown option
251             return '?';
252         }
253 
254         if (opt[1] == ':')                     // OptArg search specification?
255         {
256             // Continuously specified similar to -oAAA (gnu expansion)
257             if ( arg[2] != '\0' )
258             {
259                 s_pOptArg = &arg[2];           // Current options are viewed as-is
260             }
261             // Determine with the next argument
262             else
263             {
264                 optarg = GetArgv(s_OptInd);
265 
266                 if (optarg == NULL || optarg[0] == '-')
267                 {
268                     s_pOptArg = NULL;
269 
270                     if (opt[2] != ':')        // '::' Or not?
271                     {
272                         s_OptOpt = optchar;   // OptArg not present.
273                         return '?';
274                     }
275                 }
276                 else
277                 {
278                     s_pOptArg = optarg;
279                     s_OptInd++;              // Consume arguments
280                 }
281             }
282         }
283         return optchar;
284     }
285 
286     //----------------
287     // GetOpt() sub-routine
match_opt(int optchar,const char * optstring)288     static const char *match_opt(int optchar, const char *optstring)
289     {
290         if (optstring[0] == '-' || optstring[0] == '+')
291         {
292             optstring++;
293         }
294 
295         if (optchar != ':')
296         {
297             while (*optstring)
298             {
299                 if (optchar == *optstring)
300                 {
301                     return optstring;
302                 }
303                 optstring++;
304             }
305         }
306         return NULL;
307     }
308 
309     //----------------------------------------------------------------
310     // Force assignment of the argument buffer
SetArgumentBuffer(const void * pBuffer,size_t size)311     void SetArgumentBuffer( const void *pBuffer, size_t size )
312     {
313         Reset();
314         Setup( pBuffer, size );
315     }
316     //----------------------------------------------------------------
317     // Get argument buffer row region
GetArgumentBuffer(void)318     const void *GetArgumentBuffer(void)
319     {
320         return s_pCurrentArgBuffer;
321     }
GetArgumentBufferSize(void)322     size_t GetArgumentBufferSize(void)
323     {
324         return s_CurrentArgBufferSize;
325     }
326     //----------------------------------------------------------------
327     // Equivalent to option parsing optind
GetOptInd(void)328     int GetOptInd( void )
329     {
330         return s_OptInd;
331     }
332     //----------------------------------------------------------------
333     // Equivalent to option parsing optarg
GetOptArg(void)334     const char* GetOptArg( void )
335     {
336         return s_pOptArg;
337     }
338     //----------------------------------------------------------------
339     // Equivalent to option parsing optopt
GetOptOpt(void)340     int GetOptOpt( void )
341     {
342         return s_OptOpt;
343     }
344 }
345 }
346 }
347 
348 #else
349 
350 //----------------------------------------------------------------
351 // For Release ROM
352 
353 namespace
354 {
355     //---- argumento information structure (fixed region)
356     const nn::dbg::CTR::ArgArea s_ArgInfo __attribute__((section(".ARM.__at_0x100ff0"))) =
357     {
358         0,
359         NULL,
360         NULL,
361         1, // Set to a value different from the first member's
362     };
363 }
364 
365 namespace nn {
366 namespace dbg {
367 namespace CTR {
368 
GetArgBinary(void)369     const void* GetArgBinary( void )
370     {
371         return NULL;
372     }
GetArgBinarySize(void)373     size_t GetArgBinarySize( void )
374     {
375         return 0;
376     }
GetArgc(void)377     int GetArgc(void)
378     {
379         return 0;
380     }
GetArgv(int)381     const char* GetArgv( int )
382     {
383         return NULL;
384     }
GetOpt(const char *)385     int GetOpt(const char *)
386     {
387         return -1;
388     }
SetArgumentBuffer(const void *,size_t)389     void SetArgumentBuffer( const void*,  size_t )
390     {
391     }
GetArgumentBuffer(void)392     const void *GetArgumentBuffer(void)
393     {
394         return NULL;
395     }
GetArgumentBufferSize(void)396     size_t GetArgumentBufferSize(void)
397     {
398         return 0;
399     }
GetOptInd(void)400     int GetOptInd( void )
401     {
402         return -1;
403     }
GetOptArg(void)404     const char* GetOptArg( void )
405     {
406         return NULL;
407     }
GetOptOpt(void)408     int GetOptOpt( void )
409     {
410         return -1;
411     }
412 }
413 }
414 }
415 #endif
416