github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/purgatory/genpurg.go (about) 1 // Copyright 2022 the u-root 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 5 //go:build ignore 6 7 package main 8 9 import ( 10 "bytes" 11 "encoding/hex" 12 "fmt" 13 "io" 14 "io/ioutil" 15 "log" 16 "os" 17 "os/exec" 18 "path/filepath" 19 ) 20 21 func main() { 22 f, err := os.Create("asm.go") 23 if err != nil { 24 log.Fatal(err) 25 } 26 defer func() { 27 if err := f.Close(); err != nil { 28 log.Fatal("Closing %v: %v", f.Name(), err) 29 } 30 }() 31 32 if _, err := fmt.Fprintf(f, "// Copyright 2022 the u-root Authors. All rights reserved\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n"); err != nil { 33 log.Fatal(err) 34 } 35 if _, err := fmt.Fprintf(f, "package purgatory\nvar Purgatories = map[string]*Purgatory {\n"); err != nil { 36 log.Fatal(err) 37 } 38 d, err := ioutil.TempDir("", "kexecgen") 39 if err != nil { 40 log.Fatalf("%v", err) 41 } 42 defer os.RemoveAll(d) 43 44 for _, asm := range asms { 45 // assemble, then create the hexdump of the elf. 46 src := filepath.Join(d, asm.name) + ".S" 47 dst := filepath.Join(d, asm.name) + ".o" 48 out := filepath.Join(d, asm.name) + ".out" 49 if err := ioutil.WriteFile(src, []byte(asm.code), 0666); err != nil { 50 log.Fatal(err) 51 } 52 53 if out, err := exec.Command(asm.cc[0], append(asm.cc[1:], "-nostdinc", "-nostdlib", "-o", dst, src)...).CombinedOutput(); err != nil { 54 log.Printf("%s, %s: %v, %v", src, asm.code, string(out), err) 55 continue 56 } 57 if out, err := exec.Command(asm.ld[0], append(asm.ld[1:], "-nostdlib", "-o", out, dst)...).CombinedOutput(); err != nil { 58 log.Printf("%s, %s: %v, %v", dst, asm.code, string(out), err) 59 continue 60 } 61 code, err := ioutil.ReadFile(out) 62 if err != nil { 63 log.Fatal(err) 64 } 65 if len(code) == 0 { 66 log.Fatalf("%s: no output: dir %v", asm.name, d) 67 } 68 codehex := "\t[]byte{\n" 69 var i int 70 for i < len(code) { 71 codehex += "\t" 72 for j := 0; j < 16 && i < len(code); j++ { 73 codehex = codehex + fmt.Sprintf("%#02x, ", code[i]) 74 i++ 75 } 76 codehex += "\n" 77 } 78 codehex += "\n},\t\n" 79 80 var buf bytes.Buffer 81 if _, err := io.Copy(hex.Dumper(&buf), bytes.NewBuffer(code)); err != nil { 82 log.Fatal(err) 83 } 84 b := buf.Bytes() 85 for i := range b { 86 if b[i] == '`' { 87 b[i] = '.' 88 } 89 } 90 if _, err := fmt.Fprintf(f, "\t\"%s\": &Purgatory{\n\tName: \"%s\",\n\tHexdump: \n`%s\n`,\n\tCode: %s\n},\n", asm.name, asm.name, string(b), codehex); err != nil { 91 log.Fatal(err) 92 } 93 } 94 if _, err := fmt.Fprintf(f, "}\n"); err != nil { 95 log.Printf("Writing final brace: %v", err) 96 } 97 }