Pārlūkot izejas kodu

Support Intel syntax in the assembly reports (#520)

Add support for output assembly in Intel Syntax.
Garrett Wang 5 gadus atpakaļ
vecāks
revīzija
b1a96885c1
No account linked to committer's email address

+ 3
- 3
driver/driver.go Parādīt failu

142
 
142
 
143
 	// Disasm disassembles the named object file, starting at
143
 	// Disasm disassembles the named object file, starting at
144
 	// the start address and stopping at (before) the end address.
144
 	// the start address and stopping at (before) the end address.
145
-	Disasm(file string, start, end uint64) ([]Inst, error)
145
+	Disasm(file string, start, end uint64, intelSyntax bool) ([]Inst, error)
146
 }
146
 }
147
 
147
 
148
 // An Inst is a single instruction in an assembly listing.
148
 // An Inst is a single instruction in an assembly listing.
269
 	return pluginSyms, nil
269
 	return pluginSyms, nil
270
 }
270
 }
271
 
271
 
272
-func (o *internalObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
273
-	insts, err := o.ObjTool.Disasm(file, start, end)
272
+func (o *internalObjTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) {
273
+	insts, err := o.ObjTool.Disasm(file, start, end, intelSyntax)
274
 	if err != nil {
274
 	if err != nil {
275
 		return nil, err
275
 		return nil, err
276
 	}
276
 	}

+ 14
- 4
internal/binutils/binutils.go Parādīt failu

157
 
157
 
158
 // Disasm returns the assembly instructions for the specified address range
158
 // Disasm returns the assembly instructions for the specified address range
159
 // of a binary.
159
 // of a binary.
160
-func (bu *Binutils) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
160
+func (bu *Binutils) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) {
161
 	b := bu.get()
161
 	b := bu.get()
162
-	cmd := exec.Command(b.objdump, "-d", "-C", "--no-show-raw-insn", "-l",
162
+	args := []string{"-d", "-C", "--no-show-raw-insn", "-l",
163
 		fmt.Sprintf("--start-address=%#x", start),
163
 		fmt.Sprintf("--start-address=%#x", start),
164
-		fmt.Sprintf("--stop-address=%#x", end),
165
-		file)
164
+		fmt.Sprintf("--stop-address=%#x", end)}
165
+
166
+	if intelSyntax {
167
+		if runtime.GOOS == "darwin" {
168
+			args = append(args, "-x86-asm-syntax=intel")
169
+		} else {
170
+			args = append(args, "-M", "intel")
171
+		}
172
+	}
173
+
174
+	args = append(args, file)
175
+	cmd := exec.Command(b.objdump, args...)
166
 	out, err := cmd.Output()
176
 	out, err := cmd.Output()
167
 	if err != nil {
177
 	if err != nil {
168
 		return nil, fmt.Errorf("%v: %v", cmd.Args, err)
178
 		return nil, fmt.Errorf("%v: %v", cmd.Args, err)

+ 8
- 3
internal/binutils/binutils_test.go Parādīt failu

188
 	}
188
 	}
189
 }
189
 }
190
 
190
 
191
-func TestDisasm(t *testing.T) {
192
-	skipUnlessLinuxAmd64(t)
191
+func testDisasm(t *testing.T, intelSyntax bool) {
193
 	bu := &Binutils{}
192
 	bu := &Binutils{}
194
-	insts, err := bu.Disasm(filepath.Join("testdata", "exe_linux_64"), 0, math.MaxUint64)
193
+	insts, err := bu.Disasm(filepath.Join("testdata", "exe_linux_64"), 0, math.MaxUint64, intelSyntax)
195
 	if err != nil {
194
 	if err != nil {
196
 		t.Fatalf("Disasm: unexpected error %v", err)
195
 		t.Fatalf("Disasm: unexpected error %v", err)
197
 	}
196
 	}
206
 	}
205
 	}
207
 }
206
 }
208
 
207
 
208
+func TestDisasm(t *testing.T) {
209
+	skipUnlessLinuxAmd64(t)
210
+	testDisasm(t, true)
211
+	testDisasm(t, false)
212
+}
213
+
209
 func findSymbol(syms []*plugin.Sym, name string) *plugin.Sym {
214
 func findSymbol(syms []*plugin.Sym, name string) *plugin.Sym {
210
 	for _, s := range syms {
215
 	for _, s := range syms {
211
 		for _, n := range s.Name {
216
 		for _, n := range s.Name {

+ 3
- 0
internal/driver/commands.go Parādīt failu

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
 	"source_path":    &variable{stringKind, "", "", "Search path for source files"},
156
 	"trim_path":      &variable{stringKind, "", "", "Path to trim from source paths before search"},
156
 	"trim_path":      &variable{stringKind, "", "", "Path to trim from source paths before search"},
157
+	"intel_syntax": &variable{boolKind, "f", "", helpText(
158
+		"Show assembly in Intel syntax",
159
+		"Only applicable to commands `disasm` and `weblist`")},
157
 
160
 
158
 	// Filtering options
161
 	// Filtering options
159
 	"nodecount": &variable{intKind, "-1", "", helpText(
162
 	"nodecount": &variable{intKind, "-1", "", helpText(

+ 2
- 0
internal/driver/driver.go Parādīt failu

281
 
281
 
282
 		SourcePath: vars["source_path"].stringValue(),
282
 		SourcePath: vars["source_path"].stringValue(),
283
 		TrimPath:   vars["trim_path"].stringValue(),
283
 		TrimPath:   vars["trim_path"].stringValue(),
284
+
285
+		IntelSyntax: vars["intel_syntax"].boolValue(),
284
 	}
286
 	}
285
 
287
 
286
 	if len(p.Mapping) > 0 && p.Mapping[0].File != "" {
288
 	if len(p.Mapping) > 0 && p.Mapping[0].File != "" {

+ 1
- 1
internal/driver/driver_test.go Parādīt failu

1562
 	return &mockFile{file, "abcdef", 0}, nil
1562
 	return &mockFile{file, "abcdef", 0}, nil
1563
 }
1563
 }
1564
 
1564
 
1565
-func (m *mockObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
1565
+func (m *mockObjTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) {
1566
 	switch start {
1566
 	switch start {
1567
 	case 0x1000:
1567
 	case 0x1000:
1568
 		return []plugin.Inst{
1568
 		return []plugin.Inst{

+ 3
- 1
internal/driver/fetch_test.go Parādīt failu

161
 func (testObj) Demangler(_ string) func(names []string) (map[string]string, error) {
161
 func (testObj) Demangler(_ string) func(names []string) (map[string]string, error) {
162
 	return func(names []string) (map[string]string, error) { return nil, nil }
162
 	return func(names []string) (map[string]string, error) { return nil, nil }
163
 }
163
 }
164
-func (testObj) Disasm(file string, start, end uint64) ([]plugin.Inst, error) { return nil, nil }
164
+func (testObj) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) {
165
+	return nil, nil
166
+}
165
 
167
 
166
 type testFile struct{ name, buildID string }
168
 type testFile struct{ name, buildID string }
167
 
169
 

+ 1
- 1
internal/driver/webui_test.go Parādīt failu

172
 	return fakeObj{}, nil
172
 	return fakeObj{}, nil
173
 }
173
 }
174
 
174
 
175
-func (obj fakeObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
175
+func (obj fakeObjTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) {
176
 	return []plugin.Inst{
176
 	return []plugin.Inst{
177
 		{Addr: addrBase + 0, Text: "f1:asm", Function: "F1"},
177
 		{Addr: addrBase + 0, Text: "f1:asm", Function: "F1"},
178
 		{Addr: addrBase + 10, Text: "f2:asm", Function: "F2"},
178
 		{Addr: addrBase + 10, Text: "f2:asm", Function: "F2"},

+ 1
- 1
internal/plugin/plugin.go Parādīt failu

114
 
114
 
115
 	// Disasm disassembles the named object file, starting at
115
 	// Disasm disassembles the named object file, starting at
116
 	// the start address and stopping at (before) the end address.
116
 	// the start address and stopping at (before) the end address.
117
-	Disasm(file string, start, end uint64) ([]Inst, error)
117
+	Disasm(file string, start, end uint64, intelSyntax bool) ([]Inst, error)
118
 }
118
 }
119
 
119
 
120
 // An Inst is a single instruction in an assembly listing.
120
 // An Inst is a single instruction in an assembly listing.

+ 3
- 1
internal/report/report.go Parādīt failu

79
 	Symbol     *regexp.Regexp // Symbols to include on disassembly report.
79
 	Symbol     *regexp.Regexp // Symbols to include on disassembly report.
80
 	SourcePath string         // Search path for source files.
80
 	SourcePath string         // Search path for source files.
81
 	TrimPath   string         // Paths to trim from source file paths.
81
 	TrimPath   string         // Paths to trim from source file paths.
82
+
83
+	IntelSyntax bool // Whether or not to print assembly in Intel syntax.
82
 }
84
 }
83
 
85
 
84
 // Generate generates a report as directed by the Report.
86
 // Generate generates a report as directed by the Report.
438
 		flatSum, cumSum := sns.Sum()
440
 		flatSum, cumSum := sns.Sum()
439
 
441
 
440
 		// Get the function assembly.
442
 		// Get the function assembly.
441
-		insts, err := obj.Disasm(s.sym.File, s.sym.Start, s.sym.End)
443
+		insts, err := obj.Disasm(s.sym.File, s.sym.Start, s.sym.End, o.IntelSyntax)
442
 		if err != nil {
444
 		if err != nil {
443
 			return err
445
 			return err
444
 		}
446
 		}

+ 3
- 3
internal/report/source.go Parādīt failu

205
 		ff := fileFunction{n.Info.File, n.Info.Name}
205
 		ff := fileFunction{n.Info.File, n.Info.Name}
206
 		fns := fileNodes[ff]
206
 		fns := fileNodes[ff]
207
 
207
 
208
-		asm := assemblyPerSourceLine(symbols, fns, ff.fileName, obj)
208
+		asm := assemblyPerSourceLine(symbols, fns, ff.fileName, obj, o.IntelSyntax)
209
 		start, end := sourceCoordinates(asm)
209
 		start, end := sourceCoordinates(asm)
210
 
210
 
211
 		fnodes, path, err := getSourceFromFile(ff.fileName, reader, fns, start, end)
211
 		fnodes, path, err := getSourceFromFile(ff.fileName, reader, fns, start, end)
239
 // assemblyPerSourceLine disassembles the binary containing a symbol
239
 // assemblyPerSourceLine disassembles the binary containing a symbol
240
 // and classifies the assembly instructions according to its
240
 // and classifies the assembly instructions according to its
241
 // corresponding source line, annotating them with a set of samples.
241
 // corresponding source line, annotating them with a set of samples.
242
-func assemblyPerSourceLine(objSyms []*objSymbol, rs graph.Nodes, src string, obj plugin.ObjTool) map[int][]assemblyInstruction {
242
+func assemblyPerSourceLine(objSyms []*objSymbol, rs graph.Nodes, src string, obj plugin.ObjTool, intelSyntax bool) map[int][]assemblyInstruction {
243
 	assembly := make(map[int][]assemblyInstruction)
243
 	assembly := make(map[int][]assemblyInstruction)
244
 	// Identify symbol to use for this collection of samples.
244
 	// Identify symbol to use for this collection of samples.
245
 	o := findMatchingSymbol(objSyms, rs)
245
 	o := findMatchingSymbol(objSyms, rs)
248
 	}
248
 	}
249
 
249
 
250
 	// Extract assembly for matched symbol
250
 	// Extract assembly for matched symbol
251
-	insts, err := obj.Disasm(o.sym.File, o.sym.Start, o.sym.End)
251
+	insts, err := obj.Disasm(o.sym.File, o.sym.Start, o.sym.End, intelSyntax)
252
 	if err != nil {
252
 	if err != nil {
253
 		return assembly
253
 		return assembly
254
 	}
254
 	}

+ 1
- 1
internal/symbolizer/symbolizer_test.go Parādīt failu

267
 	return mockObjFile{frames: mockAddresses}, nil
267
 	return mockObjFile{frames: mockAddresses}, nil
268
 }
268
 }
269
 
269
 
270
-func (mockObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
270
+func (mockObjTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) {
271
 	return nil, fmt.Errorf("disassembly not supported")
271
 	return nil, fmt.Errorf("disassembly not supported")
272
 }
272
 }
273
 
273