3 * @author Nicolas VIVIEN
6 * @note CopyRight Nicolas VIVIEN
8 * @brief COD debug file parser
9 * RIM's JDE generates several files when you build a COD application.
10 * Indeed, with the COD files for the device, we have a ".debug" file.
11 * This file is usefull to debug an application from JVM.
12 * This tool is a parser to understand these ".debug" files.
15 * - 2009/08/01 : N. VIVIEN
19 * Copyright (C) 2009-2010, Nicolas VIVIEN
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30 * See the GNU General Public License in the COPYING file at the
31 * root directory of this project for more details.
39 #include <sys/types.h>
43 #include "dp_parser.h"
44 #include "dp_codinfo.h"
45 #include "ios_state.h"
49 #define COD_DEBUG_APPNAME_HEADERFIELD 0x0
50 #define COD_DEBUG_UNIQUEID_HEADERFIELD 0x8
52 #define COD_DEBUG_NONE_FIELD 0x0
53 #define COD_DEBUG_BOOLEAN_FIELD 0x1
54 #define COD_DEBUG_BYTE_FIELD 0x2
55 #define COD_DEBUG_CHAR_FIELD 0x3
56 #define COD_DEBUG_SHORT_FIELD 0x4
57 #define COD_DEBUG_INT_FIELD 0x5
58 #define COD_DEBUG_LONG_FIELD 0x6
59 #define COD_DEBUG_CLASS_FIELD 0x7
60 #define COD_DEBUG_ARRAY_FIELD 0x8
61 #define COD_DEBUG_VOID_FIELD 0xA
62 #define COD_DEBUG_DOUBLE_FIELD 0xC
76 #define DEBUG_FILE_EXT ".debug"
79 void SearchDebugFile(DebugFileList
&list
)
86 while( (entry
= readdir(path
)) ) {
89 if (strlen(entry
->d_name
) < strlen(DEBUG_FILE_EXT
))
92 offset
= strlen(entry
->d_name
) - strlen(DEBUG_FILE_EXT
);
94 if (!strcmp(entry
->d_name
+ offset
, DEBUG_FILE_EXT
)) {
95 ifstream
file(entry
->d_name
);
99 // Parse header section
100 info
.ParseHeaderSection(file
);
102 // Add element to list
103 list
.AddElement(info
.GetUniqueId(), info
.GetAppName(), entry
->d_name
);
111 bool LoadDebugInfo(const DebugFileList
&list
, const char *filename
, CodInfo
&info
)
113 if (filename
== NULL
)
116 DebugFileList::const_iterator b
= list
.begin();
118 for( ; b
!= list
.end(); b
++ ) {
119 const DebugFileEntry
&entry
= (*b
);
121 if( entry
.fileName
== filename
) {
122 info
.LoadDebugFile(filename
);
131 bool LoadDebugInfo(const DebugFileList
&list
, const uint32_t uniqueId
, const std::string module
, CodInfo
&info
)
133 DebugFileList::const_iterator b
= list
.begin();
135 for( ; b
!= list
.end(); b
++ ) {
136 const DebugFileEntry
&entry
= (*b
);
138 if ((entry
.uniqueId
== uniqueId
) && (entry
.appName
== module
)) {
139 info
.LoadDebugFile(entry
.fileName
.c_str());
148 // DebugFileList class
149 //------------------------
151 void DebugFileList::AddElement(uint32_t uniqueid
,
152 const std::string
&appname
,
153 const std::string
&filename
)
155 DebugFileEntry entry
;
157 entry
.uniqueId
= uniqueid
;
158 entry
.appName
= appname
;
159 entry
.fileName
= filename
;
165 void DebugFileList::Dump(std::ostream
&os
) const
167 ios_format_state
state(os
);
169 const_iterator i
= begin(), e
= end();
171 os
<< _(" UniqueID ") << "|";
172 os
<< _(" Module Name ") << "|";
173 os
<< _(" File Name ") << endl
;
175 os
<< "------------+";
176 os
<< "--------------------------+";
177 os
<< "--------------------------";
180 for( ; i
!= e
; ++i
) {
186 void DebugFileEntry::Dump(std::ostream
&os
) const
188 ios_format_state
state(os
);
190 os
<< " 0x" << setfill('0') << setw(8) << hex
<< uniqueId
<< " |";
191 os
<< " " << appName
<< setfill(' ') << setw(24) << " |";
192 os
<< " " << fileName
<< endl
;
197 //---------------------------
200 void ClassList::CreateDefaultEntries()
205 entry
.classPath
= "com.rim.resources";
206 entry
.className
= "net_rim_rimsecuridlibRIMResources";
210 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
211 entry
.className
= "RimSecurIDLib";
215 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
216 entry
.className
= "RimDatabaseFullException";
220 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
221 entry
.className
= "RimDecryptFailException";
225 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
226 entry
.className
= "RimDuplicateNameException";
230 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
231 entry
.className
= "RimDuplicateTokenException";
235 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
236 entry
.className
= "RimInvalidParamException";
240 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
241 entry
.className
= "RimSecurIDLib";
245 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
246 entry
.className
= "RimWrongDeviceIDException";
250 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
251 entry
.className
= "RimWrongFormFactorException";
257 //------------------------
259 bool CodInfo::LoadDebugFile(const char *filename
)
263 if (filename
== NULL
)
266 ifstream
file(filename
);
269 ParseHeaderSection(file
);
271 // Parse type area zone
272 ParseTypeSection(file
);
275 field
= ParseInteger(file
); // Read 0x0
276 field
= ParseInteger(file
); // Read 0x1
279 field
= ParseInteger(file
); // Read 0x0
280 field
= ParseInteger(file
); // Read 0x0 or 0xA
283 // Parse ressource area zone
284 ParseResourceSection(file
);
291 uint32_t CodInfo::GetUniqueId()
297 string
CodInfo::GetAppName()
303 // Private API - Section parsing
304 //-------------------------------
306 void CodInfo::ParseHeaderSection(istream
&input
)
310 type
= ParseNextHeaderField(input
);
312 if (type
!= COD_DEBUG_UNIQUEID_HEADERFIELD
)
315 type
= ParseNextHeaderField(input
);
317 if (type
!= COD_DEBUG_APPNAME_HEADERFIELD
)
322 void CodInfo::ParseTypeSection(istream
&input
)
328 // Read number of declared type content into this section
329 nbr
= ParseInteger(input
);
334 while (!input
.eof()) {
335 type
= ParseNextTypeField(input
);
337 if (type
== COD_DEBUG_NONE_FIELD
)
343 // Read again number of declared type content into this section
344 // We have to find the same value
345 check
= ParseInteger(input
);
347 // Checking... this code only exists in __DEBUG_MODE__ only, so
348 // make sure unused variables are always "used"
351 dout("Nbr = " << dec
<< nbr
<< " / Count = " << dec
<< count
<< " / check = " << check
);
355 void CodInfo::ParseResourceSection(istream
&input
)
370 for (int i
=0; i
<10; i
++) {
371 type
= ParseInteger(input
);
373 len
= ParseInteger(input
);
374 name
= ParseString(input
, len
);
376 unknown01
= ParseInteger(input
);
377 unknown02
= ParseInteger(input
);
378 unknown03
= ParseInteger(input
);
380 dout("JDGCodInfo::parseRessource"
381 << "\n Name : " << name
382 << "\n unknown01 : " << hex
<< unknown01
383 << "\n unknown02 : " << hex
<< unknown02
384 << "\n unknown03 : " << hex
<< unknown03
);
388 type
= ParseInteger(input
);
390 len
= ParseInteger(input
);
391 name
= ParseString(input
, len
);
393 unknown01
= ParseInteger(input
);
394 unknown02
= ParseInteger(input
);
395 unknown03
= ParseInteger(input
);
396 unknown04
= ParseInteger(input
);
397 unknown05
= ParseInteger(input
);
398 unknown06
= ParseInteger(input
);
399 unknown07
= ParseInteger(input
);
401 dout("JDGCodInfo::parseRessource"
402 << "\n Name : " << name
403 << "\n unknown01 : " << hex
<< unknown01
404 << "\n unknown02 : " << hex
<< unknown02
405 << "\n unknown03 : " << hex
<< unknown03
406 << "\n unknown04 : " << hex
<< unknown04
407 << "\n unknown05 : " << hex
<< unknown05
408 << "\n unknown06 : " << hex
<< unknown06
409 << "\n unknown07 : " << hex
<< unknown07
);
412 type
= ParseInteger(input
);
414 len
= ParseInteger(input
);
415 name
= ParseString(input
, len
);
417 unknown01
= ParseInteger(input
);
418 unknown02
= ParseInteger(input
);
419 unknown03
= ParseInteger(input
);
420 unknown04
= ParseInteger(input
);
422 dout("JDGCodInfo::parseRessource"
423 << "\n Name : " << name
424 << "\n unknown01 : " << hex
<< unknown01
425 << "\n unknown02 : " << hex
<< unknown02
426 << "\n unknown03 : " << hex
<< unknown03
427 << "\n unknown04 : " << hex
<< unknown04
);
430 type
= ParseInteger(input
);
432 len
= ParseInteger(input
);
433 name
= ParseString(input
, len
);
435 unknown01
= ParseInteger(input
);
436 unknown02
= ParseInteger(input
);
437 unknown03
= ParseInteger(input
);
438 unknown04
= ParseInteger(input
);
439 unknown05
= ParseInteger(input
);
441 dout("JDGCodInfo::parseRessource"
442 << "\n Name : " << name
443 << "\n unknown01 : " << hex
<< unknown01
444 << "\n unknown02 : " << hex
<< unknown02
445 << "\n unknown03 : " << hex
<< unknown03
446 << "\n unknown04 : " << hex
<< unknown04
447 << "\n unknown05 : " << hex
<< unknown05
);
449 // make sure that unused variables are always "used" when
450 // not in __DEBUG_MODE__
463 // Private API - Field parsing
464 //-------------------------------
467 uint32_t CodInfo::ParseNextHeaderField(istream
&input
)
469 uint32_t type
= ParseInteger(input
);
472 case COD_DEBUG_UNIQUEID_HEADERFIELD
:
473 ParseUniqueId(input
);
476 case COD_DEBUG_APPNAME_HEADERFIELD
:
488 uint32_t CodInfo::ParseNextTypeField(istream
&input
)
490 uint32_t type
= ParseInteger(input
);
493 case COD_DEBUG_NONE_FIELD
:
496 case COD_DEBUG_BOOLEAN_FIELD
:
500 case COD_DEBUG_BYTE_FIELD
:
504 case COD_DEBUG_CHAR_FIELD
:
508 case COD_DEBUG_SHORT_FIELD
:
512 case COD_DEBUG_INT_FIELD
:
516 case COD_DEBUG_LONG_FIELD
:
520 case COD_DEBUG_CLASS_FIELD
:
524 case COD_DEBUG_ARRAY_FIELD
:
528 case COD_DEBUG_VOID_FIELD
:
532 case COD_DEBUG_DOUBLE_FIELD
:
537 dout("Type unknown ! " << hex
<< type
);
545 void CodInfo::ParseUniqueId(istream
&input
)
547 uniqueId
= ParseInteger(input
);
551 void CodInfo::ParseAppName(istream
&input
)
553 uint32_t len
= ParseInteger(input
);
555 appName
= ParseString(input
, len
);
559 void CodInfo::ParseBoolean(istream
&input
)
561 uint32_t len
= ParseInteger(input
);
563 string str
= ParseString(input
, len
);
565 dout("JDG::CodInfo::ParseBoolean\n name : " << str
);
569 void CodInfo::ParseByte(istream
&input
)
571 uint32_t len
= ParseInteger(input
);
573 string str
= ParseString(input
, len
);
575 dout("JDG::CodInfo::ParseByte\n name : " << str
);
579 void CodInfo::ParseChar(istream
&input
)
581 uint32_t len
= ParseInteger(input
);
583 string str
= ParseString(input
, len
);
585 dout("JDG::CodInfo::ParseChar\n name : " << str
);
589 void CodInfo::ParseShort(istream
&input
)
591 uint32_t len
= ParseInteger(input
);
593 string str
= ParseString(input
, len
);
595 dout("JDG::CodInfo::ParseShort\n name : " << str
);
599 void CodInfo::ParseInt(istream
&input
)
601 uint32_t len
= ParseInteger(input
);
603 string str
= ParseString(input
, len
);
605 dout("JDG::CodInfo::ParseInt\n name : " << str
);
609 void CodInfo::ParseLong(istream
&input
)
611 uint32_t len
= ParseInteger(input
);
613 string str
= ParseString(input
, len
);
615 dout("JDG::CodInfo::ParseLong\n name : " << str
);
619 void CodInfo::ParseClass(istream
&input
)
625 dout("JDG::CodInfo::ParseClass");
627 len
= ParseInteger(input
);
629 object
.className
= ParseString(input
, len
);
631 object
.type
= ParseInteger(input
);
632 object
.unknown02
= ParseInteger(input
);
633 object
.unknown03
= ParseInteger(input
);
634 object
.id
= ParseInteger(input
);
636 len
= ParseInteger(input
);
639 object
.classPath
= "com.barry." + appName
;
640 else if (len
!= 0xFFFFFF)
641 object
.classPath
= ParseString(input
, len
);
643 len
= ParseInteger(input
);
645 object
.sourceFile
= ParseString(input
, len
);
647 object
.unknown05
= ParseInteger(input
);
648 object
.unknown06
= ParseInteger(input
);
649 object
.unknown07
= ParseInteger(input
);
650 object
.unknown08
= ParseInteger(input
);
652 classList
.push_back(object
);
654 dout("\n name : " << object
.className
655 << "\n path : " << object
.classPath
656 << "\n type : " << hex
<< object
.type
657 << "\n unknown02 : " << hex
<< object
.unknown02
658 << "\n unknown03 : " << hex
<< object
.unknown03
659 << "\n id : " << hex
<< object
.id
660 << "\n source file : " << object
.sourceFile
661 << "\n unknown05 : " << hex
<< object
.unknown05
662 << "\n unknown06 : " << hex
<< object
.unknown06
663 << "\n unknown07 : " << hex
<< object
.unknown07
664 << "\n unknown08 : " << hex
<< object
.unknown08
);
668 void CodInfo::ParseArray(istream
&input
)
670 uint32_t len
= ParseInteger(input
);
672 string str
= ParseString(input
, len
);
674 dout("JDG::CodInfo::ParseArray\n name : " << str
);
678 void CodInfo::ParseVoid(istream
&input
)
680 uint32_t len
= ParseInteger(input
);
682 string str
= ParseString(input
, len
);
684 dout("JDG::CodInfo::ParseVoid\n name : " << str
);
688 void CodInfo::ParseDouble(istream
&input
)
690 uint32_t len
= ParseInteger(input
);
692 string str
= ParseString(input
, len
);
694 dout("JDG::CodInfo::ParseDouble\n name : " << str
);
698 void CodInfo::ParseType2(istream &input) {
700 uint32_t len = ParseInteger(input);
702 string str = ParseString(input, len);
704 dout("Type2 : " << str);
706 value = ParseInteger(input);
707 value = ParseInteger(input);
708 value = ParseInteger(input);
709 value = ParseInteger(input);
710 value = ParseInteger(input);
711 value = ParseInteger(input);