- It is enough to just add a "const" to fix the "deprecated conversion from string...
[reactos.git] / reactos / tools / sysreg / rosboot_test.cpp
1
2 /* $Id$
3 *
4 * PROJECT: System regression tool for ReactOS
5 * LICENSE: GPL - See COPYING in the top level directory
6 * FILE: tools/sysreg/conf_parser.h
7 * PURPOSE: ReactOS boot test
8 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
9 */
10
11
12 #include "rosboot_test.h"
13 #include "pipe_reader.h"
14 #include "namedpipe_reader.h"
15 //#include "sym_file.h"
16 #include "file_reader.h"
17 #include "os_support.h"
18 #include "env_var.h"
19
20 #include <iostream>
21 #include <vector>
22 #include <fstream>
23 #include <time.h>
24 #include <float.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <math.h>
29 #include <signal.h>
30 #ifndef __LINUX__
31 #include <io.h>
32 #include <errno.h>
33 #endif
34
35 namespace Sysreg_
36 {
37 using std::vector;
38 using System_::PipeReader;
39 using System_::NamedPipeReader;
40 /* using System_::SymbolFile; */
41 using System_::FileReader;
42 using System_::OsSupport;
43 using System_::EnvironmentVariable;
44
45 #ifdef UNICODE
46 using std::wofstream;
47 typedef wofstream ofstream;
48 #else
49 using std::ofstream;
50 #endif
51
52 string RosBootTest::ROS_EMU_TYPE= "ROS_EMU_TYPE";
53 string RosBootTest::EMU_TYPE_QEMU = "qemu";
54 string RosBootTest::EMU_TYPE_VMWARE = "vmware";
55 string RosBootTest::ROS_HDD_IMAGE= "ROS_HDD_IMAGE";
56 string RosBootTest::ROS_CD_IMAGE = "ROS_CD_IMAGE";
57 string RosBootTest::ROS_MAX_TIME = "ROS_MAX_TIME";
58 string RosBootTest::ROS_LOG_FILE = "ROS_LOG_FILE";
59 string RosBootTest::ROS_SYM_DIR = "ROS_SYM_DIR";
60 string RosBootTest::ROS_DELAY_READ = "ROS_DELAY_READ";
61 string RosBootTest::ROS_SYSREG_CHECKPOINT = "SYSREG_CHECKPOINT:";
62 string RosBootTest::ROS_CRITICAL_IMAGE = "ROS_CRITICAL_IMAGE";
63 string RosBootTest::ROS_EMU_KILL = "ROS_EMU_KILL";
64 string RosBootTest::ROS_EMU_MEM = "ROS_EMU_MEM";
65 string RosBootTest::ROS_BOOT_CMD = "ROS_BOOT_CMD";
66
67 #ifdef __LINUX__
68 string RosBootTest::ROS_EMU_PATH = "ROS_EMU_PATH_LIN";
69 #else
70 string RosBootTest::ROS_EMU_PATH = "ROS_EMU_PATH_WIN";
71 #endif
72
73 //---------------------------------------------------------------------------------------
74 RosBootTest::RosBootTest() : m_MaxTime(65), m_DelayRead(0)
75 {
76
77 }
78
79 //---------------------------------------------------------------------------------------
80 RosBootTest::~RosBootTest()
81 {
82
83 }
84 //---------------------------------------------------------------------------------------
85 bool RosBootTest::executeBootCmd()
86 {
87 int numargs = 0;
88 const char * args[128];
89 char * pBuf;
90 char szBuffer[128];
91
92 pBuf = (char*)m_BootCmd.c_str ();
93 if (pBuf)
94 {
95 pBuf = strtok(pBuf, " ");
96 while(pBuf != NULL)
97 {
98 if (!numargs)
99 strcpy(szBuffer, pBuf);
100
101 args[numargs] = pBuf;
102 numargs++;
103 pBuf = strtok(NULL, " ");
104 }
105 args[numargs++] = 0;
106 }
107 else
108 {
109 strcpy(szBuffer, pBuf);
110 }
111 m_Pid = OsSupport::createProcess (szBuffer, numargs-1, args, false);
112 if (!m_Pid)
113 {
114 cerr << "Error: failed to launch boot cmd " << m_BootCmd << endl;
115 return false;
116 }
117
118 return true;
119 }
120 //---------------------------------------------------------------------------------------
121 void RosBootTest::delayRead()
122 {
123 if (m_DelayRead)
124 {
125 ///
126 /// delay reading until emulator is ready
127 ///
128
129 OsSupport::delayExecution(m_DelayRead);
130 }
131 }
132 //---------------------------------------------------------------------------------------
133 void RosBootTest::getDefaultHDDImage(string & img)
134 {
135 img = "output-i386";
136
137 EnvironmentVariable::getValue("ROS_OUTPUT", img);
138 #ifdef __LINUX__
139 img += "/ros.hd";
140 #else
141 img += "\\ros.hd";
142 #endif
143 }
144 //---------------------------------------------------------------------------------------
145 bool RosBootTest::isFileExisting(string output)
146 {
147 FILE * file;
148 file = fopen(output.c_str(), "r");
149
150 if (file)
151 {
152 /* the file exists */
153 fclose(file);
154 return true;
155 }
156 return false;
157 }
158
159 //---------------------------------------------------------------------------------------
160 bool RosBootTest::isDefaultHDDImageExisting()
161 {
162 string img;
163
164 getDefaultHDDImage(img);
165 return isFileExisting(img);
166 }
167
168 //---------------------------------------------------------------------------------------
169 bool RosBootTest::createHDDImage(string image)
170 {
171
172 string qemuimgdir;
173 if (!getQemuDir(qemuimgdir))
174 {
175 cerr << "Error: failed to retrieve qemu directory path" << endl;
176 return false;
177 }
178
179
180 #ifdef __LINUX__
181 qemuimgdir += "/qemu-img";
182
183 #else
184 qemuimgdir += "\\qemu-img.exe";
185 #endif
186
187 if (!isFileExisting(qemuimgdir))
188 {
189 cerr << "Error: ROS_EMU_PATH must contain the path to qemu and qemu-img " << qemuimgdir << endl;
190 return false;
191 }
192 remove(image.c_str ());
193
194 const char * options[] = {NULL,
195 "create",
196 "-f",
197 #ifdef __LINUX__
198 "raw",
199 #else
200 "vmdk",
201 #endif
202 NULL,
203 "100M",
204 NULL
205 };
206
207
208 options[0] = qemuimgdir.c_str();
209 options[4] = image.c_str();
210
211 cerr << "Creating HDD Image ..." << image << endl;
212 OsSupport::createProcess (qemuimgdir.c_str(), 6, options, true);
213 if (isFileExisting(image))
214 {
215 m_HDDImage = image;
216 return true;
217 }
218 return false;
219 }
220 //----------------------------------------------------------------------------------------
221 bool RosBootTest::isQemuPathValid()
222 {
223 string qemupath;
224
225 if (m_BootCmd.length())
226 {
227 /* the boot cmd is already provided
228 * check if path to qemu is valid
229 */
230 string::size_type pos = m_BootCmd.find_first_of(" ");
231 if (pos == string::npos)
232 {
233 /* the bootcmd is certainly not valid */
234 return false;
235 }
236 qemupath = m_BootCmd.substr(0, pos);
237 }
238 else
239 {
240 /* the qemu path is provided ROS_EMU_PATH variable */
241 qemupath = m_EmuPath;
242 }
243
244
245 return isFileExisting(qemupath);
246 }
247 //----------------------------------------------------------------------------------------
248 bool RosBootTest::hasQemuNoRebootOption()
249 {
250 ///
251 /// FIXME
252 /// extract version
253 ///
254
255 return true;
256 }
257 //----------------------------------------------------------------------------------------
258 bool RosBootTest::getQemuDir(string & qemupath)
259 {
260 string::size_type pos;
261
262 #ifdef __LINUX__
263 pos = m_EmuPath.find_last_of("/");
264 #else
265 pos = m_EmuPath.find_last_of("\\");
266 #endif
267 if (pos == string::npos)
268 {
269 cerr << "Error: ROS_EMU_PATH is invalid!!!" << endl;
270 return false;
271 }
272 qemupath = m_EmuPath.substr(0, pos);
273 return true;
274 }
275 //----------------------------------------------------------------------------------------
276 bool RosBootTest::createBootCmd()
277 {
278 string pipe;
279 string qemudir;
280 char pipename[] = "qemuXXXXXX";
281 if (m_MaxMem.length() == 0)
282 {
283 /* set default memory size to 64M */
284 m_MaxMem = "64";
285 }
286
287 #ifdef __LINUX__
288
289 if (mktemp(pipename))
290 {
291 string temp = pipename;
292 m_Src = "/tmp/" + temp;
293 pipe = "pipe:" + m_Src;
294 }
295 else
296 {
297
298 pipe = "pipe:/tmp/qemu";
299 m_Src = "/tmp/qemu";
300 }
301
302 qemudir = "/usr/share/qemu";
303 m_DebugPort = "pipe";
304 #else
305 if (_mktemp(pipename))
306 {
307 string temp = pipename;
308 pipe = "pipe:" + temp;
309 m_Src = "\\\\.\\pipe\\" + temp;
310 }
311 else
312 {
313 pipe = "pipe:qemu";
314 m_Src = "\\\\.\\pipe\\qemu";
315 }
316 m_DebugPort = "pipe";
317
318 if (!getQemuDir(qemudir))
319 {
320 return false;
321 }
322 #endif
323
324
325 m_BootCmd = m_EmuPath + " -L " + qemudir + " -m " + m_MaxMem + " -serial " + pipe;
326
327 if (m_CDImage.length())
328 {
329 /* boot from cdrom */
330 m_BootCmd += " -boot d -cdrom " + m_CDImage;
331
332 if (m_HDDImage.length ())
333 {
334 /* add disk when specified */
335 m_BootCmd += " -hda " + m_HDDImage;
336 }
337
338 }
339 else if (m_HDDImage.length ())
340 {
341 /* boot from hdd */
342 m_BootCmd += " -boot c -hda " + m_HDDImage;
343 }
344 else
345 {
346 /*
347 * no boot device provided
348 */
349 cerr << "Error: no bootdevice provided" << endl;
350 return false;
351 }
352
353 #ifdef __LINUX__
354 /* on linux we need get pid in order to be able
355 * to terminate the emulator in case of errors
356 * on windows we can get pid as return of CreateProcess
357 */
358 m_PidFile = "output-i386";
359 EnvironmentVariable::getValue("ROS_OUTPUT", m_PidFile);
360 m_PidFile += "/pid.txt";
361 m_BootCmd += " -pidfile ";
362 m_BootCmd += m_PidFile;
363 m_BootCmd += " -nographic";
364 #else
365
366 if (hasQemuNoRebootOption())
367 {
368 m_BootCmd += " -no-reboot ";
369 }
370 #endif
371 return true;
372 }
373 //----------------------------------------------------------------------------------------
374 bool RosBootTest::extractPipeFromBootCmd()
375 {
376 string::size_type pos = m_BootCmd.find("-serial pipe:");
377 if (pos == string::npos)
378 {
379 /* no debug options provided */
380 cerr << "Error: provided boot cmd does not specify a pipe debugging port" << endl;
381 return false;
382 }
383
384 string pipe = m_BootCmd.substr(pos + 13, m_BootCmd.size() - pos - 13);
385 pos = pipe.find(" ");
386 if (pos != string::npos)
387 {
388 pipe = pipe.substr(0, pos);
389 }
390 #ifdef __LINUX__
391 m_Src = pipe;
392 #else
393 m_Src = "\\\\.\\pipe\\" + pipe.substr(0, pos);
394 #endif
395 m_DebugPort = "pipe";
396 return true;
397 }
398 //----------------------------------------------------------------------------------------
399 bool RosBootTest::configureHDDImage()
400 {
401 //cout << "configureHDDImage m_HDDImage " << m_HDDImage.length() << " m_CDImage " << m_CDImage.length() << " m_BootCmd: " << m_BootCmd.length() << endl;
402 if (m_HDDImage.length())
403 {
404 /* check if ROS_HDD_IMAGE points to hdd image */
405 if (!isFileExisting(m_HDDImage))
406 {
407 if (!m_CDImage.length ())
408 {
409 cerr << "Error: HDD image is not existing and CDROM image not provided" << endl;
410 return false;
411 }
412 /* create it */
413 return createHDDImage(m_HDDImage);
414 }
415 return true;
416 }
417 else if (!m_BootCmd.length ())
418 {
419 /* no hdd image provided
420 * but also no override by
421 * ROS_BOOT_CMD
422 */
423 if (!m_CDImage.length ())
424 {
425 cerr << "Error: no HDD and CDROM image provided" << endl;
426 return false;
427 }
428
429 getDefaultHDDImage(m_HDDImage);
430 if (isFileExisting(m_HDDImage))
431 {
432 cerr << "Falling back to default hdd image " << m_HDDImage << endl;
433 return true;
434 }
435 return createHDDImage(m_HDDImage);
436 }
437 /*
438 * verify the provided ROS_BOOT_CMD for hdd image
439 *
440 */
441
442 bool hdaboot = false;
443 string::size_type pos = m_BootCmd.find ("-boot c");
444 if (pos != string::npos)
445 {
446 hdaboot = true;
447 }
448
449 pos = m_BootCmd.find("-hda ");
450 if (pos != string::npos)
451 {
452 string hdd = m_BootCmd.substr(pos + 5, m_BootCmd.length() - pos - 5);
453 if (!hdd.length ())
454 {
455 cerr << "Error: ROS_BOOT_CMD misses value of -hda option" << endl;
456 return false;
457 }
458 pos = m_BootCmd.find(" ");
459 if (pos != string::npos)
460 {
461 /// FIXME
462 /// sysreg assumes that the hdd image filename has no spaces
463 ///
464 hdd = hdd.substr(0, pos);
465 }
466 if (!isFileExisting(hdd))
467 {
468 if (hdaboot)
469 {
470 cerr << "Error: ROS_BOOT_CMD specifies booting from hda but no valid hdd image " << hdd << " provided" << endl;
471 return false;
472 }
473
474 /* the file does not exist create it */
475 return createHDDImage(hdd);
476 }
477 return true;
478 }
479
480 return false;
481 }
482 //----------------------------------------------------------------------------------------
483 bool RosBootTest::configureCDImage()
484 {
485 if (!m_BootCmd.length ())
486 {
487 if (m_CDImage.length())
488 {
489 /* we have a cd image lets check if its valid */
490 if (isFileExisting(m_CDImage))
491 {
492 cerr << "Using CDROM image " << m_CDImage << endl;
493 return true;
494 }
495 }
496 if (isFileExisting("ReactOS-RegTest.iso"))
497 {
498 m_CDImage = "ReactOS-RegTest.iso";
499 cerr << "Falling back to default CDROM image " << m_CDImage << endl;
500 return true;
501 }
502 cerr << "No CDROM image found, boot device is HDD" << endl;
503 m_CDImage = "";
504 return true;
505 }
506
507 string::size_type pos = m_BootCmd.find("-boot ");
508 if (pos == string::npos)
509 {
510 /* ROS_BOOT_CMD must provide a boot parameter*/
511 cerr << "Error: ROS_BOOT_CMD misses boot parameter" << endl;
512 return false;
513 }
514
515 string rest = m_BootCmd.substr(pos + 6, m_BootCmd.length() - pos - 6);
516 if (rest.length() < 1)
517 {
518 /* boot parameter misses option where to boot from */
519 cerr << "Error: ROS_BOOT_CMD misses boot parameter" << endl;
520 return false;
521 }
522 if (rest[0] != 'c' && rest[0] != 'd')
523 {
524 cerr << "Error: ROS_BOOT_CMD has invalid boot parameter" << endl;
525 return false;
526 }
527
528 if (rest[0] == 'c')
529 {
530 /* ROS_BOOT_CMD boots from hdd */
531 return true;
532 }
533
534 pos = m_BootCmd.find("-cdrom ");
535 if (pos == string::npos)
536 {
537 cerr << "Error: ROS_BOOT_CMD misses cdrom parameter" << endl;
538 return false;
539 }
540 rest = m_BootCmd.substr(pos + 7, m_BootCmd.length() - pos - 7);
541 if (!rest.length())
542 {
543 cerr << "Error: ROS_BOOT_CMD misses cdrom parameter" << endl;
544 return false;
545 }
546 pos = rest.find(" ");
547 if (pos != string::npos)
548 {
549 rest = rest.substr(0, pos);
550 }
551
552 if (!isFileExisting(rest))
553 {
554 cerr << "Error: cdrom image " << rest << " does not exist" << endl;
555 return false;
556 }
557 else
558 {
559 m_CDImage = rest;
560 return true;
561 }
562 }
563 //----------------------------------------------------------------------------------------
564 bool RosBootTest::configureQemu()
565 {
566 if (!isQemuPathValid())
567 {
568 cerr << "Error: the path to qemu is not valid" << endl;
569 return false;
570 }
571
572 if (!configureCDImage())
573 {
574 cerr << "Error: failed to set a valid cdrom configuration" << endl;
575 return false;
576 }
577
578 if (!configureHDDImage())
579 {
580 cerr << "Error: failed to set a valid hdd configuration" << endl;
581 return false;
582 }
583
584 if (m_BootCmd.length())
585 {
586 if (!extractPipeFromBootCmd())
587 {
588 return false;
589 }
590 }
591 else
592 {
593 if (!createBootCmd())
594 {
595 return false;
596 }
597 }
598 #ifdef __LINUX__
599 if (mkfifo(m_Src.c_str(), 400))
600 {
601 /*
602 if (errno != EEXIST)
603 {
604 cerr <<"Error: mkfifo failed with " << errno << endl;
605 }
606 */
607 return false;
608 }
609
610 #endif
611 if (m_PidFile.length () && isFileExisting(m_PidFile))
612 {
613 cerr << "Deleting pid file " << m_PidFile << endl;
614 remove(m_PidFile.c_str ());
615 }
616
617
618
619 cerr << "Opening Data Source:" << m_BootCmd << endl;
620 m_DataSource = new NamedPipeReader();
621 if (!executeBootCmd())
622 {
623 cerr << "Error: failed to launch emulator with: " << m_BootCmd << endl;
624 return false;
625 }
626
627 return true;
628 }
629
630 //---------------------------------------------------------------------------------------
631 bool RosBootTest::configureVmWare()
632 {
633 cerr << "VmWare is currently not yet supported" << endl;
634 return false;
635 }
636 //---------------------------------------------------------------------------------------
637 bool RosBootTest::readConfigurationValues(ConfigParser &conf_parser)
638 {
639 #if 0
640 if (!conf_parser.getStringValue(RosBootTest::ROS_EMU_TYPE, m_EmuType))
641 {
642 cerr << "Error: ROS_EMU_TYPE is not set" << endl;
643 return false;
644 }
645 #endif
646
647 if (!conf_parser.getStringValue(RosBootTest::ROS_EMU_PATH, m_EmuPath))
648 {
649 cerr << "Error: ROS_EMU_PATH is not set" << endl;
650 return false;
651 }
652 if (!m_HDDImage.length())
653 {
654 /* only read image once */
655 conf_parser.getStringValue (RosBootTest::ROS_HDD_IMAGE, m_HDDImage);
656 }
657 if (!m_CDImage.length())
658 {
659 /* only read cdimage once */
660 conf_parser.getStringValue (RosBootTest::ROS_CD_IMAGE, m_CDImage);
661 }
662 /* reset boot cmd */
663 m_BootCmd = "";
664
665
666 conf_parser.getIntValue (RosBootTest::ROS_MAX_TIME, m_MaxTime);
667 conf_parser.getStringValue (RosBootTest::ROS_LOG_FILE, m_DebugFile);
668 conf_parser.getStringValue (RosBootTest::ROS_SYM_DIR, m_SymDir);
669 conf_parser.getIntValue (RosBootTest::ROS_DELAY_READ, m_DelayRead);
670 conf_parser.getStringValue (RosBootTest::ROS_SYSREG_CHECKPOINT, m_Checkpoint);
671 conf_parser.getStringValue (RosBootTest::ROS_CRITICAL_IMAGE, m_CriticalImage);
672 conf_parser.getStringValue (RosBootTest::ROS_EMU_KILL, m_KillEmulator);
673 conf_parser.getStringValue (RosBootTest::ROS_EMU_MEM, m_MaxMem);
674 conf_parser.getStringValue (RosBootTest::ROS_BOOT_CMD, m_BootCmd);
675
676 return true;
677 }
678 //---------------------------------------------------------------------------------------
679 void RosBootTest::cleanup()
680 {
681 m_DataSource->closeSource();
682 OsSupport::delayExecution(3);
683
684 if (m_Pid)
685 {
686 OsSupport::terminateProcess (m_Pid, 0);
687 }
688 delete m_DataSource;
689 m_DataSource = NULL;
690
691 if (m_PidFile.length ())
692 {
693 remove(m_PidFile.c_str ());
694 }
695 }
696
697 //---------------------------------------------------------------------------------------
698 bool RosBootTest::execute(ConfigParser &conf_parser)
699 {
700 if (!readConfigurationValues(conf_parser))
701 {
702 return false;
703 }
704 #if 0
705 if (m_EmuType == EMU_TYPE_QEMU)
706 {
707 if (!configureQemu())
708 {
709 cerr << "Error: failed to configure qemu" << endl;
710 return false;
711 }
712 }
713 else if (m_EmuType == EMU_TYPE_VMWARE)
714 {
715 if (!configureVmWare())
716 {
717 cerr << "Error: failed to configure vmware" << endl;
718 return false;
719 }
720 }
721 else
722 {
723 ///
724 /// unsupported emulator
725
726 cerr << "Error: ROS_EMU_TYPE value is not supported:" << m_EmuType << "=" << EMU_TYPE_QEMU << endl;
727 return false;
728 }
729 #else
730 if (!configureQemu())
731 {
732 cerr << "Error: failed to configure qemu" << endl;
733 return false;
734 }
735 #endif
736
737 if (m_DelayRead)
738 {
739 cerr << "Delaying read for " << m_DelayRead << " seconds" << endl;
740 OsSupport::delayExecution(m_DelayRead);
741 }
742
743 if (!m_DataSource->openSource(m_Src))
744 {
745 cerr << "Error: failed to open data source with " << m_Src << endl;
746 cleanup();
747 return false;
748 }
749 #ifdef __LINUX__
750 /*
751 * For linux systems we can only
752 * check if the emulator runs by
753 * opening pid.txt and lookthrough if
754 * it exists
755 */
756
757 FILE * file = fopen(m_PidFile.c_str(), "r");
758 if (!file)
759 {
760 cerr << "Error: failed to launch emulator" << endl;
761 cleanup();
762 return false;
763 }
764 char buffer[128];
765 if (!fread(buffer, 1, sizeof(buffer), file))
766 {
767 cerr << "Error: pid file w/o pid!!! " << endl;
768 fclose(file);
769 cleanup();
770 return false;
771 }
772 m_Pid = atoi(buffer);
773 fclose(file);
774 #endif
775 OsSupport::cancelAlarms();
776 #ifdef __LINUX__
777 //OsSupport::setAlarm (m_MaxTime, m_Pid);
778 //OsSupport::setAlarm(m_MaxTime, getpid());
779 #else
780 OsSupport::setAlarm (m_MaxTime, m_Pid);
781 OsSupport::setAlarm(m_MaxTime, GetCurrentProcessId());
782 #endif
783
784 bool ret = analyzeDebugData();
785 cleanup();
786
787 return ret;
788 }
789 //---------------------------------------------------------------------------------------
790 void RosBootTest::dumpCheckpoints()
791 {
792 if (m_Checkpoints.size ())
793 {
794 cerr << "Dumping list of checkpoints: "<< endl;
795 while(!m_Checkpoints.empty ())
796 {
797 cerr << m_Checkpoints[0] << endl;
798 m_Checkpoints.erase (m_Checkpoints.begin ());
799
800 }
801 }
802 }
803 //---------------------------------------------------------------------------------------
804 RosBootTest::DebugState RosBootTest::checkDebugData(vector<string> & debug_data)
805 {
806 /// TBD the information needs to be written into an provided log object
807 /// which writes the info into HTML/log / sends etc ....
808
809 bool clear = true;
810 DebugState state = DebugStateContinue;
811
812 for(size_t i = 0; i < debug_data.size();i++)
813 {
814 string line = debug_data[i];
815
816 cout << line << endl;
817
818 if (line.find (RosBootTest::ROS_SYSREG_CHECKPOINT) != string::npos)
819 {
820 line.erase (0, line.find (RosBootTest::ROS_SYSREG_CHECKPOINT) +
821 RosBootTest::ROS_SYSREG_CHECKPOINT.length ());
822 if (!strncmp(line.c_str (), m_Checkpoint.c_str (), m_Checkpoint.length ()))
823 {
824 state = DebugStateCPReached;
825 break;
826 }
827 m_Checkpoints.push_back (line);
828 }
829
830
831 if (line.find ("*** Fatal System Error") != string::npos)
832 {
833 cerr << "Blue Screen of Death detected" <<endl;
834 if (m_Checkpoints.size ())
835 {
836 cerr << "dumping list of reached checkpoints:" << endl;
837 do
838 {
839 string cp = m_Checkpoints[0];
840 m_Checkpoints.erase (m_Checkpoints.begin ());
841 cerr << cp << endl;
842 }while(m_Checkpoints.size ());
843 cerr << "----------------------------------" << endl;
844 }
845 if (i + 1 < debug_data.size () )
846 {
847 cerr << "dumping rest of debug log" << endl;
848 while(i < debug_data.size ())
849 {
850 string data = debug_data[i];
851 cerr << data << endl;
852 i++;
853 }
854 cerr << "----------------------------------" << endl;
855 }
856 state = DebugStateBSODDetected;
857 break;
858 }
859 else if (line.find ("Unhandled exception") != string::npos)
860 {
861 if (m_CriticalImage == "IGNORE")
862 {
863 ///
864 /// ignoring all user-mode exceptions
865 ///
866 continue;
867 }
868
869
870 if (i + 3 >= debug_data.size ())
871 {
872 ///
873 /// missing information is cut off -> try reconstruct at next call
874 ///
875 clear = false;
876 break;
877 }
878
879 ///
880 /// extract address from next line
881 ///
882
883 string address = debug_data[i+2];
884 string::size_type pos = address.find_last_of (" ");
885 if (pos == string::npos)
886 {
887 cerr << "Error: trace is not available (corrupted debug info" << endl;
888 continue;
889 }
890
891
892 address = address.substr (pos, address.length () - 1 - pos);
893
894 ///
895 /// extract module name
896 ///
897 string modulename = debug_data[i+3];
898
899 pos = modulename.find_last_of ("\\");
900 if (pos == string::npos)
901 {
902 cerr << "Error: trace is not available (corrupted debug info" << endl;
903 continue;
904 }
905
906 string appname = modulename.substr (pos + 1, modulename.length () - pos);
907 if (m_CriticalImage.find (appname) == string::npos && m_CriticalImage.length () > 1)
908 {
909 /// the application is not in the list of
910 /// critical apps. Therefore we ignore the user-mode
911 /// exception
912
913 continue;
914 }
915
916 pos = appname.find_last_of (".");
917 if (pos == string::npos)
918 {
919 cerr << "Error: trace is not available (corrupted debug info" << endl;
920 continue;
921 }
922
923 modulename = appname.substr (0, pos);
924
925 cerr << "UM detected" <<endl;
926 state = DebugStateUMEDetected;
927
928 ///
929 /// resolve address
930 ///
931 string result;
932 result.reserve (200);
933 #if 0
934 SymbolFile::resolveAddress (modulename, address, result);
935 cerr << result << endl;
936 #endif
937 ///
938 /// TODO
939 ///
940 /// resolve frame addresses
941
942
943
944 break;
945 }
946 }
947
948 if (clear && debug_data.size () > 5)
949 {
950 debug_data.clear ();
951 }
952 return state;
953 }
954 //---------------------------------------------------------------------------------------
955 bool RosBootTest::analyzeDebugData()
956 {
957 vector<string> vect;
958 size_t lines = 0;
959 bool write_log;
960 ofstream file;
961 bool ret = true;
962
963 if (m_DebugFile.length ())
964 {
965 remove(m_DebugFile.c_str ());
966 file.open (m_DebugFile.c_str ());
967 }
968
969 write_log = file.is_open ();
970 while(1)
971 {
972 size_t prev_count = vect.size ();
973 if (!m_DataSource->readSource (vect))
974 {
975 continue;
976 }
977 if (write_log)
978 {
979 for (size_t i = prev_count; i < vect.size (); i++)
980 {
981 string & line = vect[i];
982 file << line;
983 }
984 }
985
986 DebugState state = checkDebugData(vect);
987 if (state == DebugStateBSODDetected || state == DebugStateUMEDetected)
988 {
989 ret = false;
990 break;
991 }
992 else if (state == DebugStateCPReached)
993 {
994 break;
995 }
996 lines += (vect.size() -prev_count); //WTF?
997 }
998 if (write_log)
999 {
1000 file.close();
1001 }
1002
1003 return ret;
1004 }
1005 } // end of namespace Sysreg_