github.com/cloudwego/iasm@v0.2.0/cmd/iasm/main.go (about) 1 // 2 // Copyright 2024 CloudWeGo Authors 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 package main 18 19 import ( 20 `os` 21 22 `github.com/cloudwego/iasm/obj` 23 `github.com/cloudwego/iasm/repl` 24 `github.com/cloudwego/iasm/x86_64` 25 `nullprogram.com/x/optparse` 26 ) 27 28 type _FileFormat int 29 30 const ( 31 _F_bin _FileFormat = iota + 1 32 _F_macho 33 _F_elf 34 ) 35 36 var formatTab = map[string]_FileFormat { 37 "bin" : _F_bin, 38 "macho" : _F_macho, 39 "elf" : _F_elf, 40 } 41 42 func usage() { 43 println("usage: iasm [OPTIONS] <source>") 44 println(" iasm -h | --help") 45 println() 46 println("General Options:") 47 println(` -D DEF, --define=DEF Passing the defination to preprocessor`) 48 println(" -f FMT, --format=FMT Select output format") 49 println(" bin Flat raw binary (default)") 50 println(" macho Mach-O executable") 51 println(" elf ELF executable") 52 println() 53 println(" -h, --help This help message") 54 println(" -o FILE, --output=FILE Output file name") 55 println(" -s, --gas-compat GAS compatible mode") 56 println() 57 println("Environment Variables:") 58 println(" CPP The C Preprocessor") 59 println() 60 } 61 62 func compile() { 63 var err error 64 var src string 65 var rem []string 66 var asm x86_64.Assembler 67 var ret []optparse.Result 68 69 /* options list */ 70 opts := []optparse.Option { 71 { "help" , 'h', optparse.KindNone }, 72 { "define" , 'D', optparse.KindRequired }, 73 { "format" , 'f', optparse.KindRequired }, 74 { "output" , 'o', optparse.KindRequired }, 75 { "gas-compat" , 's', optparse.KindNone }, 76 } 77 78 /* parse the options */ 79 if ret, rem, err = optparse.Parse(opts, os.Args); err != nil { 80 println("iasm: error: " + err.Error()) 81 usage() 82 } 83 84 /* default values */ 85 help := false 86 mgas := false 87 ffmt := "bin" 88 fout := "a.out" 89 defs := []string(nil) 90 91 /* check the result */ 92 for _, vv := range ret { 93 switch vv.Short { 94 case 'h': help = true 95 case 's': mgas = true 96 case 'f': ffmt = vv.Optarg 97 case 'o': fout = vv.Optarg 98 case 'D': defs = append(defs, vv.Optarg) 99 } 100 } 101 102 /* check file format */ 103 if _, ok := formatTab[ffmt]; !ok { 104 println("iasm: error: unknown file format: " + ffmt) 105 os.Exit(1) 106 } 107 108 /* check for help */ 109 if help { 110 usage() 111 } 112 113 /* must have source files */ 114 if len(rem) == 0 { 115 println("iasm: error: missing input file.") 116 os.Exit(1) 117 } 118 119 /* must have exactly 1 source file */ 120 if len(rem) != 1 { 121 println("iasm: error: too many input files.") 122 os.Exit(1) 123 } 124 125 /* preprocess the source file */ 126 if src, err = preprocess(rem[0], defs); err != nil { 127 println("iasm: error: failed to run preprocessor: " + err.Error()) 128 os.Exit(1) 129 } 130 131 /* check for GAS compatible mode */ 132 if mgas { 133 asm.Options().InstructionAliasing = true 134 asm.Options().IgnoreUnknownDirectives = true 135 } 136 137 /* assemble the source */ 138 if err = asm.Assemble(src); err != nil { 139 println("iasm: error: " + err.Error()) 140 os.Exit(1) 141 } 142 143 /* check for format */ 144 switch formatTab[ffmt] { 145 case _F_bin : err = os.WriteFile(fout, asm.Code(), 0755) 146 case _F_elf : err = obj.ELF.Generate(fout, asm.Code(), uint64(asm.Base()), uint64(asm.Entry())) 147 case _F_macho : err = obj.MachO.Generate(fout, asm.Code(), uint64(asm.Base()), uint64(asm.Entry())) 148 default : panic("invalid format: " + ffmt) 149 } 150 151 /* check for errors */ 152 if err != nil { 153 println("iasm: error: " + err.Error()) 154 os.Exit(1) 155 } 156 } 157 158 func main() { 159 if len(os.Args) != 1 { 160 compile() 161 } else { 162 new(repl.IASM).Start() 163 } 164 }