Browse Source

Merge pull request #17 from rauls5382/master

Add source_path option to point pprof to source files
Josef Jelinek 9 years ago
parent
commit
9e62056af5

+ 1
- 0
internal/driver/commands.go View File

152
 		" For memory profiles, use megabytes, kilobytes, bytes, etc.",
152
 		" For memory profiles, use megabytes, kilobytes, bytes, etc.",
153
 		" auto will scale each value independently to the most natural unit.")},
153
 		" auto will scale each value independently to the most natural unit.")},
154
 	"compact_labels": &variable{boolKind, "f", "", "Show minimal headers"},
154
 	"compact_labels": &variable{boolKind, "f", "", "Show minimal headers"},
155
+	"source_path":    &variable{stringKind, "", "", "Search path for source files"},
155
 
156
 
156
 	// Filtering options
157
 	// Filtering options
157
 	"nodecount": &variable{intKind, "-1", "", helpText(
158
 	"nodecount": &variable{intKind, "-1", "", helpText(

+ 2
- 0
internal/driver/driver.go View File

235
 		SampleUnit:  sample.Unit,
235
 		SampleUnit:  sample.Unit,
236
 
236
 
237
 		OutputUnit: vars["unit"].value,
237
 		OutputUnit: vars["unit"].value,
238
+
239
+		SourcePath: vars["source_path"].stringValue(),
238
 	}
240
 	}
239
 
241
 
240
 	if len(p.Mapping) > 0 && p.Mapping[0].File != "" {
242
 	if len(p.Mapping) > 0 && p.Mapping[0].File != "" {

+ 2
- 0
internal/driver/interactive.go View File

167
 			if o.boolValue() == false {
167
 			if o.boolValue() == false {
168
 				continue
168
 				continue
169
 			}
169
 			}
170
+		case n == "source_path":
171
+			continue
170
 		}
172
 		}
171
 		args = append(args, fmt.Sprintf("  %-25s : %s", n, v))
173
 		args = append(args, fmt.Sprintf("  %-25s : %s", n, v))
172
 	}
174
 	}

+ 2
- 1
internal/report/report.go View File

881
 
881
 
882
 	OutputUnit string // Units for data formatting in report.
882
 	OutputUnit string // Units for data formatting in report.
883
 
883
 
884
-	Symbol *regexp.Regexp // Symbols to include on disassembly report.
884
+	Symbol     *regexp.Regexp // Symbols to include on disassembly report.
885
+	SourcePath string         // Search path for source files.
885
 }
886
 }
886
 
887
 
887
 // New builds a new report indexing the sample values interpreting the
888
 // New builds a new report indexing the sample values interpreting the

+ 39
- 17
internal/report/source.go View File

55
 	}
55
 	}
56
 	functions.Sort(graph.NameOrder)
56
 	functions.Sort(graph.NameOrder)
57
 
57
 
58
+	sourcePath := o.SourcePath
59
+	if sourcePath == "" {
60
+		wd, err := os.Getwd()
61
+		if err != nil {
62
+			return fmt.Errorf("Could not stat current dir: %v", err)
63
+		}
64
+		sourcePath = wd
65
+	}
66
+
58
 	fmt.Fprintf(w, "Total: %s\n", rpt.formatValue(rpt.total))
67
 	fmt.Fprintf(w, "Total: %s\n", rpt.formatValue(rpt.total))
59
 	for _, fn := range functions {
68
 	for _, fn := range functions {
60
 		name := fn.Info.Name
69
 		name := fn.Info.Name
86
 			fns := fileNodes[filename]
95
 			fns := fileNodes[filename]
87
 			flatSum, cumSum := fns.Sum()
96
 			flatSum, cumSum := fns.Sum()
88
 
97
 
89
-			fnodes, path, err := getFunctionSource(name, filename, fns, 0, 0)
98
+			fnodes, path, err := getFunctionSource(name, filename, sourcePath, fns, 0, 0)
90
 			fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, path)
99
 			fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, path)
91
 			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
100
 			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
92
 				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
101
 				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
118
 		address = &hex
127
 		address = &hex
119
 	}
128
 	}
120
 
129
 
130
+	sourcePath := o.SourcePath
131
+	if sourcePath == "" {
132
+		wd, err := os.Getwd()
133
+		if err != nil {
134
+			return fmt.Errorf("Could not stat current dir: %v", err)
135
+		}
136
+		sourcePath = wd
137
+	}
138
+
121
 	// Extract interesting symbols from binary files in the profile and
139
 	// Extract interesting symbols from binary files in the profile and
122
 	// classify samples per symbol.
140
 	// classify samples per symbol.
123
 	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
141
 	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
166
 			asm := assemblyPerSourceLine(symbols, fns, filename, obj)
184
 			asm := assemblyPerSourceLine(symbols, fns, filename, obj)
167
 			start, end := sourceCoordinates(asm)
185
 			start, end := sourceCoordinates(asm)
168
 
186
 
169
-			fnodes, path, err := getFunctionSource(name, filename, fns, start, end)
187
+			fnodes, path, err := getFunctionSource(name, filename, sourcePath, fns, start, end)
170
 			if err != nil {
188
 			if err != nil {
171
 				fnodes, path = getMissingFunctionSource(filename, asm, start, end)
189
 				fnodes, path = getMissingFunctionSource(filename, asm, start, end)
172
 			}
190
 			}
319
 // getFunctionSource collects the sources of a function from a source
337
 // getFunctionSource collects the sources of a function from a source
320
 // file and annotates it with the samples in fns. Returns the sources
338
 // file and annotates it with the samples in fns. Returns the sources
321
 // as nodes, using the info.name field to hold the source code.
339
 // as nodes, using the info.name field to hold the source code.
322
-func getFunctionSource(fun, file string, fns graph.Nodes, start, end int) (graph.Nodes, string, error) {
323
-	f, file, err := adjustSourcePath(file)
340
+func getFunctionSource(fun, file, sourcePath string, fns graph.Nodes, start, end int) (graph.Nodes, string, error) {
341
+	f, file, err := openSourceFile(file, sourcePath)
324
 	if err != nil {
342
 	if err != nil {
325
 		return nil, file, err
343
 		return nil, file, err
326
 	}
344
 	}
411
 	return fnodes, filename
429
 	return fnodes, filename
412
 }
430
 }
413
 
431
 
414
-// adjustSourcePath adjusts the path for a source file by trimmming
415
-// known prefixes and searching for the file on all parents of the
416
-// current working dir.
417
-func adjustSourcePath(path string) (*os.File, string, error) {
432
+// openSourceFile opens a source file from a name encoded in a
433
+// profile. File names in a profile after often relative paths, so
434
+// search them in each of the paths in searchPath (or CWD by default),
435
+// and their parents.
436
+func openSourceFile(path, searchPath string) (*os.File, string, error) {
418
 	path = trimPath(path)
437
 	path = trimPath(path)
419
-	f, err := os.Open(path)
420
-	if err == nil {
421
-		return f, path, nil
438
+
439
+	if filepath.IsAbs(path) {
440
+		f, err := os.Open(path)
441
+		return f, path, err
422
 	}
442
 	}
423
 
443
 
424
-	if dir, wderr := os.Getwd(); wderr == nil {
444
+	// Scan each component of the path
445
+	for _, dir := range strings.Split(searchPath, ":") {
446
+		// Search up for every parent of each possible path.
425
 		for {
447
 		for {
448
+			filename := filepath.Join(dir, path)
449
+			if f, err := os.Open(filename); err == nil {
450
+				return f, filename, nil
451
+			}
426
 			parent := filepath.Dir(dir)
452
 			parent := filepath.Dir(dir)
427
 			if parent == dir {
453
 			if parent == dir {
428
 				break
454
 				break
429
 			}
455
 			}
430
-			if f, err := os.Open(filepath.Join(parent, path)); err == nil {
431
-				return f, filepath.Join(parent, path), nil
432
-			}
433
-
434
 			dir = parent
456
 			dir = parent
435
 		}
457
 		}
436
 	}
458
 	}
437
 
459
 
438
-	return nil, path, err
460
+	return nil, "", fmt.Errorf("Could not find file %s on path %s", path, searchPath)
439
 }
461
 }
440
 
462
 
441
 // trimPath cleans up a path by removing prefixes that are commonly
463
 // trimPath cleans up a path by removing prefixes that are commonly