ソースを参照

Support Intel syntax in the assembly reports (#520)

Add support for output assembly in Intel Syntax.
Garrett Wang 5 年 前
コミット
b1a96885c1
No account linked to committer's email address

+ 3
- 3
driver/driver.go ファイルの表示

@@ -142,7 +142,7 @@ type ObjTool interface {
142 142
 
143 143
 	// Disasm disassembles the named object file, starting at
144 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 148
 // An Inst is a single instruction in an assembly listing.
@@ -269,8 +269,8 @@ func (f *internalObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym,
269 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 274
 	if err != nil {
275 275
 		return nil, err
276 276
 	}

+ 14
- 4
internal/binutils/binutils.go ファイルの表示

@@ -157,12 +157,22 @@ func findExe(cmd string, paths []string) (string, bool) {
157 157
 
158 158
 // Disasm returns the assembly instructions for the specified address range
159 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 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 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 176
 	out, err := cmd.Output()
167 177
 	if err != nil {
168 178
 		return nil, fmt.Errorf("%v: %v", cmd.Args, err)

+ 8
- 3
internal/binutils/binutils_test.go ファイルの表示

@@ -188,10 +188,9 @@ func skipUnlessDarwinAmd64(t *testing.T) {
188 188
 	}
189 189
 }
190 190
 
191
-func TestDisasm(t *testing.T) {
192
-	skipUnlessLinuxAmd64(t)
191
+func testDisasm(t *testing.T, intelSyntax bool) {
193 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 194
 	if err != nil {
196 195
 		t.Fatalf("Disasm: unexpected error %v", err)
197 196
 	}
@@ -206,6 +205,12 @@ func TestDisasm(t *testing.T) {
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 214
 func findSymbol(syms []*plugin.Sym, name string) *plugin.Sym {
210 215
 	for _, s := range syms {
211 216
 		for _, n := range s.Name {

+ 3
- 0
internal/driver/commands.go ファイルの表示

@@ -154,6 +154,9 @@ var pprofVariables = variables{
154 154
 	"compact_labels": &variable{boolKind, "f", "", "Show minimal headers"},
155 155
 	"source_path":    &variable{stringKind, "", "", "Search path for source files"},
156 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 161
 	// Filtering options
159 162
 	"nodecount": &variable{intKind, "-1", "", helpText(

+ 2
- 0
internal/driver/driver.go ファイルの表示

@@ -281,6 +281,8 @@ func reportOptions(p *profile.Profile, numLabelUnits map[string]string, vars var
281 281
 
282 282
 		SourcePath: vars["source_path"].stringValue(),
283 283
 		TrimPath:   vars["trim_path"].stringValue(),
284
+
285
+		IntelSyntax: vars["intel_syntax"].boolValue(),
284 286
 	}
285 287
 
286 288
 	if len(p.Mapping) > 0 && p.Mapping[0].File != "" {

+ 1
- 1
internal/driver/driver_test.go ファイルの表示

@@ -1562,7 +1562,7 @@ func (*mockObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFi
1562 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 1566
 	switch start {
1567 1567
 	case 0x1000:
1568 1568
 		return []plugin.Inst{

+ 3
- 1
internal/driver/fetch_test.go ファイルの表示

@@ -161,7 +161,9 @@ func (o testObj) Open(file string, start, limit, offset uint64) (plugin.ObjFile,
161 161
 func (testObj) Demangler(_ string) func(names []string) (map[string]string, error) {
162 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 168
 type testFile struct{ name, buildID string }
167 169
 

+ 1
- 1
internal/driver/webui_test.go ファイルの表示

@@ -172,7 +172,7 @@ func (obj fakeObjTool) Open(file string, start, limit, offset uint64) (plugin.Ob
172 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 176
 	return []plugin.Inst{
177 177
 		{Addr: addrBase + 0, Text: "f1:asm", Function: "F1"},
178 178
 		{Addr: addrBase + 10, Text: "f2:asm", Function: "F2"},

+ 1
- 1
internal/plugin/plugin.go ファイルの表示

@@ -114,7 +114,7 @@ type ObjTool interface {
114 114
 
115 115
 	// Disasm disassembles the named object file, starting at
116 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 120
 // An Inst is a single instruction in an assembly listing.

+ 3
- 1
internal/report/report.go ファイルの表示

@@ -79,6 +79,8 @@ type Options struct {
79 79
 	Symbol     *regexp.Regexp // Symbols to include on disassembly report.
80 80
 	SourcePath string         // Search path for source files.
81 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 86
 // Generate generates a report as directed by the Report.
@@ -438,7 +440,7 @@ func PrintAssembly(w io.Writer, rpt *Report, obj plugin.ObjTool, maxFuncs int) e
438 440
 		flatSum, cumSum := sns.Sum()
439 441
 
440 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 444
 		if err != nil {
443 445
 			return err
444 446
 		}

+ 3
- 3
internal/report/source.go ファイルの表示

@@ -205,7 +205,7 @@ func PrintWebList(w io.Writer, rpt *Report, obj plugin.ObjTool, maxFiles int) er
205 205
 		ff := fileFunction{n.Info.File, n.Info.Name}
206 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 209
 		start, end := sourceCoordinates(asm)
210 210
 
211 211
 		fnodes, path, err := getSourceFromFile(ff.fileName, reader, fns, start, end)
@@ -239,7 +239,7 @@ func sourceCoordinates(asm map[int][]assemblyInstruction) (start, end int) {
239 239
 // assemblyPerSourceLine disassembles the binary containing a symbol
240 240
 // and classifies the assembly instructions according to its
241 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 243
 	assembly := make(map[int][]assemblyInstruction)
244 244
 	// Identify symbol to use for this collection of samples.
245 245
 	o := findMatchingSymbol(objSyms, rs)
@@ -248,7 +248,7 @@ func assemblyPerSourceLine(objSyms []*objSymbol, rs graph.Nodes, src string, obj
248 248
 	}
249 249
 
250 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 252
 	if err != nil {
253 253
 		return assembly
254 254
 	}

+ 1
- 1
internal/symbolizer/symbolizer_test.go ファイルの表示

@@ -267,7 +267,7 @@ func (mockObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFil
267 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 271
 	return nil, fmt.Errorf("disassembly not supported")
272 272
 }
273 273