1// Copyright 2014 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package main 6 7import ( 8 "bufio" 9 "flag" 10 "fmt" 11 "internal/buildcfg" 12 "log" 13 "os" 14 15 "cmd/asm/internal/arch" 16 "cmd/asm/internal/asm" 17 "cmd/asm/internal/flags" 18 "cmd/asm/internal/lex" 19 20 "cmd/internal/bio" 21 "cmd/internal/obj" 22 "cmd/internal/objabi" 23) 24 25func main() { 26 log.SetFlags(0) 27 log.SetPrefix("asm: ") 28 29 buildcfg.Check() 30 GOARCH := buildcfg.GOARCH 31 32 flags.Parse() 33 34 architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink) 35 if architecture == nil { 36 log.Fatalf("unrecognized architecture %s", GOARCH) 37 } 38 39 ctxt := obj.Linknew(architecture.LinkArch) 40 ctxt.Debugasm = flags.PrintOut 41 ctxt.Debugvlog = flags.DebugV 42 ctxt.Flag_dynlink = *flags.Dynlink 43 ctxt.Flag_linkshared = *flags.Linkshared 44 ctxt.Flag_shared = *flags.Shared || *flags.Dynlink 45 ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack 46 ctxt.IsAsm = true 47 ctxt.Pkgpath = *flags.Importpath 48 switch *flags.Spectre { 49 default: 50 log.Printf("unknown setting -spectre=%s", *flags.Spectre) 51 os.Exit(2) 52 case "": 53 // nothing 54 case "index": 55 // known to compiler; ignore here so people can use 56 // the same list with -gcflags=-spectre=LIST and -asmflags=-spectrre=LIST 57 case "all", "ret": 58 ctxt.Retpoline = true 59 } 60 61 ctxt.Bso = bufio.NewWriter(os.Stdout) 62 defer ctxt.Bso.Flush() 63 64 architecture.Init(ctxt) 65 66 // Create object file, write header. 67 buf, err := bio.Create(*flags.OutputFile) 68 if err != nil { 69 log.Fatal(err) 70 } 71 defer buf.Close() 72 73 if !*flags.SymABIs { 74 buf.WriteString(objabi.HeaderString()) 75 fmt.Fprintf(buf, "!\n") 76 } 77 78 var ok, diag bool 79 var failedFile string 80 for _, f := range flag.Args() { 81 lexer := lex.NewLexer(f) 82 parser := asm.NewParser(ctxt, architecture, lexer, 83 *flags.CompilingRuntime) 84 ctxt.DiagFunc = func(format string, args ...interface{}) { 85 diag = true 86 log.Printf(format, args...) 87 } 88 if *flags.SymABIs { 89 ok = parser.ParseSymABIs(buf) 90 } else { 91 pList := new(obj.Plist) 92 pList.Firstpc, ok = parser.Parse() 93 // reports errors to parser.Errorf 94 if ok { 95 obj.Flushplist(ctxt, pList, nil, *flags.Importpath) 96 } 97 } 98 if !ok { 99 failedFile = f 100 break 101 } 102 } 103 if ok && !*flags.SymABIs { 104 ctxt.NumberSyms() 105 obj.WriteObjFile(ctxt, buf) 106 } 107 if !ok || diag { 108 if failedFile != "" { 109 log.Printf("assembly of %s failed", failedFile) 110 } else { 111 log.Print("assembly failed") 112 } 113 buf.Close() 114 os.Remove(*flags.OutputFile) 115 os.Exit(1) 116 } 117} 118