ctxt := obj.Linknew(architecture.LinkArch)
if *flags.PrintOut {
- ctxt.Debugasm = true
+ ctxt.Debugasm = 1
}
ctxt.Flag_dynlink = *flags.Dynlink
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
"bytes"
"internal/testenv"
"io/ioutil"
- "log"
"os"
"os/exec"
"path/filepath"
// Make a directory to work in.
dir, err := ioutil.TempDir("", "issue6853a-")
if err != nil {
- log.Fatalf("could not create directory: %v", err)
+ t.Fatalf("could not create directory: %v", err)
}
defer os.RemoveAll(dir)
src := filepath.Join(dir, "test.go")
f, err := os.Create(src)
if err != nil {
- log.Fatalf("could not create source file: %v", err)
+ t.Fatalf("could not create source file: %v", err)
}
f.Write([]byte(`
package main
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dst, src)
out, err := cmd.CombinedOutput()
if err != nil {
- log.Fatalf("could not build target: %v", err)
+ t.Fatalf("could not build target: %v", err)
}
// Check destination to see if scanf code was included.
cmd = exec.Command(testenv.GoToolPath(t), "tool", "nm", dst)
out, err = cmd.CombinedOutput()
if err != nil {
- log.Fatalf("could not read target: %v", err)
+ t.Fatalf("could not read target: %v", err)
}
if bytes.Contains(out, []byte("scanInt")) {
- log.Fatalf("scanf code not removed from helloworld")
+ t.Fatalf("scanf code not removed from helloworld")
}
}
// Make a directory to work in.
dir, err := ioutil.TempDir("", "issue14515-")
if err != nil {
- log.Fatalf("could not create directory: %v", err)
+ t.Fatalf("could not create directory: %v", err)
}
defer os.RemoveAll(dir)
src := filepath.Join(dir, "test.go")
f, err := os.Create(src)
if err != nil {
- log.Fatalf("could not create source file: %v", err)
+ t.Fatalf("could not create source file: %v", err)
}
f.Write([]byte(`
package main
cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-S", "-o", filepath.Join(dir, "test"), src)
out, err := cmd.CombinedOutput()
if err != nil {
- log.Fatalf("could not build target: %v", err)
+ t.Fatalf("could not build target: %v", err)
}
patterns := []string{
var (
Debug_append int
- Debug_asm bool
Debug_closure int
Debug_compilelater int
debug_dclstack int
objabi.Flagcount("K", "debug missing line numbers", &Debug['K'])
objabi.Flagcount("L", "show full file names in error messages", &Debug['L'])
objabi.Flagcount("N", "disable optimizations", &Debug['N'])
- flag.BoolVar(&Debug_asm, "S", false, "print assembly listing")
+ objabi.Flagcount("S", "print assembly listing", &Debug['S'])
objabi.AddVersionFlag() // -V
objabi.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
Ctxt.Flag_dynlink = flag_dynlink
Ctxt.Flag_optimize = Debug['N'] == 0
- Ctxt.Debugasm = Debug_asm
+ Ctxt.Debugasm = Debug['S']
Ctxt.Debugvlog = Debug_vlog
if flagDWARF {
Ctxt.DebugInfo = debuginfo
'l': true, // disable inlining
'w': true, // all printing happens before compilation
'W': true, // all printing happens before compilation
+ 'S': true, // printing disassembly happens at the end (but see concurrentBackendAllowed below)
}
func concurrentBackendAllowed() bool {
return false
}
}
- // Debug_asm by itself is ok, because all printing occurs
+ // Debug['S'] by itself is ok, because all printing occurs
// while writing the object file, and that is non-concurrent.
- // Adding Debug_vlog, however, causes Debug_asm to also print
+ // Adding Debug_vlog, however, causes Debug['S'] to also print
// while flushing the plist, which happens concurrently.
if Debug_vlog || debugstr != "" || debuglive > 0 {
return false
type Link struct {
Headtype objabi.HeadType
Arch *LinkArch
- Debugasm bool
+ Debugasm int
Debugvlog bool
Debugpcln string
Flag_shared bool
fmt.Fprintf(ctxt.Bso, "\n")
if s.Type == objabi.STEXT {
for p := s.Func.Text; p != nil; p = p.Link {
- fmt.Fprintf(ctxt.Bso, "\t%#04x %v\n", uint(int(p.Pc)), p)
+ var s string
+ if ctxt.Debugasm > 1 {
+ s = p.String()
+ } else {
+ s = p.InnermostString()
+ }
+ fmt.Fprintf(ctxt.Bso, "\t%#04x %s\n", uint(int(p.Pc)), s)
}
}
for i := 0; i < len(s.P); i += 16 {
func (w *objWriter) writeSym(s *LSym) {
ctxt := w.ctxt
- if ctxt.Debugasm {
+ if ctxt.Debugasm > 0 {
w.writeSymDebug(s)
}
var plink *Prog
for p := plist.Firstpc; p != nil; p = plink {
- if ctxt.Debugasm && ctxt.Debugvlog {
+ if ctxt.Debugasm > 0 && ctxt.Debugvlog {
fmt.Printf("obj: %v\n", p)
}
plink = p.Link
func (p *Prog) Line() string {
return p.Ctxt.OutermostPos(p.Pos).Format(false, true)
}
+func (p *Prog) InnermostLine() string {
+ return p.Ctxt.InnermostPos(p.Pos).Format(false, true)
+}
// InnermostLineNumber returns a string containing the line number for the
// innermost inlined function (if any inlining) at p's position
return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.Line(), p.InstructionString())
}
+func (p *Prog) InnermostString() string {
+ if p == nil {
+ return "<nil Prog>"
+ }
+ if p.Ctxt == nil {
+ return "<Prog without ctxt>"
+ }
+ return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.InnermostLine(), p.InstructionString())
+}
+
// InstructionString returns a string representation of the instruction without preceding
// program counter or file and line number.
func (p *Prog) InstructionString() string {
}
func (ctxt *Link) CanReuseProgs() bool {
- return !ctxt.Debugasm
+ return ctxt.Debugasm == 0
}
func Dconv(p *Prog, a *Addr) string {
// against a set of regexps in comments.
ops := t.wantedAsmOpcodes(long)
for _, env := range ops.Envs() {
- cmdline := []string{"build", "-gcflags", "-S"}
+ // -S=2 forces outermost line numbers when disassembling inlined code.
+ cmdline := []string{"build", "-gcflags", "-S=2"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, long)
cmd := exec.Command(goTool(), cmdline...)