1
2
3
4
5 package ld
6
7 import (
8 "reflect"
9 "syscall"
10 "unsafe"
11 )
12
13
14
15
16 func (out *OutBuf) Mmap(filesize uint64) error {
17 oldlen := len(out.buf)
18 if oldlen != 0 {
19 out.munmap()
20 }
21
22 err := out.f.Truncate(int64(filesize))
23 if err != nil {
24 Exitf("resize output file failed: %v", err)
25 }
26
27 low, high := uint32(filesize), uint32(filesize>>32)
28 fmap, err := syscall.CreateFileMapping(syscall.Handle(out.f.Fd()), nil, syscall.PAGE_READWRITE, high, low, nil)
29 if err != nil {
30 return err
31 }
32 defer syscall.CloseHandle(fmap)
33
34 ptr, err := syscall.MapViewOfFile(fmap, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, uintptr(filesize))
35 if err != nil {
36 return err
37 }
38 bufHdr := (*reflect.SliceHeader)(unsafe.Pointer(&out.buf))
39 bufHdr.Data = ptr
40 bufHdr.Len = int(filesize)
41 bufHdr.Cap = int(filesize)
42
43
44 if uint64(oldlen+len(out.heap)) > filesize {
45 panic("mmap size too small")
46 }
47 copy(out.buf[oldlen:], out.heap)
48 out.heap = out.heap[:0]
49 return nil
50 }
51
52 func (out *OutBuf) munmap() {
53 if out.buf == nil {
54 return
55 }
56
57
58 err := syscall.FlushViewOfFile(uintptr(unsafe.Pointer(&out.buf[0])), 0)
59 if err != nil {
60 Exitf("FlushViewOfFile failed: %v", err)
61 }
62 err = syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&out.buf[0])))
63 out.buf = nil
64 if err != nil {
65 Exitf("UnmapViewOfFile failed: %v", err)
66 }
67 }
68
View as plain text