# dp_codinfo.cc

Go to the documentation of this file.

    00001 /**
    00002  * @file dp_codinfo.cc
    00003  * @author Nicolas VIVIEN
    00004  * @date 2009-08-01
    00005  *
    00006  * @note CopyRight Nicolas VIVIEN
    00007  *
    00008  * @brief COD debug file parser
    00009  *   RIM's JDE generates several files when you build a COD application.
    00010  *   Indeed, with the COD files for the device, we have a ".debug" file.
    00011  *   This file is usefull to debug an application from JVM.
    00012  *   This tool is a parser to understand these ".debug" files.
    00013  *
    00014  * @par Modifications
    00015  *   - 2009/08/01 : N. VIVIEN
    00016  *     - First release
    00017  *
    00018  * @par Licences
    00019  *   Copyright (C) 2009-2010, Nicolas VIVIEN
    00020  *
    00021  *   This program is free software; you can redistribute it and/or modify
    00022  *   it under the terms of the GNU General Public License as published by
    00023  *   the Free Software Foundation; either version 2 of the License, or
    00024  *   (at your option) any later version.
    00025  *
    00026  *   This program is distributed in the hope that it will be useful,
    00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00029  *
    00030  *   See the GNU General Public License in the COPYING file at the
    00031  *   root directory of this project for more details.
    00032  */
    00033
    00034
    00035 #include <fstream>
    00036 #include <iomanip>
    00037
    00038 #include <sys/types.h>
    00039 #include <dirent.h>
    00040 #include <string.h>
    00041
    00042 #include "dp_parser.h"
    00043 #include "dp_codinfo.h"
    00044 #include "debug.h"
    00045
    00046
    00047 #define COD_DEBUG_APPNAME_HEADERFIELD           0x0
    00048 #define COD_DEBUG_UNIQUEID_HEADERFIELD          0x8
    00049
    00050 #define COD_DEBUG_NONE_FIELD                    0x0
    00051 #define COD_DEBUG_BOOLEAN_FIELD                 0x1
    00052 #define COD_DEBUG_BYTE_FIELD                    0x2
    00053 #define COD_DEBUG_CHAR_FIELD                    0x3
    00054 #define COD_DEBUG_SHORT_FIELD                   0x4
    00055 #define COD_DEBUG_INT_FIELD                     0x5
    00056 #define COD_DEBUG_LONG_FIELD                    0x6
    00057 #define COD_DEBUG_CLASS_FIELD                   0x7
    00058 #define COD_DEBUG_ARRAY_FIELD                   0x8
    00059 #define COD_DEBUG_VOID_FIELD                    0xA
    00060 #define COD_DEBUG_DOUBLE_FIELD                  0xC
    00061
    00062
    00063 using namespace std;
    00064
    00065
    00066 namespace Barry {
    00067
    00068 namespace JDG {
    00069
    00070
    00071 // Public API
    00072 //------------
    00073
    00074 #define DEBUG_FILE_EXT          ".debug"
    00075
    00076
    00077 void SearchDebugFile(DebugFileList &list)
    00078 {
    00079         DIR *path;
    00080         struct dirent *entry;
    00081
    00082         path = opendir(".");
    00083
    00084         while( (entry = readdir(path)) ) {
    00085                 int offset;
    00086
    00087                 if (strlen(entry->d_name) < strlen(DEBUG_FILE_EXT))
    00088                         continue;
    00089
    00090                 offset = strlen(entry->d_name) - strlen(DEBUG_FILE_EXT);
    00091
    00092                 if (!strcmp(entry->d_name + offset, DEBUG_FILE_EXT)) {
    00093                         ifstream file(entry->d_name);
    00094
    00095                         CodInfo info;
    00096
    00097                         // Parse header section
    00098                         info.ParseHeaderSection(file);
    00099
    00100                         // Add element to list
    00101                         list.AddElement(info.GetUniqueId(), info.GetAppName(), entry->d_name);
    00102                 }
    00103         }
    00104
    00105         closedir(path);
    00106 }
    00107
    00108
    00109 bool LoadDebugInfo(const DebugFileList &list, const char *filename, CodInfo &info)
    00110 {
    00111         if (filename == NULL)
    00112                 return false;
    00113
    00114         DebugFileList::const_iterator b = list.begin();
    00115
    00116         for( ; b != list.end(); b++ ) {
    00117                 const DebugFileEntry &entry = (*b);
    00118
    00119                 if( entry.fileName == filename ) {
    00120                         info.LoadDebugFile(filename);
    00121                         return true;
    00122                 }
    00123         }
    00124
    00125         return false;
    00126 }
    00127
    00128
    00129 bool LoadDebugInfo(const DebugFileList &list, const uint32_t uniqueId, const std::string module, CodInfo &info)
    00130 {
    00131         DebugFileList::const_iterator b = list.begin();
    00132
    00133         for( ; b != list.end(); b++ ) {
    00134                 const DebugFileEntry &entry = (*b);
    00135
    00136                 if ((entry.uniqueId == uniqueId) && (entry.appName == module)) {
    00137                         info.LoadDebugFile(entry.fileName.c_str());
    00138                         return true;
    00139                 }
    00140         }
    00141
    00142         return false;
    00143 }
    00144
    00145
    00146 // DebugFileList class
    00147 //------------------------
    00148
    00149 void DebugFileList::AddElement(uint32_t uniqueid,
    00150                                 const std::string &appname,
    00151                                 const std::string &filename)
    00152 {
    00153         DebugFileEntry entry;
    00154
    00155         entry.uniqueId = uniqueid;
    00156         entry.appName = appname;
    00157         entry.fileName = filename;
    00158
    00159         push_back(entry);
    00160 }
    00161
    00162
    00163 void DebugFileList::Dump(std::ostream &os) const
    00164 {
    00165         const_iterator i = begin(), e = end();
    00166
    00167         os << "  UniqueID  " << "|";
    00168         os << "        Module Name       " << "|";
    00169         os << "         File Name        " << endl;
    00170
    00171         os << "------------+";
    00172         os << "--------------------------+";
    00173         os << "--------------------------";
    00174         os << endl;
    00175
    00176         for( ; i != e; ++i ) {
    00177                 (*i).Dump(os);
    00178         }
    00179 }
    00180
    00181
    00182 void DebugFileEntry::Dump(std::ostream &os) const
    00183 {
    00184         os << " 0x" << setfill('0') << setw(8) << hex << uniqueId << " |";
    00185         os << " " << appName << setfill(' ') << setw(24) << " |";
    00186         os << " " << fileName << endl;
    00187 }
    00188
    00189
    00190 // ClassList class
    00191 //---------------------------
    00192
    00193
    00194 void ClassList::CreateDefaultEntries()
    00195 {
    00196         ClassEntry entry;
    00197
    00198         // 1
    00199         entry.classPath = "com.rim.resources";
    00200         entry.className = "net_rim_rimsecuridlibRIMResources";
    00201         push_back(entry);
    00202
    00203         // 2
    00204         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00205         entry.className = "RimSecurIDLib";
    00206         push_back(entry);
    00207
    00208         // 3
    00209         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00210         entry.className = "RimDatabaseFullException";
    00211         push_back(entry);
    00212
    00213         // 4
    00214         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00215         entry.className = "RimDecryptFailException";
    00216         push_back(entry);
    00217
    00218         // 5
    00219         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00220         entry.className = "RimDuplicateNameException";
    00221         push_back(entry);
    00222
    00223         // 6
    00224         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00225         entry.className = "RimDuplicateTokenException";
    00226         push_back(entry);
    00227
    00228         // 7
    00229         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00230         entry.className = "RimInvalidParamException";
    00231         push_back(entry);
    00232
    00233         // 8
    00234         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00235         entry.className = "RimSecurIDLib";
    00236         push_back(entry);
    00237
    00238         // 9
    00239         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00240         entry.className = "RimWrongDeviceIDException";
    00241         push_back(entry);
    00242
    00243         // 10
    00244         entry.classPath = "net.rim.device.cldc.impl.softtoken.rimsecuridlib";
    00245         entry.className = "RimWrongFormFactorException";
    00246         push_back(entry);
    00247 }
    00248
    00249
    00250 // CodInfo class
    00251 //------------------------
    00252
    00253 bool CodInfo::LoadDebugFile(const char *filename)
    00254 {
    00255         uint32_t field;
    00256
    00257         if (filename == NULL)
    00258                 return false;
    00259
    00260         ifstream file(filename);
    00261
    00262         // Parse header file
    00263         ParseHeaderSection(file);
    00264
    00265         // Parse type area zone
    00266         ParseTypeSection(file);
    00267
    00268         // FIXME : ???
    00269         field = ParseInteger(file); // Read 0x0
    00270         field = ParseInteger(file); // Read 0x1
    00271
    00272         // FIXME : ???
    00273         field = ParseInteger(file); // Read 0x0
    00274         field = ParseInteger(file); // Read 0x0 or 0xA
    00275
    00276         if (field == 0xA) {
    00277                 // Parse ressource area zone
    00278                 ParseResourceSection(file);
    00279         }
    00280
    00281         return true;
    00282 }
    00283
    00284
    00285 uint32_t CodInfo::GetUniqueId()
    00286 {
    00287         return uniqueId;
    00288 }
    00289
    00290
    00291 string CodInfo::GetAppName()
    00292 {
    00293         return appName;
    00294 }
    00295
    00296
    00297 // Private API - Section parsing
    00298 //-------------------------------
    00299
    00300 void CodInfo::ParseHeaderSection(istream &input)
    00301 {
    00302         uint32_t type;
    00303
    00304         type = ParseNextHeaderField(input);
    00305
    00306         if (type != COD_DEBUG_UNIQUEID_HEADERFIELD)
    00307                 return;
    00308
    00309         type = ParseNextHeaderField(input);
    00310
    00311         if (type != COD_DEBUG_APPNAME_HEADERFIELD)
    00312                 return;
    00313 }
    00314
    00315
    00316 void CodInfo::ParseTypeSection(istream &input)
    00317 {
    00318         uint32_t type;
    00319         uint32_t count;
    00320         uint32_t nbr, check;
    00321
    00322         // Read number of declared type content into this section
    00323         nbr = ParseInteger(input);
    00324
    00325         // Read each object
    00326         count = 0;
    00327
    00328         while (!input.eof()) {
    00329                 type = ParseNextTypeField(input);
    00330
    00331                 if (type == COD_DEBUG_NONE_FIELD)
    00332                         break;
    00333
    00334                 count++;
    00335         }
    00336
    00337         // Read again number of declared type content into this section
    00338         // We have to find the same value
    00339         check = ParseInteger(input);
    00340
    00341         // Checking...
    00342         dout("Nbr = " << dec << nbr << " / Count = " << dec << count << " / check = " << check);
    00343 }
    00344
    00345
    00346 void CodInfo::ParseResourceSection(istream &input)
    00347 {
    00348         uint32_t len;
    00349         uint32_t type;
    00350         uint32_t unknown01;
    00351         uint32_t unknown02;
    00352         uint32_t unknown03;
    00353         uint32_t unknown04;
    00354         uint32_t unknown05;
    00355         uint32_t unknown06;
    00356         uint32_t unknown07;
    00357
    00358         string name;
    00359
    00360         // type = 1
    00361         for (int i=0; i<10; i++) {
    00362                 type = ParseInteger(input);
    00363
    00364                 len = ParseInteger(input);
    00365                 name = ParseString(input, len);
    00366
    00367                 unknown01 = ParseInteger(input);
    00368                 unknown02 = ParseInteger(input);
    00369                 unknown03 = ParseInteger(input);
    00370
    00371                 dout("JDGCodInfo::parseRessource"
    00372                         << "\n  Name : " << name
    00373                         << "\n  unknown01 : " << hex << unknown01
    00374                         << "\n  unknown02 : " << hex << unknown02
    00375                         << "\n  unknown03 : " << hex << unknown03);
    00376         }
    00377
    00378         // type = 2
    00379         type = ParseInteger(input);
    00380
    00381         len = ParseInteger(input);
    00382         name = ParseString(input, len);
    00383
    00384         unknown01 = ParseInteger(input);
    00385         unknown02 = ParseInteger(input);
    00386         unknown03 = ParseInteger(input);
    00387         unknown04 = ParseInteger(input);
    00388         unknown05 = ParseInteger(input);
    00389         unknown06 = ParseInteger(input);
    00390         unknown07 = ParseInteger(input);
    00391
    00392         dout("JDGCodInfo::parseRessource"
    00393                 << "\n  Name : " << name
    00394                 << "\n  unknown01 : " << hex << unknown01
    00395                 << "\n  unknown02 : " << hex << unknown02
    00396                 << "\n  unknown03 : " << hex << unknown03
    00397                 << "\n  unknown04 : " << hex << unknown04
    00398                 << "\n  unknown05 : " << hex << unknown05
    00399                 << "\n  unknown06 : " << hex << unknown06
    00400                 << "\n  unknown07 : " << hex << unknown07);
    00401
    00402         // type = 1
    00403         type = ParseInteger(input);
    00404
    00405         len = ParseInteger(input);
    00406         name = ParseString(input, len);
    00407
    00408         unknown01 = ParseInteger(input);
    00409         unknown02 = ParseInteger(input);
    00410         unknown03 = ParseInteger(input);
    00411         unknown04 = ParseInteger(input);
    00412
    00413         dout("JDGCodInfo::parseRessource"
    00414                 << "\n  Name : " << name
    00415                 << "\n  unknown01 : " << hex << unknown01
    00416                 << "\n  unknown02 : " << hex << unknown02
    00417                 << "\n  unknown03 : " << hex << unknown03
    00418                 << "\n  unknown04 : " << hex << unknown04);
    00419
    00420         // type = 0
    00421         type = ParseInteger(input);
    00422
    00423         len = ParseInteger(input);
    00424         name = ParseString(input, len);
    00425
    00426         unknown01 = ParseInteger(input);
    00427         unknown02 = ParseInteger(input);
    00428         unknown03 = ParseInteger(input);
    00429         unknown04 = ParseInteger(input);
    00430         unknown05 = ParseInteger(input);
    00431
    00432         dout("JDGCodInfo::parseRessource"
    00433                 << "\n  Name : " << name
    00434                 << "\n  unknown01 : " << hex << unknown01
    00435                 << "\n  unknown02 : " << hex << unknown02
    00436                 << "\n  unknown03 : " << hex << unknown03
    00437                 << "\n  unknown04 : " << hex << unknown04
    00438                 << "\n  unknown05 : " << hex << unknown05);
    00439 }
    00440
    00441
    00442
    00443 // Private API - Field parsing
    00444 //-------------------------------
    00445
    00446
    00447 uint32_t CodInfo::ParseNextHeaderField(istream &input)
    00448 {
    00449         uint32_t type = ParseInteger(input);
    00450
    00451         switch (type) {
    00452         case COD_DEBUG_UNIQUEID_HEADERFIELD:
    00453                 ParseUniqueId(input);
    00454                 break;
    00455
    00456         case COD_DEBUG_APPNAME_HEADERFIELD:
    00457                 ParseAppName(input);
    00458                 break;
    00459
    00460         default:
    00461                 type = 0xFFFFFFFF;
    00462         }
    00463
    00464         return type;
    00465 }
    00466
    00467
    00468 uint32_t CodInfo::ParseNextTypeField(istream &input)
    00469 {
    00470         uint32_t type = ParseInteger(input);
    00471
    00472         switch (type) {
    00473         case COD_DEBUG_NONE_FIELD:
    00474                 break;
    00475
    00476         case COD_DEBUG_BOOLEAN_FIELD:
    00477                 ParseBoolean(input);
    00478                 break;
    00479
    00480         case COD_DEBUG_BYTE_FIELD:
    00481                 ParseByte(input);
    00482                 break;
    00483
    00484         case COD_DEBUG_CHAR_FIELD:
    00485                 ParseChar(input);
    00486                 break;
    00487
    00488         case COD_DEBUG_SHORT_FIELD:
    00489                 ParseShort(input);
    00490                 break;
    00491
    00492         case COD_DEBUG_INT_FIELD:
    00493                 ParseInt(input);
    00494                 break;
    00495
    00496         case COD_DEBUG_LONG_FIELD:
    00497                 ParseLong(input);
    00498                 break;
    00499
    00500         case COD_DEBUG_CLASS_FIELD:
    00501                 ParseClass(input);
    00502                 break;
    00503
    00504         case COD_DEBUG_ARRAY_FIELD:
    00505                 ParseArray(input);
    00506                 break;
    00507
    00508         case COD_DEBUG_VOID_FIELD:
    00509                 ParseVoid(input);
    00510                 break;
    00511
    00512         case COD_DEBUG_DOUBLE_FIELD:
    00513                 ParseDouble(input);
    00514                 break;
    00515
    00516         default:
    00517                 dout("Type unknown ! " << hex << type);
    00518                 type = 0xFFFFFFFF;
    00519         }
    00520
    00521         return type;
    00522 }
    00523
    00524
    00525 void CodInfo::ParseUniqueId(istream &input)
    00526 {
    00527         uniqueId = ParseInteger(input);
    00528 }
    00529
    00530
    00531 void CodInfo::ParseAppName(istream &input)
    00532 {
    00533         uint32_t len = ParseInteger(input);
    00534
    00535         appName = ParseString(input, len);
    00536 }
    00537
    00538
    00539 void CodInfo::ParseBoolean(istream &input)
    00540 {
    00541         uint32_t len  = ParseInteger(input);
    00542
    00543         string str = ParseString(input, len);
    00544
    00545         dout("JDG::CodInfo::ParseBoolean\n  name : " << str);
    00546 }
    00547
    00548
    00549 void CodInfo::ParseByte(istream &input)
    00550 {
    00551         uint32_t len  = ParseInteger(input);
    00552
    00553         string str = ParseString(input, len);
    00554
    00555         dout("JDG::CodInfo::ParseByte\n  name : " << str);
    00556 }
    00557
    00558
    00559 void CodInfo::ParseChar(istream &input)
    00560 {
    00561         uint32_t len  = ParseInteger(input);
    00562
    00563         string str = ParseString(input, len);
    00564
    00565         dout("JDG::CodInfo::ParseChar\n  name : " << str);
    00566 }
    00567
    00568
    00569 void CodInfo::ParseShort(istream &input)
    00570 {
    00571         uint32_t len  = ParseInteger(input);
    00572
    00573         string str = ParseString(input, len);
    00574
    00575         dout("JDG::CodInfo::ParseShort\n  name : " << str);
    00576 }
    00577
    00578
    00579 void CodInfo::ParseInt(istream &input)
    00580 {
    00581         uint32_t len  = ParseInteger(input);
    00582
    00583         string str = ParseString(input, len);
    00584
    00585         dout("JDG::CodInfo::ParseInt\n  name : " << str);
    00586 }
    00587
    00588
    00589 void CodInfo::ParseLong(istream &input)
    00590 {
    00591         uint32_t len  = ParseInteger(input);
    00592
    00593         string str = ParseString(input, len);
    00594
    00595         dout("JDG::CodInfo::ParseLong\n  name : " << str);
    00596 }
    00597
    00598
    00599 void CodInfo::ParseClass(istream &input)
    00600 {
    00601         uint32_t len;
    00602
    00603         ClassEntry object;
    00604
    00605         dout("JDG::CodInfo::ParseClass");
    00606
    00607         len  = ParseInteger(input);
    00608
    00609         object.className = ParseString(input, len);
    00610
    00611         object.type = ParseInteger(input);
    00612         object.unknown02 = ParseInteger(input);
    00613         object.unknown03 = ParseInteger(input);
    00614         object.id = ParseInteger(input);
    00615
    00616         len  = ParseInteger(input);
    00617
    00618         if (len == 0)
    00619                 object.classPath = "com.barry." + appName;
    00620         else if (len != 0xFFFFFF)
    00621                 object.classPath = ParseString(input, len);
    00622
    00623         len  = ParseInteger(input);
    00624
    00625         object.sourceFile = ParseString(input, len);
    00626
    00627         object.unknown05 = ParseInteger(input);
    00628         object.unknown06 = ParseInteger(input);
    00629         object.unknown07 = ParseInteger(input);
    00630         object.unknown08 = ParseInteger(input);
    00631
    00632         classList.push_back(object);
    00633
    00634         dout("\n  name : " << object.className
    00635                 << "\n  path : " << object.classPath
    00636                 << "\n  type : " << hex << object.type
    00637                 << "\n  unknown02 : " << hex << object.unknown02
    00638                 << "\n  unknown03 : " << hex << object.unknown03
    00639                 << "\n  id : " << hex << object.id
    00640                 << "\n  source file : " << object.sourceFile
    00641                 << "\n  unknown05 : " << hex << object.unknown05
    00642                 << "\n  unknown06 : " << hex << object.unknown06
    00643                 << "\n  unknown07 : " << hex << object.unknown07
    00644                 << "\n  unknown08 : " << hex << object.unknown08);
    00645 }
    00646
    00647
    00648 void CodInfo::ParseArray(istream &input)
    00649 {
    00650         uint32_t len  = ParseInteger(input);
    00651
    00652         string str = ParseString(input, len);
    00653
    00654         dout("JDG::CodInfo::ParseArray\n  name : " << str);
    00655 }
    00656
    00657
    00658 void CodInfo::ParseVoid(istream &input)
    00659 {
    00660         uint32_t len  = ParseInteger(input);
    00661
    00662         string str = ParseString(input, len);
    00663
    00664         dout("JDG::CodInfo::ParseVoid\n  name : " << str);
    00665 }
    00666
    00667
    00668 void CodInfo::ParseDouble(istream &input)
    00669 {
    00670         uint32_t len  = ParseInteger(input);
    00671
    00672         string str = ParseString(input, len);
    00673
    00674         dout("JDG::CodInfo::ParseDouble\n  name : " << str);
    00675 }
    00676
    00677 /*
    00678 void CodInfo::ParseType2(istream &input) {
    00679         uint32_t value;
    00680         uint32_t len  = ParseInteger(input);
    00681
    00682         string str = ParseString(input, len);
    00683
    00684         dout("Type2 : " << str);
    00685
    00686         value = ParseInteger(input);
    00687         value = ParseInteger(input);
    00688         value = ParseInteger(input);
    00689         value = ParseInteger(input);
    00690         value = ParseInteger(input);
    00691         value = ParseInteger(input);
    00692 }
    00693 */
    00694 } // namespace JDG
    00695
    00696 } // namespace Barry
    00697