diff options
Diffstat (limited to 'src/build/debug')
-rw-r--r-- | src/build/debug/Hostboot/BlTrace.pm | 1 | ||||
-rwxr-xr-x | src/build/debug/Hostboot/Dump.pm | 14 | ||||
-rwxr-xr-x | src/build/debug/Hostboot/Gcov.pm | 464 | ||||
-rw-r--r-- | src/build/debug/Hostboot/GcovModuleUnload.pm | 69 | ||||
-rw-r--r-- | src/build/debug/Hostboot/PrintVMM.pm | 4 | ||||
-rwxr-xr-x | src/build/debug/Hostboot/_DebugFrameworkVMM.pm | 4 | ||||
-rwxr-xr-x | src/build/debug/eSEL.pl | 44 | ||||
-rwxr-xr-x | src/build/debug/ffdcExpander | 727 | ||||
-rw-r--r-- | src/build/debug/simics-debug-framework.py | 23 |
9 files changed, 1208 insertions, 142 deletions
diff --git a/src/build/debug/Hostboot/BlTrace.pm b/src/build/debug/Hostboot/BlTrace.pm index 5fd8baf18..9d9dc9988 100644 --- a/src/build/debug/Hostboot/BlTrace.pm +++ b/src/build/debug/Hostboot/BlTrace.pm @@ -83,6 +83,7 @@ my %traceText = ( "FA" => "PNOR Access getHBBSection findTOC no HBB section", "FB" => "main verifyBaseImage failed", "FC" => "main verifyBaseImage secure rom invalid", + "FD" => "PNOR Access findTOC handleMMIO LPC ERR returned", ); sub formatTrace diff --git a/src/build/debug/Hostboot/Dump.pm b/src/build/debug/Hostboot/Dump.pm index 705638aa2..90b445df9 100755 --- a/src/build/debug/Hostboot/Dump.pm +++ b/src/build/debug/Hostboot/Dump.pm @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2019 # [+] International Business Machines Corp. # # @@ -106,6 +106,13 @@ sub main $debug = 1; } + # Parse 'quiet' option. + my $quiet = 0; + if (defined $args->{"quiet"}) + { + $quiet = 1; + } + # Check for a different output directory my $outdir = "./"; if (defined $args->{"outdir"}) @@ -128,7 +135,7 @@ sub main open( OUTFH, ">$hbDumpFile" ) or die "can't open $hbDumpFile: $!\n"; binmode(OUTFH); - ::userDisplay "Using HRMOR=". ::getHRMOR() . "\n"; + ::userDisplay "Using HRMOR=". sprintf("0x%X",::getHRMOR()) . "\n"; # Read memory regions and output to file. foreach my $state (@{$memory_states{int $memstate}}) @@ -152,7 +159,7 @@ sub main $curlength = $length_remaining; } - ::userDisplay (sprintf "...%x@%x\n", $curlength, $curstart); + ::userDisplay (sprintf "...%x@%x\n", $curlength, $curstart) if !$quiet; my $data = ::readData($curstart, $curlength); seek OUTFH, $curstart, SEEK_SET; @@ -187,6 +194,7 @@ sub helpInfo options => { "outdir=<path>" => ["Output directory for dump file"], "debug" => ["More debug output."], + "quiet" => ["Less output."], }, ); } diff --git a/src/build/debug/Hostboot/Gcov.pm b/src/build/debug/Hostboot/Gcov.pm index 84df2f9f9..48e71d66b 100755 --- a/src/build/debug/Hostboot/Gcov.pm +++ b/src/build/debug/Hostboot/Gcov.pm @@ -1,4 +1,3 @@ -#!/usr/bin/perl # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # @@ -6,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2015 +# Contributors Listed Below - COPYRIGHT 2012,2019 # [+] International Business Machines Corp. # # @@ -23,15 +22,18 @@ # permissions and limitations under the License. # # IBM_PROLOG_END_TAG +#!/usr/bin/perl use strict; +use warnings; use File::Path; use File::Basename; +use IO::Handle; package Hostboot::Gcov; use Hostboot::_DebugFrameworkVMM qw(NotFound NotPresent getPhysicalAddr); use Exporter; -our @EXPORT_OK = ('main'); +our @EXPORT_OK = ('init', 'main', 'parseGcovInfo'); # NOTE: # @@ -50,26 +52,37 @@ our @EXPORT_OK = ('main'); use constant GCOV_EXTENDED_IMAGE_ADDRESS => (1024 * 1024 * 1024); use constant GCOV_INFO_HEAD_SYMBOLNAME => "_gcov_info_head"; +use constant GCOV_INFO_MAGIC_SYMBOLNAME => "_gcov_info_magic"; +use constant GCOV_MAGIC_IDENTIFIER => 0xbeefb055; -use constant GCOV_INFO_VERSION_OFFSET => 0; -use constant GCOV_INFO_NEXT_OFFSET => GCOV_INFO_VERSION_OFFSET + 8; -use constant GCOV_INFO_TIMESTAMP_OFFSET => GCOV_INFO_NEXT_OFFSET + 8; -use constant GCOV_INFO_FILENAME_OFFSET => GCOV_INFO_TIMESTAMP_OFFSET + 8; -use constant GCOV_INFO_NFUNCTIONS_OFFSET => GCOV_INFO_FILENAME_OFFSET + 8; -use constant GCOV_INFO_FUNCTIONS_OFFSET => GCOV_INFO_NFUNCTIONS_OFFSET + 8; -use constant GCOV_INFO_CTRMASK_OFFSET => GCOV_INFO_FUNCTIONS_OFFSET + 8; -use constant GCOV_INFO_COUNTS_OFFSET => GCOV_INFO_CTRMASK_OFFSET + 8; - -use constant GCOV_FNINFO_IDENT_OFFSET => 0; -use constant GCOV_FNINFO_CHECKSUM_OFFSET => GCOV_FNINFO_IDENT_OFFSET + 4; -use constant GCOV_FNINFO_NCTRS_OFFSET => GCOV_FNINFO_CHECKSUM_OFFSET + 4; +use constant GCOV_COUNTERS_492 => 9; +use constant SIZEOF_PTR => 8; +use constant SIZEOF_UINT64 => 8; -use constant GCOV_CTRINFO_COUNT_OFFSET => 0; -use constant GCOV_CTRINFO_VALUEPTR_OFFSET => GCOV_CTRINFO_COUNT_OFFSET + 8; - -use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461; use constant GCOV_FUNCTION_TAG => 0x01000000; use constant GCOV_COUNTERS_TAG => 0x01a10000; +use constant GCOV_PROGRAM_SUMMARY_TAG => 0xa3000000; + +use constant GCOV_GCDA_MAGIC_VALUE => 0x67636461; + +# See gcov.h for the structs (gcov_info, gcov_fn_info) from which +# these offsets derive + +use constant GCOV_INFO_VERSION_OFFSET_492 => 0; +use constant GCOV_INFO_NEXT_OFFSET_492 => 8; +use constant GCOV_INFO_TIMESTAMP_OFFSET_492 => 16; +use constant GCOV_INFO_FILENAME_OFFSET_492 => 24; +use constant GCOV_INFO_MERGE_OFFSET_492 => 32; +use constant GCOV_INFO_N_FUNCTIONS_OFFSET_492 => 32 + (9 * 8); +use constant GCOV_INFO_FUNCTIONS_OFFSET_492 => GCOV_INFO_N_FUNCTIONS_OFFSET_492 + 8; + +use constant GCOV_FN_INFO_IDENT_OFFSET_492 => 8; +use constant GCOV_FN_INFO_LINENO_CHECKSUM_OFFSET_492 => 12; +use constant GCOV_FN_INFO_CFG_CHECKSUM_OFFSET_492 => 16; +use constant GCOV_FN_INFO_CTR_INFO_OFFSET_492 => 24; + +use constant GCOV_CTR_INFO_NUM_OFFSET_492 => 0; +use constant GCOV_CTR_INFO_VALUES_OFFSET_492 => 8; # In memory format: # GCC creates a 'gcov_info' structure for each .o file. The info @@ -134,20 +147,43 @@ use constant GCOV_COUNTERS_TAG => 0x01a10000; # uint64_ts, containing instrumented counts, for the preceeding function. # Global of where we want the output to go. -our $output_dir; our $debug_mode; +our $hbicore_extended_bin_file; +our $hbicore_extended_bin_file_size; BEGIN { $debug_mode = 0; - $output_dir = ""; } -return 1; + +sub init +{ + # TODO: We need to figure out how to handle reading data from + # HBB/HBRT for when those are instrumented. One hurdle is being + # able to determine from an address what module it belongs to, + # because HBB/HBI/HBRT are not necessarily laid out in memory as + # they are in PNOR or anywhere else. + + my $hbicore_extended_bin_fname = "$ENV{SANDBOXROOT}/$ENV{SANDBOXNAME}/src/hbfw/img/hostboot_extended.bin"; + + userDebug("Opening " . $hbicore_extended_bin_fname . " for HBI\n"); + + unless (open($hbicore_extended_bin_file, "< $hbicore_extended_bin_fname")) { + ::userDisplay "Failed to open $hbicore_extended_bin_fname, exiting\n"; + return 0; + } + + binmode($hbicore_extended_bin_file); + + $hbicore_extended_bin_file_size = -s $hbicore_extended_bin_fname; + + return 1; +} sub main { - # Pick a new output directory based on the time. - $output_dir = sprintf "gcov.output.%d/", time; - File::Path::mkpath($output_dir); + if (!init()) { + return; + } # Find all the hostboot modules. my @modules = getModules(); @@ -160,7 +196,10 @@ sub main my $pwd = `pwd`; chomp $pwd; - ::userDisplay "GCOV output written to: $pwd/$output_dir\n"; + + close $hbicore_extended_bin_file or die; + + ::userDisplay("GCOV info extraction complete.\n"); } sub parseModuleGcov @@ -168,8 +207,23 @@ sub parseModuleGcov my $module = shift; ::userDisplay "Extracting GCOV info for ".$module."\n"; + # Search for magic symbol. + my ($gcov_magic, $unused) = + ::findSymbolAddress($module.GCOV_INFO_MAGIC_SYMBOLNAME); + + if (!defined($gcov_magic)) + { + $gcov_magic = 0; + } + + if ($gcov_magic == 0 || read32($gcov_magic, 1) != GCOV_MAGIC_IDENTIFIER) + { + ::userDisplay "\tgcov_magic at address " . (sprintf "0x%x", $gcov_magic) . " is incorrect. Skipped.\n"; + return; + } + # Search for gcov_info chain symbol. - my ($gcov_info, $unused) = + my ($gcov_info, $unused2) = ::findSymbolAddress($module.GCOV_INFO_HEAD_SYMBOLNAME); userDebug("\tFound info at 0x" . (sprintf "%x", $gcov_info) . "\n"); @@ -181,7 +235,7 @@ sub parseModuleGcov if (($gcov_info eq NotFound) || ($gcov_info eq NotPresent)) { - ::userDisplay "\tModule data is not present.\n"; + ::userDisplay "\tModule data is not present, module might have been unloaded, skipping.\n"; return; } } @@ -189,7 +243,7 @@ sub parseModuleGcov # Check that we found the gcov_info chain. if ($gcov_info == 0) { - ::userDisplay "\tUnable to find gcov_info chain. Skipped.\n"; + ::userDisplay "\tUnable to find gcov_info chain, module might hvae been unloaded. Skipping.\n"; return; } @@ -202,39 +256,44 @@ sub parseGcovInfo my $info_ptr = shift; return if (0 eq $info_ptr); - my $filename = readStr(read64($info_ptr + GCOV_INFO_FILENAME_OFFSET)); - userDebug("\tFile = ".$filename."\n"); + userDebug("\tReading filename pointer from offset " . (sprintf "0x%x", ($info_ptr + GCOV_INFO_FILENAME_OFFSET_492)) . "\n"); - my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET); - my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET); + my $filename_addr = read64($info_ptr + GCOV_INFO_FILENAME_OFFSET_492); - my $func_count = read32($info_ptr + GCOV_INFO_NFUNCTIONS_OFFSET); - userDebug("\tFunction Count = ".$func_count."\n"); + userDebug("\tReading filename from offset " . (sprintf "0x%x", $filename_addr) . "\n"); - my $funcs = read64($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET); - userDebug("\tFunc Address = ".(sprintf "%x", $funcs)."\n"); + my $filename = readStr($filename_addr); - my $ctrmask = read32($info_ptr + GCOV_INFO_CTRMASK_OFFSET); - if ($ctrmask % 2) # Check that COUNTER_ARCS is turned on. - { - # COUNTER_ARCS is on. Create file, find arc-values array, - # parse functions. + if ($filename) { + ::userDisplay("\tFile = ".$filename."\n"); - my $fd = createGcovFile($filename, $version, $stamp); + my $version = read32($info_ptr + GCOV_INFO_VERSION_OFFSET_492); + my $stamp = read32($info_ptr + GCOV_INFO_TIMESTAMP_OFFSET_492); - my $arcs_ptr = read64($info_ptr + GCOV_INFO_COUNTS_OFFSET + - GCOV_CTRINFO_VALUEPTR_OFFSET); - parseGcovFuncs($fd, $funcs, $func_count, $ctrmask, $arcs_ptr); + my $func_count = read32($info_ptr + GCOV_INFO_N_FUNCTIONS_OFFSET_492); + userDebug("\tFunction Count = ".$func_count."\n"); - close $fd; - } - else - { - userDebug("COUNTER_ARCS is missing!\n"); + my $funcs = read64($info_ptr + GCOV_INFO_FUNCTIONS_OFFSET_492, 1); + + if ($funcs ne NotFound && $funcs ne NotPresent) { + userDebug("\tFunc Address = ".(sprintf "0x%x", $funcs)."\n"); + + if ($version ne NotFound && $stamp ne NotFound && $func_count ne NotFound) { + my $fd = createGcovFile($filename, $version, $stamp); + + parseGcovFuncs($fd, $funcs, $func_count); + + close $fd or die $!; + } + } else { + userDebug("\tFunc Address is NULL, skipping\n"); + } + } else { + userDebug("\tCannot read filename, skipping\n"); } # Look for next .o in gcov_info chain, parse. - my $next = read64($info_ptr + GCOV_INFO_NEXT_OFFSET); + my $next = read64($info_ptr + GCOV_INFO_NEXT_OFFSET_492); parseGcovInfo($next); } @@ -243,62 +302,95 @@ sub parseGcovFuncs my $fd = shift; my $func_ptr = shift; my $func_count = shift; - my $mask = shift; - my $val_ptr = shift; - my $fn_offset = 0; + my $GCOV_COUNTERS_SUMMABLE_492 = 1; - # Need to calculate the number of counters based on the bits on in - # the 'mask'. This is used to determine the size of the function - # descriptor object. - my $counters = 0; - { - my $_mask = $mask; + print $fd pack('l', GCOV_PROGRAM_SUMMARY_TAG); # data.program.header.tag - while (0 != $_mask) - { - $counters++; - $_mask = ($_mask >> 1); - } - } + # for each GCOV_COUNTERS_SUMMABLE we have ten int32 (num, runs, and bitvector{8}) + # plus three int64 (sum, max, sum_max) i.e. 10 + 3*2 + # data.unit.header.length is the number of int32's we have following. + print $fd pack('l', 1 + $GCOV_COUNTERS_SUMMABLE_492 * (10 + 3 * 2)); # data.unit.header.length; - userDebug("\tCounters = ".$counters."\n"); + print $fd pack('l', 0); # data.summary:object.checksum (must be 0 according to docs) - # Round up the counter count to the nearest two for alignment of the - # function descriptor object. - if ($counters % 2) - { - $counters++; - } - my $func_size = GCOV_FNINFO_CHECKSUM_OFFSET + 4 * $counters; + for (my $i = 0; $i < $GCOV_COUNTERS_SUMMABLE_492; $i++) { + print $fd pack('l', 0); # data.summary:object.count-summary.num + print $fd pack('l', 0); # data.summary:object.count-summary.runs + print $fd pack('l', 0); # data.summary:object.count-summary.sum@lo + print $fd pack('l', 0); # data.summary:object.count-summary.sum@hi + print $fd pack('l', 0); # data.summary:object.count-summary.max@lo + print $fd pack('l', 0); # data.summary:object.count-summary.max@hi + print $fd pack('l', 0); # data.summary:object.count-summary.sum_max@lo + print $fd pack('l', 0); # data.summary:object.count-summary.sum_max@hi - userDebug("\tFunction size = ".$func_size."\n"); + print $fd pack('l8', (0) x 8); # data.summary:object.count-summary.histogram.bitvector{8} + } # Iterate through the functions and parse. for(my $function = 0; $function < $func_count; $function++) { - my $func_off = ($func_ptr + $func_size * $function); - my $ident = read32($func_off + GCOV_FNINFO_IDENT_OFFSET); - my $chksum = read32($func_off + GCOV_FNINFO_CHECKSUM_OFFSET); + userDebug("\tFunction $function of $func_count\n"); + + my $fn_info_ptr = read64($func_ptr + SIZEOF_PTR*$function, 1); + + if (($fn_info_ptr eq NotFound) || ($fn_info_ptr eq NotPresent)) + { + userDebug("\tCannot read function info pointer, skipping\n"); + next; + } + + userDebug("\tfn_info_ptr = " . (sprintf "%x", $fn_info_ptr) . "\n"); + + my $ident = read32($fn_info_ptr + GCOV_FN_INFO_IDENT_OFFSET_492, 1); + my $lineno_chksum = read32($fn_info_ptr + GCOV_FN_INFO_LINENO_CHECKSUM_OFFSET_492, 1); + my $cfg_chksum = read32($fn_info_ptr + GCOV_FN_INFO_CFG_CHECKSUM_OFFSET_492, 1); + my $ctr_info_ptr = $fn_info_ptr + GCOV_FN_INFO_CTR_INFO_OFFSET_492; + + if ($ident eq NotFound + || $lineno_chksum eq NotFound + || $cfg_chksum eq NotFound) + { + userDebug("Skipping because fn_info structure members are not readable\n"); + next; + } + + my $num_ctrs = read32($ctr_info_ptr + GCOV_CTR_INFO_NUM_OFFSET_492, 1); + my $ctrs_ptr = read64($ctr_info_ptr + GCOV_CTR_INFO_VALUES_OFFSET_492, 1); + + if ($ctrs_ptr eq NotFound || $num_ctrs eq NotFound) + { + userDebug("Skipping because counters length isn't mapped\n"); + next; + } - userDebug("Ident = ".(sprintf "%x", $ident)."\n"); - userDebug("Chksum = ".(sprintf "%x", $chksum)."\n"); + my $counters = readData($ctrs_ptr, SIZEOF_UINT64 * $num_ctrs); + + userDebug("Ident = ".(sprintf "0x%x", $ident)."\n"); + userDebug("lineno Chksum = ".(sprintf "0x%x", $lineno_chksum)."\n"); + userDebug("cfg Chksum = ".(sprintf "0x%x", $cfg_chksum)."\n"); + userDebug("Num counters = ".(sprintf "%d", $num_ctrs)."\n"); + userDebug("ctrs_ptr = ".(sprintf "0x%x", $ctrs_ptr)."\n"); + + if (($counters eq NotFound) || ($counters eq NotPresent)) + { + userDebug("Skipping because counter data not resident in memory\n"); + next; + } print $fd pack('l', GCOV_FUNCTION_TAG); # Write function tag. - print $fd pack('l', 2); # Write size = 2. + print $fd pack('l', 3); # Write size = 3. print $fd pack('l', $ident); # Write ident. - print $fd pack('l', $chksum); # Write checksum. - - my $nctr_val = read32($func_off + GCOV_FNINFO_NCTRS_OFFSET); - userDebug("N-Counters = ".$nctr_val."\n"); + print $fd pack('l', $lineno_chksum); # Write checksum. + print $fd pack('l', $cfg_chksum); # Write checksum. print $fd pack('l', GCOV_COUNTERS_TAG); # Write counter tag. - print $fd pack('l', $nctr_val * 2); # Write counter length. + print $fd pack('l', $num_ctrs * 2); # Write counter length. # Read each counter value, output. # Read as one big block for performance reasons. - my $counters = readData($val_ptr + 8*($fn_offset), 8 * $nctr_val); - for(my $v_idx = 0; $v_idx < $nctr_val; $v_idx++) + + for(my $v_idx = 0; $v_idx < $num_ctrs; $v_idx++) { my $val = substr $counters, 0, 8; $counters = substr $counters, 8; @@ -306,15 +398,34 @@ sub parseGcovFuncs $val = unpack("Q", $val); userDebug("\tValue[$v_idx] = ".$val."\n"); + my $preex_read_low = read($fd, my $low_word, 4); + my $preex_read_high = read($fd, my $high_word, 4); + + if (!defined($preex_read_low) or !(defined($preex_read_high))) { + die; + } + my $preex_read = $preex_read_low + $preex_read_high; + + if ($preex_read == 8) + { + my $preex_val = (unpack("l", $high_word) << 32) | unpack("l", $low_word); + + $val += $preex_val; + } + + if ($preex_read > 0) + { + seek $fd, -$preex_read, 1; + } + else + { + seek $fd, 0, 2; + } + print $fd pack('l', $val & 0xFFFFFFFF); # Write lower word. print $fd pack('l', $val >> 32) ; # Write upper word. } - - # We used up a number of counters, so move the offset forward for - # the next function. - $fn_offset += $nctr_val; } - } # The *.gcda filename found in the gcov_info struct is an absolute path to @@ -330,16 +441,25 @@ sub createGcovFile my $version = shift; my $stamp = shift; - # Change *./../obj/ into obj/, prepend output_dir. - $name =~ s/.*\/obj\//obj\//; - $name = $output_dir.$name; - - # Make sure everything after 'obj/' exists (create subdirs). - my $dir = File::Basename::dirname($name); - File::Path::mkpath($dir); + # if the file exists then we update it, if not we create it + my $GCOVFILE; + if (-e $name) + { + if (!open($GCOVFILE, "+<$name")) + { + ::userDisplay("Failed to open $name for reading/writing gcov information\n"); + die; + } + } + else + { + if (!open($GCOVFILE, "+>$name")) + { + ::userDisplay("Failed to open $name for writing gcov information\n"); + die; + } + } - # Create file. - open(my $GCOVFILE, "> $name"); binmode($GCOVFILE); # Write out header. @@ -377,6 +497,22 @@ sub isVirtualAddress return ($addr >= GCOV_EXTENDED_IMAGE_ADDRESS); } +sub readExtImage +{ + my $addr = shift; + my $amount = shift; + + if ($addr + $amount >= $hbicore_extended_bin_file_size) { + return NotFound; + } + + seek $hbicore_extended_bin_file, $addr, 0; + + read $hbicore_extended_bin_file, my ($contents), $amount; + + return $contents; +} + # Utility to read a block of data from eithr memory or using the extended # image file as a fallback if not present in memory. use constant PAGESIZE => 4096; @@ -401,8 +537,13 @@ sub readData my $paddr = getPhysicalAddr($addr); if ((NotFound eq $paddr) || (NotPresent eq $paddr)) { - $paddr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS; - $result = $result.::readExtImage($paddr, $amount); + my $tmpdata = readExtImage($addr - GCOV_EXTENDED_IMAGE_ADDRESS, $amount); + + if ($tmpdata eq NotFound) { + return NotFound; + } + + $result = $result . $tmpdata; } else { @@ -423,14 +564,27 @@ sub readData sub read64 { my $addr = shift; + my $fallback = shift; + my $old_addr = $addr; if (isVirtualAddress($addr)) { $addr = getPhysicalAddr($addr); if ((NotFound eq $addr) || (NotPresent eq $addr)) { + userDebug((sprintf "0x%x", $old_addr). " not translatable 2\n"); + + if (!$fallback) { + return NotFound; + } + $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS; - my $result = ::readExtImage($addr, 8); + my $result = readExtImage($addr, 8); + + if ($result eq NotFound) { + return NotFound; + } + if (::littleendian()) { $result = reverse($result); } return unpack("Q", $result); } @@ -444,14 +598,25 @@ sub read64 sub read32 { my $addr = shift; + my $fallback = shift; + my $old_addr = $addr; if (isVirtualAddress($addr)) { $addr = getPhysicalAddr($addr); if ((NotFound eq $addr) || (NotPresent eq $addr)) { + userDebug((sprintf "0x%x", $old_addr). "not translatable 3\n"); + + if (!$fallback) { + return NotFound; + } + $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS; - my $result = ::readExtImage($addr, 4); + my $result = readExtImage($addr, 4); + if ($result eq NotFound) { + return NotFound; + } if (::littleendian()) { $result = reverse($result); } return unpack("L", $result); } @@ -471,8 +636,10 @@ sub read8 $addr = getPhysicalAddr($addr); if ((NotFound eq $addr) || (NotPresent eq $addr)) { + userDebug((sprintf "0x%x", $addr). "not translatable 4\n"); + $addr = $old_addr - GCOV_EXTENDED_IMAGE_ADDRESS; - my $result = ::readExtImage($addr, 1); + my $result = readExtImage($addr, 1); return unpack("C", $result); } } @@ -486,31 +653,82 @@ sub readStr { my $addr = shift; my $old_addr = $addr; + if (isVirtualAddress($addr)) { - $addr = $addr - GCOV_EXTENDED_IMAGE_ADDRESS; + userDebug("it is a virtual address, addr is " . (sprintf "%x", $addr) . "\n"); + my $phys_addr = getPhysicalAddr($addr); - # Virtual address, so need to read 1 byte at a time from the file. - my $string = ""; - my $byte = 0; - - do + if ((NotFound eq $phys_addr) || (NotPresent eq $phys_addr)) { - $byte = ::readExtImage($addr,1); - $addr = $addr + 1; + userDebug("Translation not found, reading from pnor\n"); + # Virtual address, so need to read 1 byte at a time from the file. + my $string = ""; + my $byte = 0; - if (unpack("C",$byte) eq 0) + do { - return $string; - } + $byte = readExtImage($addr - GCOV_EXTENDED_IMAGE_ADDRESS, 1); - $string = $string.$byte; + if ($byte eq NotFound) + { + return ""; + } - } while (1) + $addr = $addr + 1; + + if (unpack("C",$byte) eq 0) + { + return $string; + } + + $string = $string.$byte; + } while (1); + } + else + { + my $string = ""; + my $byte = 0; + + do + { + if (($addr & 0xfff) == 0) + { + # we have to recalculate the physical address + # whenever we cross a page boundary + $phys_addr = getPhysicalAddr($addr); + + if ((NotFound eq $phys_addr) || (NotPresent eq $phys_addr)) + { + userDebug((sprintf "0x%x", $addr). "not translatable 10\n"); + return ""; + } + } + + $byte = read8($phys_addr); + + if ($byte eq NotFound) + { + userDebug("Cannot read byte from physical address\n"); + return ""; + } + + $addr += 1; + $phys_addr += 1; + + if ($byte != 0) + { + $string = $string . pack("C", $byte); + } + } while ($byte != 0); + + return $string; + } } else { - ::readStr($addr); + userDebug("it is NOT a virtual address\n"); + return ::readStr($addr); } } @@ -531,3 +749,5 @@ sub helpInfo intro => [ "Extracts the GCOV information."], ); } + +1; # Last expression in a perl module must be truthy. diff --git a/src/build/debug/Hostboot/GcovModuleUnload.pm b/src/build/debug/Hostboot/GcovModuleUnload.pm new file mode 100644 index 000000000..1a411cc3c --- /dev/null +++ b/src/build/debug/Hostboot/GcovModuleUnload.pm @@ -0,0 +1,69 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/debug/Hostboot/GcovModuleUnload.pm $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +#!/usr/bin/perl +use strict; +use File::Path; +use File::Basename; + +package Hostboot::GcovModuleUnload; +use Hostboot::Gcov qw(parseGcovInfo init); + +use Exporter; +our @EXPORT_OK = ('main', 'parseGcovInfo'); + +sub main +{ + my ($packName, $args) = @_; + + my $gcov_info_address = $args->{"address"}; + + ::userDisplay("Dumping gcov module info from " . (sprintf "0x%x", $gcov_info_address) . "\n"); + + if ($gcov_info_address <= 0) { + ::userDisplay("Can't dump from NULL\n"); + return -1; + } + + if (!Hostboot::Gcov::init()) { + return -2; + } + + Hostboot::Gcov::parseGcovInfo($gcov_info_address); + + ::userDisplay("Done.\n"); + + return 0; +} + +# Debug tool help info. +sub helpInfo +{ + my %info = ( + name => "GcovModuleUnload", + intro => [ "Extracts the GCOV information from modules as they are being unloaded."], + ); +} + +1; # Last expression in a perl module must be truthy. diff --git a/src/build/debug/Hostboot/PrintVMM.pm b/src/build/debug/Hostboot/PrintVMM.pm index 476262d93..57a57a9e2 100644 --- a/src/build/debug/Hostboot/PrintVMM.pm +++ b/src/build/debug/Hostboot/PrintVMM.pm @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2020 # [+] International Business Machines Corp. # # @@ -73,7 +73,7 @@ sub main my @segment_manager_addr = ::findPointer("SGMNTMGR", "Singleton<SegmentManager>::instance()::instance"); - if (not defined @segment_manager_addr) + if (not @segment_manager_addr) { ::userDisplay " VirtualToPhy: Cannot find Device Segment symbol.\n"; die; } diff --git a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm index 128df4ec7..ca323bd32 100755 --- a/src/build/debug/Hostboot/_DebugFrameworkVMM.pm +++ b/src/build/debug/Hostboot/_DebugFrameworkVMM.pm @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2018 +# Contributors Listed Below - COPYRIGHT 2012,2020 # [+] International Business Machines Corp. # # @@ -404,7 +404,7 @@ sub getPhysicalAddr "Singleton<SegmentManager>::instance()::instance"); - if (not defined @segment_manager_addr) + if (not @segment_manager_addr) { ::userDisplay " VirtualToPhy: Cannot find SegmentManager symbol.\n"; return NotFound; diff --git a/src/build/debug/eSEL.pl b/src/build/debug/eSEL.pl index ddce72f50..ed9ef2335 100755 --- a/src/build/debug/eSEL.pl +++ b/src/build/debug/eSEL.pl @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2017,2018 +# Contributors Listed Below - COPYRIGHT 2017,2019 # [+] International Business Machines Corp. # # @@ -588,6 +588,11 @@ sub DecodeObmcEselData $timestamp_found = 1; last; } + elsif($next_line =~ /timestamp/) + { + $timestamp_found = 2; + last; + } elsif($next_line =~ /ESEL/ or $next_line =~ /20 00 04/) # found the next ESEL { @@ -601,16 +606,35 @@ sub DecodeObmcEselData if($timestamp_found) { - # strip the "Timestamp", commas, spaces, and the newline - $next_line =~ s/"Timestamp"://g; - $next_line =~ s/,//g; - $next_line =~ s/ //g; - chomp $next_line; - - # convert to date/time (we are given the timestamp in ms, so divide - # by 1000 to get s). - $timestamp = + if($timestamp_found == 1) + { + # strip the "Timestamp", commas, spaces, and the newline + $next_line =~ s/"Timestamp"://g; + $next_line =~ s/,//g; + $next_line =~ s/ //g; + chomp $next_line; + + # convert to date/time (we are given the timestamp in ms, so divide + # by 1000 to get s). + $timestamp = strftime("%m/%d/%Y %H:%M:%S", localtime($next_line/1000)); + } + elsif($timestamp_found == 2) + { + # Field format :: "timestamp": "2019-10-31 10:20:50" + $next_line =~ s/"timestamp"://g; + $next_line =~ s/"//g; #drop the quotes + my @tmp1 = split( " ", $next_line ); #break the date and time apart + my @df = split( /-/, $tmp1[0] ); #break up the date fields + # Convert to :: 11/05/2019 12:25:41 + $timestamp = "$df[1]/$df[2]/$df[0] $tmp1[1]"; + ($debug) && print "timestamp> $timestamp \n"; + } + else + { + die "Bad timestamp\n"; + } + ($debug) && print "Timestamp for ESEL #$esel_record_count:$next_line\n"; ($debug) && print "Decoded timestamp for ESEL #$esel_record_count:$timestamp\n"; diff --git a/src/build/debug/ffdcExpander b/src/build/debug/ffdcExpander new file mode 100755 index 000000000..95f7c970f --- /dev/null +++ b/src/build/debug/ffdcExpander @@ -0,0 +1,727 @@ +#!/bin/sh +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/debug/ffdcExpander $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,2020 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + + +############################################################################### +# @file ffdcExpander +# This shell script takes a SYSDUMP file and extracts various debug elements. +# The caller has the option to post artifacts to a defect. +# +# The starting point for this script is at the end of the file. +############################################################################### + +############################################################################### +# Some helpful constants +############################################################################### +FFDC_GUNZIP_TOOL="/bin/gunzip" +FFDC_DUMP_PARSER="/esw/bin/dumpparser" + + +############################################################################### +# Some global variables +############################################################################### +FFDC_3RD_PARTY_SCRIPT_DIR="/gsa/ausgsa/projects/h/hostboot/optools/" # Location of files updatecq.pl, cqcmd.pl and Slurp.pm +FFDC_SCRIPT_NAME=$(basename "${0}") # Cache the name of this script +FFDC_SCRIPT_DIR=$(dirname "${0}") # Location of this script and supporting scripts +FFDC_SCRIPT_DIR="${FFDC_SCRIPT_DIR}/" +FFDC_SYSDUMP_FILE_GZ="" # format SYSDUMP.13020B8.20000001.20190725181300.gz +FFDC_SYSDUMP_FILE="" # format SYSDUMP.13020B8.20000001.20190725181300 +FFDC_HB_DUMP_FILE=""; # format hb.dump.SYSDUMP.13020B8.20000001.20190725181300 +FFDC_FSP_DRIVER_DIR="" # format '/esw/fips922/Builds/b0724a_1931.922' +FFDC_FSP_DRIVER="" # format 'fips922', 'fips950' , etc +FFDC_FSP_BUILD_TAG="" # format b0724a_1931.922 +FFDC_DEFECT_NUM="" # format 'SW123456', 'sw123456', 'Sw123456' or 'sW123456' +FFDC_DEFECT_NUM_CHARS="8" # The number of characters expected in defect including 'SW' +FFDC_CWD="`pwd -P`/" # The current working directory +FFDC_DEST_DIR="${FFDC_CWD}" # The destination directory of artifacts, default to CWD +FFDC_CQ_USER="" # The CQ user ID +FFDC_CQ_PASS="" # The CQ password +FFDC_RETURN_VALUE="0" # The return value. Default to success '0' +FFDC_TIME_STAMP="" # A time stamp is generated to make the files unique + +############################################################################### +# Print the usage line +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _ffdcUsage_() +{ + echo "" + echo " Usage: ${FFDC_SCRIPT_NAME} -g <FFDC_SYSDUMP_FILE.gz> | -s <FFDC_SYSDUMP_FILE> |" + echo " -h <HB_FFDC_SYSDUMP_FILE> -b <FSP_BUILD_TAG>" + echo " [ OPTIONS ]" + echo "" + echo " OPTIONS: [ -d <DEST_DIR> ] [ -a <DEFECT_NUM> ] [ -t ]" + echo " -t attach a time stamp to the artifacts" + echo "" + echo " Examples: ${FFDC_SCRIPT_NAME} -g SYSDUMP.13020B8.20000001.20190725181300.raw67117184.gz" + echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184" + echo " ${FFDC_SCRIPT_NAME} -h hb.dump.SYSDUMP.13020B8.20000001.20190725181300 -b b0724a_1931.922" + echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184 -a SW123456 -t" + echo " ${FFDC_SCRIPT_NAME} -s SYSDUMP.13020B8.20000001.20190725181300.raw67117184 -d dir" + echo "" + return 0; # Return success +} + +############################################################################### +# @brief Get the caller's options and validate them +# +# @param [in] $* - All of the caller's inputs after name of script +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _getUserInputOptionsAndValidate_() +{ + # Default caller options + CALLER_SYSDUMP_FILE_GZ="" + CALLER_SYSDUMP_FILE="" + CALLER_HB_DUMP_FILE="" + CALLER_FSP_BUILD_TAG="" + CALLER_DEST_DIR="" + CALLER_REQUESTS_TIME_STAMP="" + + # Get caller's options + FFDC_RETURN_VALUE="22" # Default to 'Invalid argument' + MANDATORY_OPTION_CHOSEN="0" + echo "" + while getopts ts:g:h:b:d:a: option + do + if [ -n "${option}" ]; then + FFDC_RETURN_VALUE="0"; # Found an argument + fi + case "${option}" + in + t) CALLER_REQUESTS_TIME_STAMP=1;; + s) CALLER_SYSDUMP_FILE=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";; + g) CALLER_SYSDUMP_FILE_GZ=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";; + h) CALLER_HB_DUMP_FILE=${OPTARG}; MANDATORY_OPTION_CHOSEN="1";; + b) CALLER_FSP_BUILD_TAG=${OPTARG};; + d) CALLER_DEST_DIR=${OPTARG};; + a) CALLER_DEFECT_NUM=${OPTARG};; + \?) FFDC_RETURN_VALUE=22;; + :) FFDC_RETURN_VALUE=22;; + esac + done + + # If call to getopts not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + _ffdcUsage_ + return $FFDC_RETURN_VALUE; + fi + + # Check for a valid option chosen + if [ "$MANDATORY_OPTION_CHOSEN" == "0" ]; then + _ffdcUsage_ + return $FFDC_RETURN_VALUE; + fi + + # Check for nonsensical options + if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then + echo " ERROR: Incompatible options: options -g and -s can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ] && [ -n "${CALLER_HB_DUMP_FILE}" ]; then + echo " ERROR: Incompatible options: options -g and -h can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Incompatible options: options -g and -b can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Incompatible options: options -s and -b can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -n "${CALLER_SYSDUMP_FILE}" ] && [ -n "${CALLER_HB_DUMP_FILE}" ]; then + echo " ERROR: Incompatible options: options -s and -h can't be used together"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + # Verify that if caller is passing in a HB dump file, they must supply the build tag + if [ -n "${CALLER_HB_DUMP_FILE}" ] && [ -z "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Must supply a -b option with the -h option"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + if [ -z "${CALLER_HB_DUMP_FILE}" ] && [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + echo " ERROR: Must supply a -h option with the -b option"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi + + # If caller requests a time stamp, option -t, then oblige + if [ "$CALLER_REQUESTS_TIME_STAMP" == "1" ]; then + FFDC_TIME_STAMP=$(date +%s) + FFDC_TIME_STAMP="_${FFDC_TIME_STAMP}" + fi + + # If caller supplied a gzippped SYSDUMP file, option -g, then confirm it exists + if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then + if [ ! -e "${CALLER_SYSDUMP_FILE_GZ}" ]; then + echo " gzipped SYSDUMP file (${CALLER_SYSDUMP_FILE_GZ}) not found"; + return 22; # return 'Invalid argument' + fi + + # Check if file given is a gzipped file, verify that it ends in .gz + if [[ "${CALLER_SYSDUMP_FILE_GZ}" != *\.gz ]]; then + echo " "; + echo " WARNING: It appears that file (${CALLER_SYSDUMP_FILE_GZ}) is not a gzipped file" + while true; do + echo "" + read -p " Do you wish to continue with file [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " ¯\_(?)_/¯ exiting ..."; echo ""; return 22;; # return 'Invalid argument' + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + fi + + # Save caller's gzippped SYSDUMP file, option -g + FFDC_SYSDUMP_FILE_GZ="$CALLER_SYSDUMP_FILE_GZ" + + ## Add an absolute path to the gzipped file, if not already an absolute path + # Check the first character to see if starting with absolute path + FIRST_CHAR="${FFDC_SYSDUMP_FILE_GZ:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_SYSDUMP_FILE_GZ="${FFDC_CWD}${FFDC_SYSDUMP_FILE_GZ}" + fi + fi # end if [ -n "${CALLER_SYSDUMP_FILE_GZ}" ]; then + + + # If caller supplied a SYSDUMP file, option -f, then confirm it exists + if [ -n "${CALLER_SYSDUMP_FILE}" ]; then + if [ ! -e "${CALLER_SYSDUMP_FILE}" ]; then + echo " SYSDUMP file (${CALLER_SYSDUMP_FILE}) not found"; + return 22; # return 'Invalid argument' + fi + + # Save caller's SYSDUMP file, option -f + FFDC_SYSDUMP_FILE="${CALLER_SYSDUMP_FILE}" + + ## Add an absolute path to the gzipped file, if not already an absolute path + # Check the first character to see if starting with absolute path + FIRST_CHAR="${FFDC_SYSDUMP_FILE:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_SYSDUMP_FILE="${FFDC_CWD}${FFDC_SYSDUMP_FILE}" + fi + fi # end if [ -n "${CALLER_SYSDUMP_FILE}" ]; then + + + # If caller supplied a HB dump file, option -h, then confirm it exists + if [ -n "${CALLER_HB_DUMP_FILE}" ]; then + if [ ! -e "${CALLER_HB_DUMP_FILE}" ]; then + echo " HB dump file (${CALLER_HB_DUMP_FILE}) not found"; + return 22; # return 'Invalid argument' + fi + + # Save caller's HB dump file, option -h + FFDC_HB_DUMP_FILE="${CALLER_HB_DUMP_FILE}" + + ## Add an absolute path to the HB dump file, if not already an absolute path + # Check the first character to see if starting with absolute path + FIRST_CHAR="${FFDC_HB_DUMP_FILE:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_HB_DUMP_FILE="${FFDC_CWD}${FFDC_HB_DUMP_FILE}" + fi + fi # end if [ -n "${CALLER_HB_DUMP_FILE}" ]; then + + + # If caller supplied an FSP build tag, option -b, then validate it + if [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + # Extrapolate the FSP Build Release from the FSP build tag + if [[ "${CALLER_FSP_BUILD_TAG}" = *"."* ]]; then + FIPS_VERS=$(echo ${CALLER_FSP_BUILD_TAG} | \cut -d"." -f 2) + if [ -n "${FIPS_VERS}" ]; then + FFDC_FSP_DRIVER="fips${FIPS_VERS}" + else + echo " "; + echo " Build tag (${CALLER_FSP_BUILD_TAG}) appears to be in wrong format"; + echo " Cannot extrapolate the FIPS version from build tag"; + return 22; # return 'Invalid argument' + fi + else + echo " "; + echo " Build tag (${CALLER_FSP_BUILD_TAG}) appears to be in wrong format"; + echo " Cannot extrapolate the FIPS version from build tag"; + _ffdcUsage_ + return 22; # return 'Invalid argument' + fi # end if [[ "${CALLER_FSP_BUILD_TAG}" = *"."* ]]; then + + # Save the caller's FSP build tag + FFDC_FSP_BUILD_TAG="${CALLER_FSP_BUILD_TAG}" + + # Save the caller's FSP build tag with the directory to it + FFDC_FSP_DRIVER_DIR="/esw/${FFDC_FSP_DRIVER}/Builds/${CALLER_FSP_BUILD_TAG}" + fi # end if [ -n "${CALLER_FSP_BUILD_TAG}" ]; then + + # If caller supplied a defect, option -a, just confirm it is in the correct + # nomenclature and format + if [ -n "${CALLER_DEFECT_NUM}" ]; then + + FFDC_DEFECT_NUM=$(echo ${CALLER_DEFECT_NUM^^}) + if [[ $FFDC_DEFECT_NUM != SW* ]]; then + echo " ERROR: software defect must be preceded with 'SW'"; + echo " "; + return 22; # return 'Invalid argument' + fi + + NUM_CHARS=${#FFDC_DEFECT_NUM} + if [[ "${NUM_CHARS}" -ne "${FFDC_DEFECT_NUM_CHARS}" ]]; then + echo " ERROR: software defect must have a total of ${FFDC_DEFECT_NUM_CHARS} characters, including 'SW'"; + echo " "; + return 22; # return 'Invalid argument' + fi + + INTEGER_PART=$(echo ${CALLER_DEFECT_NUM} | sed "s/^SW//g") + REG_EXP='^[0-9]+$' + if ! [[ $INTEGER_PART =~ $REG_EXP ]]; then + echo " ERROR: the characters (${INTEGER_PART}) that follow 'SW' must be an integer"; + echo " "; + return 22; # return 'Invalid argument' + fi + + # Prompt username and password for CQ + _queryUserPassword_; + FFDC_RETURN_VALUE=$? + if [ "${FFDC_RETURN_VALUE}" != "0" ]; then + echo "" + return ${FFDC_RETURN_VALUE}; # Return failure + fi + fi # end # If caller supplied a defect, option -a, ... + + + # If caller supplied a destination directory, option -d, then confirm it + # exists and determine if it is a relative path or absolute path + if [ -n "${CALLER_DEST_DIR}" ]; then + if [ ! -e "${CALLER_DEST_DIR}" ]; then + echo " Destination directory (${CALLER_DEST_DIR}) not found"; + while true; do + echo "" + read -p " Do you wish to ceate it [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " ¯\_(?)_/¯ exiting ..."; echo ""; return 22;; # return 'Invalid argument' + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + + mkdir -p ${CALLER_DEST_DIR} + FFDC_RETURN_VALUE=$? + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + echo "" + return $FFDC_RETURN_VALUE; # Propagate failure + fi + echo " Destination directory (${CALLER_DEST_DIR}) created"; + echo "" + fi + + # Save caller's destination directory option + FFDC_DEST_DIR="$CALLER_DEST_DIR" + NUM_CHARS=$((${#FFDC_DEST_DIR}-1)) + LAST_CHAR="${FFDC_DEST_DIR:$NUM_CHARS:1}" + # If last char not a '/' then append a '/' + if [ "${LAST_CHAR}" != "/" ]; then + FFDC_DEST_DIR="${FFDC_DEST_DIR}/" + fi + + ## Add an absolute path to the destination directory, if it is not + ## already an absolute path. + # Inspect the first character to determine path is absolute or not + FIRST_CHAR="${FFDC_DEST_DIR:0:1}" + # If first char not a '/' then append an absolute path + if [ "${FIRST_CHAR}" != "/" ]; then + FFDC_DEST_DIR="${FFDC_CWD}${FFDC_DEST_DIR}" + fi + fi # end if [ -n "${CALLER_DEST_DIR}" ]; then + + return 0; # Return success +} + +############################################################################### +# @brief Query caller for user name and password +############################################################################### +function _queryUserPassword_() +{ + if [ -n "${FFDC_DEFECT_NUM}" ]; then + read -p 'CQ Username: ' FFDC_CQ_USER + read -sp 'CQ Password: ' FFDC_CQ_PASS + fi + + return 0; +} + +############################################################################### +# @brief Unzip the system dump file +# +# Example: unzip SYSDUMP.13020B8.20000001.20190725181300.raw67117184.gz => +# SYSDUMP.13020B8.20000001.20190725181300.raw67117184 +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _unzipSysDumpFile_() +{ + # Verify that we can get to the dumpparser script + if [[ ! -e "${FFDC_GUNZIP_TOOL}" ]]; then + echo "" + echo " ERROR: Could not find gunzip tool ${FFDC_GUNZIP_TOOL}" + echo "" + return 2; # Return 'No such file or directory' + fi + + ## Extrapolate the SYSDUMP file from the gzipped file + # Remove any directories and only get the file name + FFDC_SYSDUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE_GZ} | awk -F / '{ print $NF }') + # Remove the '.gz' from the gzipped file + FFDC_SYSDUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE} | sed "s/\.gz$//") + # Prepend the caller's directory + FFDC_SYSDUMP_FILE="${FFDC_DEST_DIR}${FFDC_SYSDUMP_FILE}" + + # Check if the SYSDUMP file already exists, if so, ask caller if they wish + # to overwrite it + if [[ -e "${FFDC_SYSDUMP_FILE}" ]]; then + echo "" + echo " SYSDUMP file (${FFDC_SYSDUMP_FILE}) already exists ..." + while true; do + echo "" + read -p " Do you wish to override the file and continue [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " Skipping call to ${FFDC_GUNZIP_TOOL} ..."; echo ""; return 0;; + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + fi + + # Unzip the gzipped SYSDUMP file + echo "" + echo " ${FFDC_GUNZIP_TOOL} -c ${FFDC_SYSDUMP_FILE_GZ} > ${FFDC_SYSDUMP_FILE}" + `${FFDC_GUNZIP_TOOL} -c ${FFDC_SYSDUMP_FILE_GZ} > ${FFDC_SYSDUMP_FILE}` + FFDC_RETURN_VALUE=$? + if [ "${FFDC_RETURN_VALUE}" != "0" ]; then + echo "" + return ${FFDC_RETURN_VALUE}; # Return failure + fi + + return 0; # Return success +} + + +############################################################################### +# @brief Extract the HB system dump file from the SYSDUMP file +# +# Example: /esw/bin/dumpparser -extMem SYSDUMP.13020B8.20000001.20190725181300.raw67117184 => +# hb.dump.SYSDUMP.13020B8.20000001.20190725181300 +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function _extractHbSysDumpFile_() +{ + # Verify that we can get to the dump parser script + if [[ ! -e "${FFDC_DUMP_PARSER}" ]]; then + echo "" + echo " ERROR: Could not find parser ${FFDC_DUMP_PARSER}" + echo "" + return 2; # Return 'No such file or directory' + fi + + ## Extrapolate the HB dump file name from the SYSDUMP file + # Remove any directories and only get the file name + FFDC_HB_DUMP_FILE=$(echo ${FFDC_SYSDUMP_FILE} | awk -F / '{ print $NF }') + # Remove the .gz from the SYSDUMP, if it exists + FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/\.gz$//") + # Remove the postpended '.rawxxx' from the SYSDUMP file, if it exists + FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/\.raw.*$//") + # Prepend 'hb.dump.' to file + FFDC_HB_DUMP_FILE=$(echo ${FFDC_HB_DUMP_FILE} | sed "s/^/hb.dump./") + # Prepend the caller's directory + FFDC_HB_DUMP_FILE="${FFDC_DEST_DIR}${FFDC_HB_DUMP_FILE}" + + # Extract the the FSP build info from the SYSDUMP file + FSP_BUILD_INFO=$(${FFDC_DUMP_PARSER} -a ${FFDC_SYSDUMP_FILE} | grep "Driver is" | awk '{ print $4 }') + + # Extract the the FSP driver info from the FSP build info + FFDC_FSP_DRIVER=$(echo ${FSP_BUILD_INFO} | awk -F / '{ print $1 }') + + # Extract the FSP build tag info from the FSP build info + FFDC_FSP_BUILD_TAG=$(echo ${FSP_BUILD_INFO} | awk -F / '{ print $2 }') + + # Create a path to FSP build driver info + FFDC_FSP_DRIVER_DIR="/esw/${FFDC_FSP_DRIVER}/Builds/${FFDC_FSP_BUILD_TAG}" + + # Check if the HB dump file already exists, if so, ask caller if they wish + # to overwrite it + if [[ -e "${FFDC_HB_DUMP_FILE}" ]]; then + echo "" + echo " HB system dump file (${FFDC_HB_DUMP_FILE}) already exists ..." + while true; do + echo "" + read -p " Do you wish to override the file and continue [Y/N] ? " yn + case $yn in + [Yy] ) break;; + [Nn] ) echo " Skipping call to ${FFDC_DUMP_PARSER} ..."; return 0;; + * ) echo " Please answer [Y]es or [N]o.";; + esac + done + fi + + # Change directory to user supplied directory + \cd -P ${FFDC_DEST_DIR} ; + + # Parse out the HB dump file using the dump parser + echo "" + echo " ${FFDC_DUMP_PARSER} -extMem ${FFDC_SYSDUMP_FILE}" + ${FFDC_DUMP_PARSER} -extMem ${FFDC_SYSDUMP_FILE} + + FFDC_RETURN_VALUE=$? + if [ "${FFDC_RETURN_VALUE}" != "0" ]; then + # Return back to current working directory + \cd -P ${FFDC_CWD} + echo "" + return ${FFDC_RETURN_VALUE}; # Return failure + fi + + echo " Created file ${FFDC_HB_DUMP_FILE}" + + # Return back to current working directory + \cd -P ${FFDC_CWD} + + return 0; # Return success +} + + +############################################################################### +# @brief Set the path to the fsp-trace tool +# +# @return 0 +############################################################################### +function _setFSPTracePath_() +{ + FFDC_FSP_PATH="/esw/$FFDC_FSP_DRIVER/Builds/built/images/nfs/x86.nfp/bin/" + echo "" + echo " Using fsp-trace tool: ${FFDC_FSP_PATH}fsp-trace" + PATH=${FFDC_FSP_PATH}:$PATH + + # Verify that we can get to the dump parser script + if [[ ! -e "${FFDC_FSP_PATH}fsp-trace" ]]; then + echo "" + echo " ERROR: Could not find fsp trace ${FFDC_DUMP_PARSER}" + echo "" + return 2; # Return 'No such file or directory' + fi + + echo "PATH=${FFDC_FSP_PATH}:\$PATH" >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + + return 0; # Return success +} + +############################################################################### +# @brief Extract various HB dump info +# +# @param [in] $1 The HB tools directory +# @param [in] $2 Path to the hb-dump-debug tools directory +############################################################################### +function _getInfoFromHBDump_() +{ + echo "" + echo " Extracting the Trace information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Trace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Trace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Printk information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Printk --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Printk --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Errl information (Component/PLID list) from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Errl --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Errl --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Errl information (Detailed listing of all Error Logs) from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Errl --tool-options='display=all' --file=${FFDC_HB_DUMP_FILE} >> ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Errl --tool-options='display=all' --file=${FFDC_HB_DUMP_FILE} >> ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Ps information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the Ps information from HB dump with backtrace ..." + echo " running: $1 --img-path=$2/ --tool=Ps --tool-options="with-backtrace" --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=Ps --tool-options="with-backtrace" --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the MemStats information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=Ps --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=MemStats --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the PageMgr information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=PageMgr --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=PageMgr --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP} + + echo "" + echo " Extracting the BlTrace information from HB dump ..." + echo " running: $1 --img-path=$2/ --tool=BlTrace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP}" | tee -a ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + $1 --img-path=$2/ --tool=BlTrace --file=${FFDC_HB_DUMP_FILE} > ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP} +} + +############################################################################### +# @brief Extract various HB dump info and post to defect, if caller wishes to +############################################################################### +function _getInfoFromHBDumpAndPost_() +{ + _setFSPTracePath_ + FFDC_RETURN_VALUE=$? + # If call to _setFSPTracePath_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + HB_TOOLS_DIR=$FFDC_FSP_DRIVER_DIR/obj/x86.nfp/hbfw/simics + HB_DUMP_DEBUG=$HB_TOOLS_DIR/hb-dump-debug + _getInfoFromHBDump_ $HB_DUMP_DEBUG $HB_TOOLS_DIR + + # If supplied a defect number, then post a comment to the defect and add + # the generated dump files as attachments + if [ -n "${FFDC_DEFECT_NUM}" ]; then + PATH=${FFDC_3RD_PARTY_SCRIPT_DIR}:$PATH + CQFILE=${FFDC_3RD_PARTY_SCRIPT_DIR}updatecq.pl + + echo "" + echo -e "\n Adding attachment TRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}TRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS -s "Hostboot dump files stored at $FFDC_DEST_DIR" + + echo -e "\n Adding attachment PRINTK${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PRINTK${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment ERRL${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}ERRL${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment PS${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PS${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment PS_BACKTRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PS_BACKTRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment MEMSTATS${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}MEMSTATS${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment PAGEMGR${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}PAGEMGR${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + + echo -e "\n Adding attachment BLTRACE${FFDC_TIME_STAMP} to defect ${FFDC_DEFECT_NUM} ..." + perl $CQFILE -id $FFDC_DEFECT_NUM -a ${FFDC_DEST_DIR}BLTRACE${FFDC_TIME_STAMP} -u $FFDC_CQ_USER -p $FFDC_CQ_PASS + fi +} + + +############################################################################### +# @brief The main. The real starting place of this script +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### +function ffdcExpanderMain() +{ + # Get user input options and validate + _getUserInputOptionsAndValidate_ $* + FFDC_RETURN_VALUE=$? + # If call to _getUserInputOptionsAndValidate_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + + # If caller supplied a gzipped file then unzip it + if [ -n "${FFDC_SYSDUMP_FILE_GZ}" ]; then + _unzipSysDumpFile_ + FFDC_RETURN_VALUE=$? + fi + # If call to _unzipSysDumpFile_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + + # If caller supplied a SYSDUMP file then extract HB dump file + if [ -n "${FFDC_SYSDUMP_FILE}" ]; then + _extractHbSysDumpFile_ ${FFDC_SYSDUMP_FILE} + FFDC_RETURN_VALUE=$? + fi + # If call to _extractHbSysDumpFile_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + + # If caller supplied a HB dump file and a FSP build tag, then retrieve HB info + if [ -n "${FFDC_HB_DUMP_FILE}" ] && [ -n "${FFDC_FSP_DRIVER_DIR}" ]; then + # Save the FSP build tag as a file for the caller's benefit + touch ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + # Add some info data to the file + echo ${FFDC_FSP_BUILD_TAG} > ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + echo ${FFDC_FSP_DRIVER} >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + echo ${FFDC_FSP_DRIVER_DIR} >> ${FFDC_DEST_DIR}${FFDC_FSP_BUILD_TAG} + + _getInfoFromHBDumpAndPost_ ${FFDC_HB_DUMP_FILE} ${FFDC_FSP_DRIVER_DIR}; + FFDC_RETURN_VALUE=$? + fi + # If call to _getInfoFromHBDumpAndPost_ not successful, then propagate error back + if [ "$FFDC_RETURN_VALUE" != "0" ]; then + return $FFDC_RETURN_VALUE; + fi + + echo "" + return 0; +} + + +############################################################################### +# @brief Call the main starting function, ffdcExpanderMain, the beginning point +# of this script +# +# @return 0 if successful, not 0 if a failure occurred +############################################################################### + +ffdcExpanderMain $* +exit $?; + diff --git a/src/build/debug/simics-debug-framework.py b/src/build/debug/simics-debug-framework.py index 3176f8cba..fd90806bb 100644 --- a/src/build/debug/simics-debug-framework.py +++ b/src/build/debug/simics-debug-framework.py @@ -516,7 +516,7 @@ def magic_instruction_callback(user_arg, cpu, arg): # Stop the simulation, much like a hard-coded breakpoint SIM_break_simulation( "Simulation stopped. (hap 7007)" ) - if arg == 7008: + if arg == 7008: # MAGIC_RANDOM cpu.r3 = random.randint(1, 0xffffffffffffffffL) if arg == 7009: # MAGIC_MEMORYLEAK_FUNCTION @@ -525,6 +525,10 @@ def magic_instruction_callback(user_arg, cpu, arg): if arg == 7011: #MAGIC_SIMICS_CHECK cpu.r3 = 1 print "TimeManager::cv_isSimicsRunning = true" + # Clear the dump flag in case it was still set from a previous boot + # (this call happens only 1 time and it is very early in the boot) + if( os.environ.has_key('HB_DUMP_COMPLETE') ): + del os.environ['HB_DUMP_COMPLETE'] if arg == 7012: # MAGIC_LOAD_PAYLOAD #For P9 the Payload load is much faster due to PNOR @@ -537,6 +541,17 @@ def magic_instruction_callback(user_arg, cpu, arg): #SIM_run_alone( run_command, cmd ) print "MAGIC_LOAD_PAYLOAD not implemented\n"; + if arg == 7014: # MAGIC_HB_DUMP + # Collect a hostboot dump + # (no args) + + # Make sure we only do 1 dump even though every thread will TI + if( not os.environ.has_key('HB_DUMP_COMPLETE') ): + print "Generating Hostboot Dump for TI" + os.environ['HB_DUMP_COMPLETE']="1" + cmd1 = "hb-Dump quiet" + SIM_run_alone(run_command, cmd1 ) + if arg == 7018: # MAGIC_BREAK_ON_ERROR # Stop the simulation if an env var is set if( os.environ.has_key('HB_BREAK_ON_ERROR') ): @@ -573,6 +588,7 @@ def magic_instruction_callback(user_arg, cpu, arg): percent_s = "%s" dateCommand = "shell \" date +'%s > TRACE REGS: %d %d' \""%(percent_s,first_num,second_num) SIM_run_alone(run_command, dateCommand ) + if arg == 7022: # MAGIC_SET_LOG_LEVEL if( not os.environ.has_key('ENABLE_HB_SIMICS_LOGS') ): #print("Skipping Hostboot Simics Logging because ENABLE_HB_SIMICS_LOGS is not set") @@ -745,7 +761,9 @@ def magic_instruction_callback(user_arg, cpu, arg): #file = open("hb_trace_debug.dat", "a") #file.write("%s\n" % (saveCommand)) #file.close() - + if arg == 7056: # MAGIC_GCOV_DUMP_NOW + print('Gcov dumping chain from 0x%x' % (cpu.r3,)) + SIM_run_alone(run_command, 'hb-GcovModuleUnload "address=%d"' % (cpu.r3,)) # Continuous trace: Clear these files. rc = os.system( "rm -f hbTracMERG" ) @@ -769,4 +787,3 @@ SIM_hap_add_callback_range( "Core_Magic_Instruction", magic_instruction_callback # Run the registration automatically whenever this script is loaded. register_hb_debug_framework_tools() - |