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
);
347 dout("Nbr = " << dec
<< nbr
<< " / Count = " << dec
<< count
<< " / check = " << check
);
351 void CodInfo::ParseResourceSection(istream
&input
)
366 for (int i
=0; i
<10; i
++) {
367 type
= ParseInteger(input
);
369 len
= ParseInteger(input
);
370 name
= ParseString(input
, len
);
372 unknown01
= ParseInteger(input
);
373 unknown02
= ParseInteger(input
);
374 unknown03
= ParseInteger(input
);
376 dout("JDGCodInfo::parseRessource"
377 << "\n Name : " << name
378 << "\n unknown01 : " << hex
<< unknown01
379 << "\n unknown02 : " << hex
<< unknown02
380 << "\n unknown03 : " << hex
<< unknown03
);
384 type
= ParseInteger(input
);
386 len
= ParseInteger(input
);
387 name
= ParseString(input
, len
);
389 unknown01
= ParseInteger(input
);
390 unknown02
= ParseInteger(input
);
391 unknown03
= ParseInteger(input
);
392 unknown04
= ParseInteger(input
);
393 unknown05
= ParseInteger(input
);
394 unknown06
= ParseInteger(input
);
395 unknown07
= ParseInteger(input
);
397 dout("JDGCodInfo::parseRessource"
398 << "\n Name : " << name
399 << "\n unknown01 : " << hex
<< unknown01
400 << "\n unknown02 : " << hex
<< unknown02
401 << "\n unknown03 : " << hex
<< unknown03
402 << "\n unknown04 : " << hex
<< unknown04
403 << "\n unknown05 : " << hex
<< unknown05
404 << "\n unknown06 : " << hex
<< unknown06
405 << "\n unknown07 : " << hex
<< unknown07
);
408 type
= ParseInteger(input
);
410 len
= ParseInteger(input
);
411 name
= ParseString(input
, len
);
413 unknown01
= ParseInteger(input
);
414 unknown02
= ParseInteger(input
);
415 unknown03
= ParseInteger(input
);
416 unknown04
= ParseInteger(input
);
418 dout("JDGCodInfo::parseRessource"
419 << "\n Name : " << name
420 << "\n unknown01 : " << hex
<< unknown01
421 << "\n unknown02 : " << hex
<< unknown02
422 << "\n unknown03 : " << hex
<< unknown03
423 << "\n unknown04 : " << hex
<< unknown04
);
426 type
= ParseInteger(input
);
428 len
= ParseInteger(input
);
429 name
= ParseString(input
, len
);
431 unknown01
= ParseInteger(input
);
432 unknown02
= ParseInteger(input
);
433 unknown03
= ParseInteger(input
);
434 unknown04
= ParseInteger(input
);
435 unknown05
= ParseInteger(input
);
437 dout("JDGCodInfo::parseRessource"
438 << "\n Name : " << name
439 << "\n unknown01 : " << hex
<< unknown01
440 << "\n unknown02 : " << hex
<< unknown02
441 << "\n unknown03 : " << hex
<< unknown03
442 << "\n unknown04 : " << hex
<< unknown04
443 << "\n unknown05 : " << hex
<< unknown05
);
448 // Private API - Field parsing
449 //-------------------------------
452 uint32_t CodInfo::ParseNextHeaderField(istream
&input
)
454 uint32_t type
= ParseInteger(input
);
457 case COD_DEBUG_UNIQUEID_HEADERFIELD
:
458 ParseUniqueId(input
);
461 case COD_DEBUG_APPNAME_HEADERFIELD
:
473 uint32_t CodInfo::ParseNextTypeField(istream
&input
)
475 uint32_t type
= ParseInteger(input
);
478 case COD_DEBUG_NONE_FIELD
:
481 case COD_DEBUG_BOOLEAN_FIELD
:
485 case COD_DEBUG_BYTE_FIELD
:
489 case COD_DEBUG_CHAR_FIELD
:
493 case COD_DEBUG_SHORT_FIELD
:
497 case COD_DEBUG_INT_FIELD
:
501 case COD_DEBUG_LONG_FIELD
:
505 case COD_DEBUG_CLASS_FIELD
:
509 case COD_DEBUG_ARRAY_FIELD
:
513 case COD_DEBUG_VOID_FIELD
:
517 case COD_DEBUG_DOUBLE_FIELD
:
522 dout("Type unknown ! " << hex
<< type
);
530 void CodInfo::ParseUniqueId(istream
&input
)
532 uniqueId
= ParseInteger(input
);
536 void CodInfo::ParseAppName(istream
&input
)
538 uint32_t len
= ParseInteger(input
);
540 appName
= ParseString(input
, len
);
544 void CodInfo::ParseBoolean(istream
&input
)
546 uint32_t len
= ParseInteger(input
);
548 string str
= ParseString(input
, len
);
550 dout("JDG::CodInfo::ParseBoolean\n name : " << str
);
554 void CodInfo::ParseByte(istream
&input
)
556 uint32_t len
= ParseInteger(input
);
558 string str
= ParseString(input
, len
);
560 dout("JDG::CodInfo::ParseByte\n name : " << str
);
564 void CodInfo::ParseChar(istream
&input
)
566 uint32_t len
= ParseInteger(input
);
568 string str
= ParseString(input
, len
);
570 dout("JDG::CodInfo::ParseChar\n name : " << str
);
574 void CodInfo::ParseShort(istream
&input
)
576 uint32_t len
= ParseInteger(input
);
578 string str
= ParseString(input
, len
);
580 dout("JDG::CodInfo::ParseShort\n name : " << str
);
584 void CodInfo::ParseInt(istream
&input
)
586 uint32_t len
= ParseInteger(input
);
588 string str
= ParseString(input
, len
);
590 dout("JDG::CodInfo::ParseInt\n name : " << str
);
594 void CodInfo::ParseLong(istream
&input
)
596 uint32_t len
= ParseInteger(input
);
598 string str
= ParseString(input
, len
);
600 dout("JDG::CodInfo::ParseLong\n name : " << str
);
604 void CodInfo::ParseClass(istream
&input
)
610 dout("JDG::CodInfo::ParseClass");
612 len
= ParseInteger(input
);
614 object
.className
= ParseString(input
, len
);
616 object
.type
= ParseInteger(input
);
617 object
.unknown02
= ParseInteger(input
);
618 object
.unknown03
= ParseInteger(input
);
619 object
.id
= ParseInteger(input
);
621 len
= ParseInteger(input
);
624 object
.classPath
= "com.barry." + appName
;
625 else if (len
!= 0xFFFFFF)
626 object
.classPath
= ParseString(input
, len
);
628 len
= ParseInteger(input
);
630 object
.sourceFile
= ParseString(input
, len
);
632 object
.unknown05
= ParseInteger(input
);
633 object
.unknown06
= ParseInteger(input
);
634 object
.unknown07
= ParseInteger(input
);
635 object
.unknown08
= ParseInteger(input
);
637 classList
.push_back(object
);
639 dout("\n name : " << object
.className
640 << "\n path : " << object
.classPath
641 << "\n type : " << hex
<< object
.type
642 << "\n unknown02 : " << hex
<< object
.unknown02
643 << "\n unknown03 : " << hex
<< object
.unknown03
644 << "\n id : " << hex
<< object
.id
645 << "\n source file : " << object
.sourceFile
646 << "\n unknown05 : " << hex
<< object
.unknown05
647 << "\n unknown06 : " << hex
<< object
.unknown06
648 << "\n unknown07 : " << hex
<< object
.unknown07
649 << "\n unknown08 : " << hex
<< object
.unknown08
);
653 void CodInfo::ParseArray(istream
&input
)
655 uint32_t len
= ParseInteger(input
);
657 string str
= ParseString(input
, len
);
659 dout("JDG::CodInfo::ParseArray\n name : " << str
);
663 void CodInfo::ParseVoid(istream
&input
)
665 uint32_t len
= ParseInteger(input
);
667 string str
= ParseString(input
, len
);
669 dout("JDG::CodInfo::ParseVoid\n name : " << str
);
673 void CodInfo::ParseDouble(istream
&input
)
675 uint32_t len
= ParseInteger(input
);
677 string str
= ParseString(input
, len
);
679 dout("JDG::CodInfo::ParseDouble\n name : " << str
);
683 void CodInfo::ParseType2(istream &input) {
685 uint32_t len = ParseInteger(input);
687 string str = ParseString(input, len);
689 dout("Type2 : " << str);
691 value = ParseInteger(input);
692 value = ParseInteger(input);
693 value = ParseInteger(input);
694 value = ParseInteger(input);
695 value = ParseInteger(input);
696 value = ParseInteger(input);