github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/internal/crash/crash.go (about) 1 // Copyright 2017 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Package crash can be used by local tests to interact with on-device crash reports. 6 package crash 7 8 import ( 9 "context" 10 "os" 11 "path/filepath" 12 "strings" 13 14 "go.chromium.org/tast/core/fsutil" 15 "go.chromium.org/tast/core/internal/logging" 16 ) 17 18 const ( 19 // DefaultCrashDir contains the directory where the kernel writes core and minidump files. 20 DefaultCrashDir = "/var/spool/crash" 21 // ChromeCrashDir contains the directory where Chrome writes minidump files. 22 // Tests configure Chrome to write crashes to this location/ by setting the BREAKPAD_DUMP_LOCATION 23 // environment variable. This overrides the default /home/chronos/user/crash location, which is in 24 // the user's cryptohome and hence is only accessible while they are logged in. 25 ChromeCrashDir = "/home/chronos/crash" 26 27 // BIOSExt is the extension for bios crash files. 28 BIOSExt = ".bios_log" 29 // CoreExt is the extension for core files. 30 CoreExt = ".core" 31 // MinidumpExt is the extension for minidump crash files. 32 MinidumpExt = ".dmp" 33 // LogExt is the extension for log files containing additional information that are written by crash_reporter. 34 LogExt = ".log" 35 // InfoExt is the extention for info files. 36 InfoExt = ".info" 37 // ProclogExt is the extention for proclog files. 38 ProclogExt = ".proclog" 39 // KCrashExt is the extension for log files created by kernel warnings and crashes. 40 KCrashExt = ".kcrash" 41 // GPUStateExt is the extension for GPU state files written by crash_reporter. 42 GPUStateExt = ".i915_error_state.log.xz" 43 // MetadataExt is the extension for metadata files written by crash collectors and read by crash_sender. 44 MetadataExt = ".meta" 45 // CompressedTxtExt is an extension on the compressed log files written by crash_reporter. 46 CompressedTxtExt = ".txt.gz" 47 // CompressedLogExt is an extension on the compressed log files written by crash_reporter. 48 CompressedLogExt = ".log.gz" 49 50 lsbReleasePath = "/etc/lsb-release" 51 ) 52 53 // DefaultDirs returns all standard directories to which crashes are written. 54 func DefaultDirs() []string { 55 return []string{DefaultCrashDir, ChromeCrashDir} 56 } 57 58 // isCrashFile returns true if filename could be the name of a file generated by 59 // crashes or crash_reporter. 60 func isCrashFile(filename string) bool { 61 knownExts := []string{ 62 BIOSExt, 63 CoreExt, 64 MinidumpExt, 65 LogExt, 66 ProclogExt, 67 InfoExt, 68 KCrashExt, 69 GPUStateExt, 70 MetadataExt, 71 CompressedTxtExt, 72 CompressedLogExt, 73 } 74 for _, ext := range knownExts { 75 if strings.HasSuffix(filename, ext) { 76 return true 77 } 78 } 79 return false 80 } 81 82 // GetCrashes returns the paths of all files in dirs generated in response to crashes. 83 // Nonexistent directories are skipped. 84 func GetCrashes(dirs ...string) ([]string, error) { 85 var crashFiles []string 86 for _, dir := range dirs { 87 df, err := os.Open(dir) 88 if os.IsNotExist(err) { 89 continue 90 } else if err != nil { 91 return nil, err 92 } 93 files, err := df.Readdirnames(-1) 94 df.Close() 95 if err != nil { 96 return nil, err 97 } 98 99 for _, fn := range files { 100 if isCrashFile(fn) { 101 crashFiles = append(crashFiles, filepath.Join(dir, fn)) 102 } 103 } 104 } 105 return crashFiles, nil 106 } 107 108 // CopyNewFiles copies paths that are present in newPaths but not in oldPaths into dstDir. 109 // If maxPerExec is positive, it limits the maximum number of files that will be copied 110 // for each base executable. The returned warnings map contains non-fatal errors keyed by 111 // crash file paths. 112 func CopyNewFiles(ctx context.Context, dstDir string, newPaths, oldPaths []string) error { 113 oldMap := make(map[string]struct{}, len(oldPaths)) 114 for _, p := range oldPaths { 115 oldMap[p] = struct{}{} 116 } 117 118 for _, sp := range newPaths { 119 if _, ok := oldMap[sp]; ok { 120 continue 121 } 122 // Core dumps (.core) are often too large, do not copy them. 123 // Minidumps (.dmp) are usually sufficient. 124 if strings.HasSuffix(sp, ".core") { 125 continue 126 } 127 128 if err := fsutil.CopyFile(sp, filepath.Join(dstDir, filepath.Base(sp))); err != nil { 129 logging.Infof(ctx, "%s: %v", sp, err) 130 } 131 } 132 return nil 133 } 134 135 // CopySystemInfo copies system information relevant to crash dumps (e.g. lsb-release) into dstDir. 136 func CopySystemInfo(dstDir string) error { 137 return fsutil.CopyFile(lsbReleasePath, filepath.Join(dstDir, filepath.Base(lsbReleasePath))) 138 }