package obj import ( `fmt` `io` `os` ) // Format represents the saved binary file format. type Format int const ( // ELF indicates it should be saved as an ELF binary. ELF Format = iota // MachO indicates it should be saved as a Mach-O binary. MachO ) var formatTab = [...]func(w io.Writer, code []byte, base uint64, entry uint64) error { ELF : nil, MachO : assembleMachO, } var formatNames = map[Format]string { ELF : "ELF", MachO : "Mach-O", } // String returns the name of a specified format. func (self Format) String() string { if v, ok := formatNames[self]; ok { return v } else { return fmt.Sprintf("Format(%d)", self) } } // Write assembles a binary executable. func (self Format) Write(w io.Writer, code []byte, base uint64, entry uint64) error { if self >= 0 && int(self) < len(formatTab) && formatTab[self] != nil { return formatTab[self](w, code, base, entry) } else { return fmt.Errorf("unsupported format: %s", self) } } // Generate generates a binary executable file from the specified code. func (self Format) Generate(name string, code []byte, base uint64, entry uint64) error { var fp *os.File var err error /* create the output file */ if fp, err = os.Create(name); err != nil { return err } /* generate the code */ if err = self.Write(fp, code, base, entry); err != nil { _ = fp.Close() _ = os.Remove(name) return err } /* close the file and make it executable */ _ = fp.Close() _ = os.Chmod(name, 0755) return nil }