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.
38 #include <sys/types.h>
42 #include "dp_parser.h"
43 #include "dp_codinfo.h"
44 #include "ios_state.h"
48 #define COD_DEBUG_APPNAME_HEADERFIELD 0x0
49 #define COD_DEBUG_UNIQUEID_HEADERFIELD 0x8
51 #define COD_DEBUG_NONE_FIELD 0x0
52 #define COD_DEBUG_BOOLEAN_FIELD 0x1
53 #define COD_DEBUG_BYTE_FIELD 0x2
54 #define COD_DEBUG_CHAR_FIELD 0x3
55 #define COD_DEBUG_SHORT_FIELD 0x4
56 #define COD_DEBUG_INT_FIELD 0x5
57 #define COD_DEBUG_LONG_FIELD 0x6
58 #define COD_DEBUG_CLASS_FIELD 0x7
59 #define COD_DEBUG_ARRAY_FIELD 0x8
60 #define COD_DEBUG_VOID_FIELD 0xA
61 #define COD_DEBUG_DOUBLE_FIELD 0xC
75 #define DEBUG_FILE_EXT ".debug"
78 void SearchDebugFile(DebugFileList
&list
)
85 while( (entry
= readdir(path
)) ) {
88 if (strlen(entry
->d_name
) < strlen(DEBUG_FILE_EXT
))
91 offset
= strlen(entry
->d_name
) - strlen(DEBUG_FILE_EXT
);
93 if (!strcmp(entry
->d_name
+ offset
, DEBUG_FILE_EXT
)) {
94 ifstream
file(entry
->d_name
);
98 // Parse header section
99 info
.ParseHeaderSection(file
);
101 // Add element to list
102 list
.AddElement(info
.GetUniqueId(), info
.GetAppName(), entry
->d_name
);
110 bool LoadDebugInfo(const DebugFileList
&list
, const char *filename
, CodInfo
&info
)
112 if (filename
== NULL
)
115 DebugFileList::const_iterator b
= list
.begin();
117 for( ; b
!= list
.end(); b
++ ) {
118 const DebugFileEntry
&entry
= (*b
);
120 if( entry
.fileName
== filename
) {
121 info
.LoadDebugFile(filename
);
130 bool LoadDebugInfo(const DebugFileList
&list
, const uint32_t uniqueId
, const std::string module
, CodInfo
&info
)
132 DebugFileList::const_iterator b
= list
.begin();
134 for( ; b
!= list
.end(); b
++ ) {
135 const DebugFileEntry
&entry
= (*b
);
137 if ((entry
.uniqueId
== uniqueId
) && (entry
.appName
== module
)) {
138 info
.LoadDebugFile(entry
.fileName
.c_str());
147 // DebugFileList class
148 //------------------------
150 void DebugFileList::AddElement(uint32_t uniqueid
,
151 const std::string
&appname
,
152 const std::string
&filename
)
154 DebugFileEntry entry
;
156 entry
.uniqueId
= uniqueid
;
157 entry
.appName
= appname
;
158 entry
.fileName
= filename
;
164 void DebugFileList::Dump(std::ostream
&os
) const
166 ios_format_state
state(os
);
168 const_iterator i
= begin(), e
= end();
170 os
<< " UniqueID " << "|";
171 os
<< " Module Name " << "|";
172 os
<< " File Name " << endl
;
174 os
<< "------------+";
175 os
<< "--------------------------+";
176 os
<< "--------------------------";
179 for( ; i
!= e
; ++i
) {
185 void DebugFileEntry::Dump(std::ostream
&os
) const
187 ios_format_state
state(os
);
189 os
<< " 0x" << setfill('0') << setw(8) << hex
<< uniqueId
<< " |";
190 os
<< " " << appName
<< setfill(' ') << setw(24) << " |";
191 os
<< " " << fileName
<< endl
;
196 //---------------------------
199 void ClassList::CreateDefaultEntries()
204 entry
.classPath
= "com.rim.resources";
205 entry
.className
= "net_rim_rimsecuridlibRIMResources";
209 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
210 entry
.className
= "RimSecurIDLib";
214 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
215 entry
.className
= "RimDatabaseFullException";
219 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
220 entry
.className
= "RimDecryptFailException";
224 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
225 entry
.className
= "RimDuplicateNameException";
229 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
230 entry
.className
= "RimDuplicateTokenException";
234 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
235 entry
.className
= "RimInvalidParamException";
239 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
240 entry
.className
= "RimSecurIDLib";
244 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
245 entry
.className
= "RimWrongDeviceIDException";
249 entry
.classPath
= "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
250 entry
.className
= "RimWrongFormFactorException";
256 //------------------------
258 bool CodInfo::LoadDebugFile(const char *filename
)
262 if (filename
== NULL
)
265 ifstream
file(filename
);
268 ParseHeaderSection(file
);
270 // Parse type area zone
271 ParseTypeSection(file
);
274 field
= ParseInteger(file
); // Read 0x0
275 field
= ParseInteger(file
); // Read 0x1
278 field
= ParseInteger(file
); // Read 0x0
279 field
= ParseInteger(file
); // Read 0x0 or 0xA
282 // Parse ressource area zone
283 ParseResourceSection(file
);
290 uint32_t CodInfo::GetUniqueId()
296 string
CodInfo::GetAppName()
302 // Private API - Section parsing
303 //-------------------------------
305 void CodInfo::ParseHeaderSection(istream
&input
)
309 type
= ParseNextHeaderField(input
);
311 if (type
!= COD_DEBUG_UNIQUEID_HEADERFIELD
)
314 type
= ParseNextHeaderField(input
);
316 if (type
!= COD_DEBUG_APPNAME_HEADERFIELD
)
321 void CodInfo::ParseTypeSection(istream
&input
)
327 // Read number of declared type content into this section
328 nbr
= ParseInteger(input
);
333 while (!input
.eof()) {
334 type
= ParseNextTypeField(input
);
336 if (type
== COD_DEBUG_NONE_FIELD
)
342 // Read again number of declared type content into this section
343 // We have to find the same value
344 check
= ParseInteger(input
);
346 // Checking... this code only exists in __DEBUG_MODE__ only, so
347 // make sure unused variables are always "used"
350 dout("Nbr = " << dec
<< nbr
<< " / Count = " << dec
<< count
<< " / check = " << check
);
354 void CodInfo::ParseResourceSection(istream
&input
)
369 for (int i
=0; i
<10; i
++) {
370 type
= ParseInteger(input
);
372 len
= ParseInteger(input
);
373 name
= ParseString(input
, len
);
375 unknown01
= ParseInteger(input
);
376 unknown02
= ParseInteger(input
);
377 unknown03
= ParseInteger(input
);
379 dout("JDGCodInfo::parseRessource"
380 << "\n Name : " << name
381 << "\n unknown01 : " << hex
<< unknown01
382 << "\n unknown02 : " << hex
<< unknown02
383 << "\n unknown03 : " << hex
<< unknown03
);
387 type
= ParseInteger(input
);
389 len
= ParseInteger(input
);
390 name
= ParseString(input
, len
);
392 unknown01
= ParseInteger(input
);
393 unknown02
= ParseInteger(input
);
394 unknown03
= ParseInteger(input
);
395 unknown04
= ParseInteger(input
);
396 unknown05
= ParseInteger(input
);
397 unknown06
= ParseInteger(input
);
398 unknown07
= ParseInteger(input
);
400 dout("JDGCodInfo::parseRessource"
401 << "\n Name : " << name
402 << "\n unknown01 : " << hex
<< unknown01
403 << "\n unknown02 : " << hex
<< unknown02
404 << "\n unknown03 : " << hex
<< unknown03
405 << "\n unknown04 : " << hex
<< unknown04
406 << "\n unknown05 : " << hex
<< unknown05
407 << "\n unknown06 : " << hex
<< unknown06
408 << "\n unknown07 : " << hex
<< unknown07
);
411 type
= ParseInteger(input
);
413 len
= ParseInteger(input
);
414 name
= ParseString(input
, len
);
416 unknown01
= ParseInteger(input
);
417 unknown02
= ParseInteger(input
);
418 unknown03
= ParseInteger(input
);
419 unknown04
= ParseInteger(input
);
421 dout("JDGCodInfo::parseRessource"
422 << "\n Name : " << name
423 << "\n unknown01 : " << hex
<< unknown01
424 << "\n unknown02 : " << hex
<< unknown02
425 << "\n unknown03 : " << hex
<< unknown03
426 << "\n unknown04 : " << hex
<< unknown04
);
429 type
= ParseInteger(input
);
431 len
= ParseInteger(input
);
432 name
= ParseString(input
, len
);
434 unknown01
= ParseInteger(input
);
435 unknown02
= ParseInteger(input
);
436 unknown03
= ParseInteger(input
);
437 unknown04
= ParseInteger(input
);
438 unknown05
= ParseInteger(input
);
440 dout("JDGCodInfo::parseRessource"
441 << "\n Name : " << name
442 << "\n unknown01 : " << hex
<< unknown01
443 << "\n unknown02 : " << hex
<< unknown02
444 << "\n unknown03 : " << hex
<< unknown03
445 << "\n unknown04 : " << hex
<< unknown04
446 << "\n unknown05 : " << hex
<< unknown05
);
448 // make sure that unused variables are always "used" when
449 // not in __DEBUG_MODE__
462 // Private API - Field parsing
463 //-------------------------------
466 uint32_t CodInfo::ParseNextHeaderField(istream
&input
)
468 uint32_t type
= ParseInteger(input
);
471 case COD_DEBUG_UNIQUEID_HEADERFIELD
:
472 ParseUniqueId(input
);
475 case COD_DEBUG_APPNAME_HEADERFIELD
:
487 uint32_t CodInfo::ParseNextTypeField(istream
&input
)
489 uint32_t type
= ParseInteger(input
);
492 case COD_DEBUG_NONE_FIELD
:
495 case COD_DEBUG_BOOLEAN_FIELD
:
499 case COD_DEBUG_BYTE_FIELD
:
503 case COD_DEBUG_CHAR_FIELD
:
507 case COD_DEBUG_SHORT_FIELD
:
511 case COD_DEBUG_INT_FIELD
:
515 case COD_DEBUG_LONG_FIELD
:
519 case COD_DEBUG_CLASS_FIELD
:
523 case COD_DEBUG_ARRAY_FIELD
:
527 case COD_DEBUG_VOID_FIELD
:
531 case COD_DEBUG_DOUBLE_FIELD
:
536 dout("Type unknown ! " << hex
<< type
);
544 void CodInfo::ParseUniqueId(istream
&input
)
546 uniqueId
= ParseInteger(input
);
550 void CodInfo::ParseAppName(istream
&input
)
552 uint32_t len
= ParseInteger(input
);
554 appName
= ParseString(input
, len
);
558 void CodInfo::ParseBoolean(istream
&input
)
560 uint32_t len
= ParseInteger(input
);
562 string str
= ParseString(input
, len
);
564 dout("JDG::CodInfo::ParseBoolean\n name : " << str
);
568 void CodInfo::ParseByte(istream
&input
)
570 uint32_t len
= ParseInteger(input
);
572 string str
= ParseString(input
, len
);
574 dout("JDG::CodInfo::ParseByte\n name : " << str
);
578 void CodInfo::ParseChar(istream
&input
)
580 uint32_t len
= ParseInteger(input
);
582 string str
= ParseString(input
, len
);
584 dout("JDG::CodInfo::ParseChar\n name : " << str
);
588 void CodInfo::ParseShort(istream
&input
)
590 uint32_t len
= ParseInteger(input
);
592 string str
= ParseString(input
, len
);
594 dout("JDG::CodInfo::ParseShort\n name : " << str
);
598 void CodInfo::ParseInt(istream
&input
)
600 uint32_t len
= ParseInteger(input
);
602 string str
= ParseString(input
, len
);
604 dout("JDG::CodInfo::ParseInt\n name : " << str
);
608 void CodInfo::ParseLong(istream
&input
)
610 uint32_t len
= ParseInteger(input
);
612 string str
= ParseString(input
, len
);
614 dout("JDG::CodInfo::ParseLong\n name : " << str
);
618 void CodInfo::ParseClass(istream
&input
)
624 dout("JDG::CodInfo::ParseClass");
626 len
= ParseInteger(input
);
628 object
.className
= ParseString(input
, len
);
630 object
.type
= ParseInteger(input
);
631 object
.unknown02
= ParseInteger(input
);
632 object
.unknown03
= ParseInteger(input
);
633 object
.id
= ParseInteger(input
);
635 len
= ParseInteger(input
);
638 object
.classPath
= "com.barry." + appName
;
639 else if (len
!= 0xFFFFFF)
640 object
.classPath
= ParseString(input
, len
);
642 len
= ParseInteger(input
);
644 object
.sourceFile
= ParseString(input
, len
);
646 object
.unknown05
= ParseInteger(input
);
647 object
.unknown06
= ParseInteger(input
);
648 object
.unknown07
= ParseInteger(input
);
649 object
.unknown08
= ParseInteger(input
);
651 classList
.push_back(object
);
653 dout("\n name : " << object
.className
654 << "\n path : " << object
.classPath
655 << "\n type : " << hex
<< object
.type
656 << "\n unknown02 : " << hex
<< object
.unknown02
657 << "\n unknown03 : " << hex
<< object
.unknown03
658 << "\n id : " << hex
<< object
.id
659 << "\n source file : " << object
.sourceFile
660 << "\n unknown05 : " << hex
<< object
.unknown05
661 << "\n unknown06 : " << hex
<< object
.unknown06
662 << "\n unknown07 : " << hex
<< object
.unknown07
663 << "\n unknown08 : " << hex
<< object
.unknown08
);
667 void CodInfo::ParseArray(istream
&input
)
669 uint32_t len
= ParseInteger(input
);
671 string str
= ParseString(input
, len
);
673 dout("JDG::CodInfo::ParseArray\n name : " << str
);
677 void CodInfo::ParseVoid(istream
&input
)
679 uint32_t len
= ParseInteger(input
);
681 string str
= ParseString(input
, len
);
683 dout("JDG::CodInfo::ParseVoid\n name : " << str
);
687 void CodInfo::ParseDouble(istream
&input
)
689 uint32_t len
= ParseInteger(input
);
691 string str
= ParseString(input
, len
);
693 dout("JDG::CodInfo::ParseDouble\n name : " << str
);
697 void CodInfo::ParseType2(istream &input) {
699 uint32_t len = ParseInteger(input);
701 string str = ParseString(input, len);
703 dout("Type2 : " << str);
705 value = ParseInteger(input);
706 value = ParseInteger(input);
707 value = ParseInteger(input);
708 value = ParseInteger(input);
709 value = ParseInteger(input);
710 value = ParseInteger(input);