3030#include < QDesktopServices>
3131#include < QMessageBox>
3232#include < QSettings>
33+ #include < QMimeDatabase>
34+ #include < QMimeType>
35+ #include < QDebug>
36+
37+ #include " stackwalker.h"
3338
3439BreakDown::BreakDown (QWidget *parent) :
3540 QMainWindow(parent),
@@ -142,8 +147,13 @@ void BreakDown::openJsonFile(const QString &file)
142147 if (!jsonFile.open (QIODevice::ReadOnly|QIODevice::Text)) { return ; }
143148 QString rawJson = jsonFile.readAll ();
144149 jsonFile.close ();
150+ if (!rawJson.isEmpty ()) { openJsonString (rawJson); }
151+ }
145152
146- QJsonDocument doc (QJsonDocument::fromJson (rawJson.toUtf8 ()));
153+ void BreakDown::openJsonString (const QString json, const QString customID)
154+ {
155+ if (json.isEmpty ()) { return ; }
156+ QJsonDocument doc (QJsonDocument::fromJson (json.toUtf8 ()));
147157 if (doc.isEmpty () || doc.isNull ()) { return ; }
148158 QJsonObject obj = doc.object ();
149159
@@ -157,6 +167,7 @@ void BreakDown::openJsonFile(const QString &file)
157167 QJsonObject system_info_item = system_info.toObject ();
158168
159169 QString uuid = obj.value (QString (" uuid" )).toString ();
170+ if (uuid.isEmpty () && !customID.isEmpty ()) { uuid = customID; }
160171 QString timestamp = obj.value (QString (" submitted_timestamp" )).toString ();
161172 QString comment = obj.value (QString (" Comments" )).toString ();
162173 QString git_commit = obj.value (QString (" git_commit" )).toString ();
@@ -309,18 +320,124 @@ void BreakDown::openJsonFile(const QString &file)
309320 }
310321}
311322
323+ void BreakDown::openDumpFile (const QString &file)
324+ {
325+ vector<string> server_path;
326+ vector<string> symbol_paths;
327+
328+ // TODO: settings (also remember cache and tmp!!!)
329+ server_path.push_back (" https://stackwalker.000webhostapp.com/symbols" );
330+
331+ Minidump minidump (file.toStdString ());
332+ minidump.Read ();
333+
334+ Json::Value root;
335+ scoped_ptr<SymbolSupplier> symbol_supplier;
336+ HTTPSymbolSupplier* http_symbol_supplier = nullptr ;
337+ if (!server_path.empty ()) {
338+ http_symbol_supplier = new HTTPSymbolSupplier (server_path,
339+ QDir::tempPath ().toStdString (),
340+ symbol_paths,
341+ QDir::tempPath ().toStdString ());
342+ symbol_supplier.reset (http_symbol_supplier);
343+ } else if (!symbol_paths.empty ()) {
344+ symbol_supplier.reset (new SimpleSymbolSupplier (symbol_paths));
345+ }
346+
347+ BasicSourceLineResolver resolver;
348+ StackFrameSymbolizerForward symbolizer (symbol_supplier.get (), &resolver);
349+ MinidumpProcessor minidump_processor (&symbolizer, true );
350+ ProcessState process_state;
351+ ProcessResult result = minidump_processor.Process (&minidump, &process_state);
352+
353+ if (result != google_breakpad::PROCESS_OK) {
354+ string failed = ResultString (result);
355+ QMessageBox::warning (this ,
356+ tr (" Failed to process minidump" ),
357+ QString::fromStdString (failed));
358+ return ;
359+ }
360+
361+ Json::Value raw_root (Json::objectValue);
362+
363+ root[" status" ] = ResultString (result);
364+ root[" sensitive" ] = Json::Value (Json::objectValue);
365+ if (result == google_breakpad::PROCESS_OK) {
366+ ConvertProcessStateToJSON (process_state,
367+ symbolizer,
368+ http_symbol_supplier,
369+ root,
370+ raw_root);
371+ } else {
372+ QMessageBox::warning (this ,
373+ tr (" Failed to process minidump" ),
374+ QString::fromStdString (ResultString (result)));
375+ }
376+ ConvertMemoryInfoToJSON (minidump, raw_root, root);
377+
378+ // Get the PID.
379+ MinidumpMiscInfo* misc_info = minidump.GetMiscInfo ();
380+ if (misc_info && misc_info->misc_info () &&
381+ (misc_info->misc_info ()->flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID))
382+ {
383+ root[" pid" ] = misc_info->misc_info ()->process_id ;
384+ }
385+
386+ // See if this is a Linux dump with /proc/cpuinfo in it
387+ uint32_t cpuinfo_length = 0 ;
388+ if (process_state.system_info ()->os == " Linux" &&
389+ minidump.SeekToStreamType (MD_LINUX_CPU_INFO, &cpuinfo_length))
390+ {
391+ string contents;
392+ contents.resize (cpuinfo_length);
393+ if (minidump.ReadBytes (const_cast <char *>(contents.data ()), cpuinfo_length)) {
394+ ConvertCPUInfoToJSON (contents, root);
395+ }
396+ }
397+
398+ // See if this is a Linux dump with /etc/lsb-release in it
399+ uint32_t length = 0 ;
400+ if (process_state.system_info ()->os == " Linux" &&
401+ minidump.SeekToStreamType (MD_LINUX_LSB_RELEASE, &length))
402+ {
403+ string contents;
404+ contents.resize (length);
405+ if (minidump.ReadBytes (const_cast <char *>(contents.data ()), length)) {
406+ ConvertLSBReleaseToJSON (contents, root);
407+ }
408+ }
409+
410+ scoped_ptr<Json::Writer> writer;
411+ writer.reset (new Json::StyledWriter ());
412+ string json = writer->write (root);
413+
414+ if (!json.empty ()) {
415+ QFileInfo info (file);
416+ openJsonString (QString::fromStdString (json), info.baseName ());
417+ }
418+ }
419+
312420void BreakDown::on_actionQuit_triggered ()
313421{
314422 qApp->quit ();
315423}
316424
317425void BreakDown::on_actionOpen_triggered ()
318426{
319- QString jsonFile = QFileDialog::getOpenFileName (this ,
320- tr (" Open Stackwalker JSON or DMP" ),
321- QDir::homePath ());
322- if (jsonFile.isEmpty ()) { return ; }
323- openJsonFile (jsonFile);
427+ QString file = QFileDialog::getOpenFileName (this ,
428+ tr (" Open Stackwalker JSON or Breakpad DMP" ),
429+ QDir::homePath (),
430+ " *.json *.dmp" );
431+ if (file.isEmpty ()) { return ; }
432+
433+ QMimeDatabase db;
434+ QMimeType type = db.mimeTypeForFile (file);
435+
436+ if (type.name () == " application/json" ) {
437+ openJsonFile (file);
438+ } else {
439+ openDumpFile (file);
440+ }
324441}
325442
326443void BreakDown::on_reportInfoCrashTree_itemDoubleClicked (QTreeWidgetItem *item, int column)
@@ -335,6 +452,6 @@ void BreakDown::on_actionAbout_triggered()
335452 QMessageBox::about (this ,
336453 QString (" %1 Breakdown" ).arg (tr (" About" )),
337454 QString (" <h3>Breakdown</h3>"
338- " <p>Parse crash reports from Stackwalker, designed for use with Natron .<p>"
339- " <p>Copyright © 2019 <a href=\" https://github.com/rodlie\" >Ole-André Rodlie</a>.</p>" ));
455+ " <p>Parse crash reports from Breakpad .<p>"
456+ " <p>Copyright ©2019 <a href=\" https://github.com/rodlie\" >Ole-André Rodlie</a>.</p>" ));
340457}
0 commit comments