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