Ejemplo n.º 1
0
 public function testGetTitle()
 {
     // Create a stack frame with zero fields (special case)
     $model = new StackFrame();
     $title = $model->getTitle();
     $this->assertTrue($title == '[WARNING: Stack unwind information not available. Frames below may be wrong.]');
     $model->addr_pc = 0x123456;
     $title = $model->getTitle();
     $this->assertTrue($title == '0x123456');
     $model->module_id = 1;
     $model->offs_in_module = 0x43435;
     $title = $model->getTitle();
     $this->assertTrue($title == 'CrashRptd.dll!+0x43435');
     // Set some sym info
     $model->symbol_name = '__test@test@@AAZ';
     $model->offs_in_symbol = 0x123;
     $title = $model->getTitle();
     $this->assertTrue($title == 'CrashRptd.dll! __test@test@@AAZ +0x123 ');
     // Set source file info
     $model->src_line = 60;
     $title = $model->getTitle();
     $this->assertTrue($title == 'CrashRptd.dll! __test@test@@AAZ +0x123 [line 60]');
     $model->src_file_name = 'CrashRpt.cpp';
     $title = $model->getTitle();
     $this->assertTrue($title == 'CrashRptd.dll! __test@test@@AAZ +0x123 [CrashRpt.cpp: 60]');
     // Find a stack frame with symbol info
     $model = StackFrame::model()->findByPk(1);
     $title = $model->getTitle();
     $this->assertTrue($title == 'CrashRptd.dll! CMainDlg::OnCrash() +0x1 [CrashRptTest.cpp: 1023]');
 }
Ejemplo n.º 2
0
 /**
  * Scans stack trace for this thread and retrieves the uppermost frame 
  * with symbol information. The information is considered as thread entry 
  * point function name. 
  */
 public function getThreadFuncName()
 {
     // Look for uppermost stack frame.
     $criteria = new CDbCriteria();
     $criteria->compare('thread_id', $this->id);
     $criteria->addCondition('symbol_name IS NOT NULL');
     $criteria->order = 'id DESC';
     $stackFrame = StackFrame::model()->find($criteria);
     if ($stackFrame === null) {
         return 'n/a';
     } else {
         if (isset($stackFrame->und_symbol_name)) {
             return $stackFrame->und_symbol_name;
         } else {
             return $stackFrame->symbol_name;
         }
     }
 }
Ejemplo n.º 3
0
 /**
  * This method reads crash report information from XML file and
  * updates appropriate database tables. 
  * @param string $xmlFileName XML file name.
  * @param integer $crashReportId Crash report ID in database.
  * @return boolean true on success.
  */
 public function importCrashReportFromXml($xmlFileName, $crashReportId)
 {
     $status = false;
     // Find appropriate {{crashreport}} table record
     $criteria = new CDbCriteria();
     $criteria->select = '*';
     $criteria->condition = 'id=' . $crashReportId;
     $crashReport = CrashReport::model()->find($criteria);
     if ($crashReport == Null) {
         Yii::log('Not found crash report id=' . $crashReportId);
         return $status;
     }
     $crashReport->status = CrashReport::STATUS_PROCESSED;
     // Begin DB transaction
     $transaction = Yii::app()->db->beginTransaction();
     try {
         // Load XML file
         $doc = @simplexml_load_file($xmlFileName);
         if ($doc == Null) {
             throw new Exception('CrashFix service has encountered an error when retrieving information from crash report file');
         }
         // Get command return status message from XML
         $elemSummary = $doc->Summary;
         if ($elemSummary == Null) {
             throw new Exception('Internal error: not found Summary element in XML document ' . $xmlFileName);
         }
         // Extract crash report info
         $generatorVersion = (int) $elemSummary->GeneratorVersion;
         $crashGuid = (string) $elemSummary->CrashGUID;
         $appName = (string) $elemSummary->ApplicationName;
         $appVersion = (string) $elemSummary->ApplicationVersion;
         $exeImage = (string) $elemSummary->ExecutableImage;
         $dateCreated = (string) $elemSummary->DateCreatedUTC;
         $osNameReg = (string) $elemSummary->OSNameReg;
         $osVersionMinidump = (string) $elemSummary->OSVersionMinidump;
         $osIs64Bit = (int) $elemSummary->OSIs64Bit;
         $geoLocation = (string) $elemSummary->GeographicLocation;
         $productType = (string) $elemSummary->ProductType;
         $cpuArchitecture = (string) $elemSummary->CPUArchitecture;
         $cpuCount = (int) $elemSummary->CPUCount;
         $guiResourceCount = (int) $elemSummary->GUIResourceCount;
         $openHandleCount = $elemSummary->OpenHandleCount;
         $memoryUsageKbytes = $elemSummary->MemoryUsageKbytes;
         $exceptionType = (string) $elemSummary->ExceptionType;
         $exceptionAddress = $elemSummary->ExceptionAddress;
         $sehExceptionCode = $elemSummary->SEHExceptionCode;
         $exceptionThreadID = $elemSummary->ExceptionThreadID;
         $exceptionModuleName = (string) $elemSummary->ExceptionModuleName;
         $exceptionModuleBase = (string) $elemSummary->ExceptionModuleBase;
         if (strlen($exceptionModuleBase) == 0) {
             $exceptionModuleBase = 0;
         }
         $crashReport->exceptionmodulebase = $exceptionModuleBase;
         $userEmail = (string) $elemSummary->UserEmail;
         $problemDescription = (string) $elemSummary->ProblemDescription;
         // Set crash report fields
         $crashReport->status = CrashReport::STATUS_PROCESSED;
         $crashReport->crashrptver = $generatorVersion;
         $crashReport->crashguid = $crashGuid;
         $ver = AppVersion::createIfNotExists($appVersion, $crashReport->project_id);
         $crashReport->appversion_id = $ver->id;
         if (strlen($userEmail) != 0) {
             $crashReport->emailfrom = $userEmail;
         }
         if (strlen($problemDescription) != 0) {
             $crashReport->description = $problemDescription;
         }
         if (strlen($dateCreated) != 0) {
             $crashReport->date_created = strtotime($dateCreated);
         }
         $crashReport->os_name_reg = $osNameReg;
         $crashReport->os_ver_mdmp = $osVersionMinidump;
         $crashReport->os_is_64bit = $osIs64Bit;
         $crashReport->geo_location = $geoLocation;
         $crashReport->product_type = $productType;
         $crashReport->cpu_architecture = $cpuArchitecture;
         $crashReport->cpu_count = $cpuCount;
         $crashReport->gui_resource_count = $guiResourceCount;
         $crashReport->memory_usage_kbytes = $memoryUsageKbytes;
         $crashReport->open_handle_count = $openHandleCount;
         $crashReport->exception_type = $exceptionType;
         if (strlen($sehExceptionCode) != 0) {
             $crashReport->exception_code = $sehExceptionCode;
         }
         if (strlen($exceptionThreadID) != 0) {
             $crashReport->exception_thread_id = $exceptionThreadID;
         }
         if (strlen($exceptionAddress) != 0) {
             $crashReport->exceptionaddress = $exceptionAddress;
         }
         if (strlen($exceptionModuleName) != 0) {
             $crashReport->exceptionmodule = $exceptionModuleName;
         }
         if (strlen($exceptionModuleBase) != 0) {
             $crashReport->exceptionmodulebase = $exceptionModuleBase;
         }
         $crashReport->exe_image = $exeImage;
         // Validate crash report fields
         if (!$crashReport->validate()) {
             // There are some errors
             $errors = $crashReport->getErrors();
             foreach ($errors as $fieldName => $fieldErrors) {
                 foreach ($fieldErrors as $errorMsg) {
                     // Add an error message to log
                     Yii::log('Error in crashreport data (' . $crashReport->{$fieldName} . '): ' . $errorMsg, 'error');
                     // Associate a processing error with crash report record
                     $this->addProcessingError(ProcessingError::TYPE_CRASH_REPORT_ERROR, $crashReport->id, $errorMsg . ' (' . $crashReport->{$fieldName} . ')');
                     // Clear field - this should fix the error
                     unset($crashReport->{$fieldName});
                 }
             }
             // Clear validation errors
             $crashReport->clearErrors();
         }
         // Extract file items
         $elemFileList = $doc->FileList;
         if ($elemFileList != Null) {
             $i = 0;
             foreach ($elemFileList->Row as $elemRow) {
                 $i++;
                 if ($i == 1) {
                     continue;
                 }
                 // Skip header row
                 $itemNo = $elemRow->Cell[0]['val'];
                 $itemName = $elemRow->Cell[1]['val'];
                 $itemDesc = $elemRow->Cell[2]['val'];
                 $fileItem = new FileItem();
                 $fileItem->filename = $itemName;
                 $fileItem->description = $itemDesc;
                 $fileItem->crashreport_id = $crashReportId;
                 if (!$fileItem->save()) {
                     throw new Exception('Could not save file item record');
                 }
             }
         }
         // Extract custom props
         $elemAppDefinedProps = $doc->ApplicationDefinedProperties;
         if ($elemAppDefinedProps != Null) {
             $i = 0;
             foreach ($elemAppDefinedProps->Row as $elemRow) {
                 $i++;
                 if ($i == 1) {
                     continue;
                 }
                 // Skip header row
                 $itemNo = $elemRow->Cell[0]['val'];
                 $name = $elemRow->Cell[1]['val'];
                 $val = $elemRow->Cell[2]['val'];
                 $customProp = new CustomProp();
                 $customProp->name = $name;
                 $customProp->value = $val;
                 $customProp->crashreport_id = $crashReportId;
                 if (!$customProp->save()) {
                     throw new Exception('Could not save custom property record');
                 }
             }
         }
         // Extract the list of modules
         $elemModuleList = $doc->ModuleList;
         if ($elemModuleList != Null && $elemModuleList->count() != 0) {
             $i = 0;
             foreach ($elemModuleList->Row as $elemRow) {
                 $i++;
                 if ($i == 1) {
                     continue;
                 }
                 // Skip header row
                 $itemNo = $elemRow->Cell[0]['val'];
                 $name = $elemRow->Cell[1]['val'];
                 $symLoadStatus = $elemRow->Cell[2]['val'];
                 $loadedPdbName = $elemRow->Cell[3]['val'];
                 $loadedPdbGUID = $elemRow->Cell[4]['val'];
                 $fileVersion = $elemRow->Cell[5]['val'];
                 $timeStamp = $elemRow->Cell[6]['val'];
                 $guidnAge = $elemRow->Cell[7]['val'];
                 $module = new Module();
                 $module->crashreport_id = $crashReportId;
                 $module->name = $name;
                 $module->sym_load_status = $symLoadStatus;
                 $module->file_version = $fileVersion;
                 $module->timestamp = $timeStamp;
                 $module->matching_pdb_guid = $guidnAge;
                 $debugInfo = DebugInfo::model()->findByAttributes(array('guid' => $loadedPdbGUID));
                 if ($debugInfo != null) {
                     $module->loaded_debug_info_id = $debugInfo->id;
                 }
                 if (!$module->save()) {
                     throw new Exception('Could not save module record');
                 }
             }
         }
         // Extract the list of stack traces
         foreach ($doc->StackTrace as $elemStackTrace) {
             $threadId = $elemStackTrace->ThreadID;
             $stackTraceMD5 = $elemStackTrace->StackTraceMD5;
             $thread = new Thread();
             $thread->thread_id = $threadId;
             $thread->crashreport_id = $crashReportId;
             if (strlen($stackTraceMD5) != 0) {
                 $thread->stack_trace_md5 = $stackTraceMD5;
             }
             if (!$thread->save()) {
                 throw new Exception('Could not save thread record');
             }
             $i = 0;
             foreach ($elemStackTrace->Row as $elemRow) {
                 $i++;
                 if ($i == 1) {
                     continue;
                 }
                 // Skip header row
                 $title = $elemRow->Cell[0]['val'];
                 $addrPC = $elemRow->Cell[1]['val'];
                 $moduleName = $elemRow->Cell[2]['val'];
                 $offsInModule = $elemRow->Cell[3]['val'];
                 $symName = $elemRow->Cell[4]['val'];
                 $undSymName = $elemRow->Cell[5]['val'];
                 $offsInSym = $elemRow->Cell[6]['val'];
                 $srcFile = $elemRow->Cell[7]['val'];
                 $srcLine = $elemRow->Cell[8]['val'];
                 $offsInLine = $elemRow->Cell[9]['val'];
                 $stackFrame = new StackFrame();
                 $stackFrame->thread_id = $thread->id;
                 $stackFrame->addr_pc = $addrPC;
                 if (strlen($moduleName) != 0) {
                     $module = Module::model()->findByAttributes(array('name' => $moduleName, 'crashreport_id' => $crashReportId));
                     if ($module != null) {
                         $stackFrame->module_id = $module->id;
                     }
                     $stackFrame->offs_in_module = $offsInModule;
                 }
                 if (strlen($symName) != 0) {
                     $stackFrame->symbol_name = $symName;
                 }
                 if (strlen($undSymName) != 0) {
                     $stackFrame->und_symbol_name = $undSymName;
                 }
                 if (strlen($offsInSym) != 0) {
                     $stackFrame->offs_in_symbol = $offsInSym;
                 }
                 if (strlen($srcFile) != 0) {
                     $stackFrame->src_file_name = $srcFile;
                 }
                 if (strlen($srcLine) != 0) {
                     $stackFrame->src_line = $srcLine;
                 }
                 if (strlen($offsInLine) != 0) {
                     $stackFrame->offs_in_line = $offsInLine;
                 }
                 if (!$stackFrame->save()) {
                     throw new Exception('Could not save stack frame record');
                 }
             }
         }
         // Commit transaction
         $transaction->commit();
         // Success.
         $status = true;
     } catch (Exception $e) {
         // Rollback transaction
         $transaction->rollback();
         // Add a message to log
         Yii::log($e->getMessage(), 'error');
         $crashReport->status = CrashReport::STATUS_INVALID;
         // Associate a processing error with crash report record
         $this->addProcessingError(ProcessingError::TYPE_CRASH_REPORT_ERROR, $crashReport->id, $e->getMessage());
         $status = false;
     }
     // Update crash group based on new data
     $crashGroup = $crashReport->createCrashGroup();
     if ($crashGroup == Null) {
         Yii::log('Error creating crash group', 'error');
         $status = false;
     }
     $crashReport->groupid = $crashGroup->id;
     // Update crash report
     $saved = $crashReport->save();
     if (!$saved) {
         Yii::log('Error saving AR crashReport', 'error');
         $status = false;
     }
     if (!$saved || !$crashReport->checkQuota()) {
         Yii::log('Error checking crash report quota', 'error');
         $status = false;
         // Delete crash report
         $crashReport = $crashReport = CrashReport::model()->find('id=' . $crashReport->id);
         $crashReport->delete();
     }
     // Return status
     return $status;
 }