"path/filepath"
        "runtime"
        "strings"
+       "sync"
 )
 
 // Data layout and relocation.
 // hostobjCopy creates a copy of the object files in hostobj in a
 // temporary directory.
 func hostobjCopy() (paths []string) {
+       var wg sync.WaitGroup
+       sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
        for i, h := range hostobj {
-               f, err := os.Open(h.file)
-               if err != nil {
-                       Exitf("cannot reopen %s: %v", h.pn, err)
-               }
-               if _, err := f.Seek(h.off, 0); err != nil {
-                       Exitf("cannot seek %s: %v", h.pn, err)
-               }
+               h := h
+               dst := fmt.Sprintf("%s/%06d.o", tmpdir, i)
+               paths = append(paths, dst)
+
+               wg.Add(1)
+               go func() {
+                       sema <- struct{}{}
+                       defer func() {
+                               <-sema
+                               wg.Done()
+                       }()
+                       f, err := os.Open(h.file)
+                       if err != nil {
+                               Exitf("cannot reopen %s: %v", h.pn, err)
+                       }
+                       if _, err := f.Seek(h.off, 0); err != nil {
+                               Exitf("cannot seek %s: %v", h.pn, err)
+                       }
 
-               p := fmt.Sprintf("%s/%06d.o", tmpdir, i)
-               paths = append(paths, p)
-               w, err := os.Create(p)
-               if err != nil {
-                       Exitf("cannot create %s: %v", p, err)
-               }
-               if _, err := io.CopyN(w, f, h.length); err != nil {
-                       Exitf("cannot write %s: %v", p, err)
-               }
-               if err := w.Close(); err != nil {
-                       Exitf("cannot close %s: %v", p, err)
-               }
+                       w, err := os.Create(dst)
+                       if err != nil {
+                               Exitf("cannot create %s: %v", dst, err)
+                       }
+                       if _, err := io.CopyN(w, f, h.length); err != nil {
+                               Exitf("cannot write %s: %v", dst, err)
+                       }
+                       if err := w.Close(); err != nil {
+                               Exitf("cannot close %s: %v", dst, err)
+                       }
+               }()
        }
+       wg.Wait()
        return paths
 }