/
reader_linux.go
106 lines (83 loc) · 2 KB
/
reader_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package procio
import (
"fmt"
"io"
"os"
"syscall"
"github.com/sirupsen/logrus"
"github.com/targodan/go-errors"
)
type memfileReader struct {
proc Process
seg *MemorySegmentInfo
memfile *os.File
position uintptr
}
func newMemoryReader(proc Process, seg *MemorySegmentInfo) (memoryReaderImpl, error) {
memfile, err := os.OpenFile(fmt.Sprintf("%s/%d/mem", procPath, proc.PID()), os.O_RDONLY, 0400)
if err != nil {
return nil, fmt.Errorf("could not open process memory for reading, reason: %w", err)
}
rdr := &memfileReader{
proc: proc,
seg: seg,
memfile: memfile,
position: 0,
}
return rdr, nil
}
func (rdr *memfileReader) computeFileOffset() uintptr {
return rdr.seg.BaseAddress + rdr.position
}
func (rdr *memfileReader) Read(data []byte) (int, error) {
if rdr.position >= rdr.seg.Size {
return 0, io.EOF
}
l := uintptr(len(data))
if rdr.position+l > rdr.seg.Size {
l = rdr.seg.Size - rdr.position
data = data[:l]
}
if len(data) == 0 {
return 0, nil
}
fd := int(rdr.memfile.Fd())
offset := int64(rdr.computeFileOffset())
n, err := syscall.Pread(fd, data, offset)
logrus.WithFields(logrus.Fields{
"pid": rdr.proc.PID(),
"baseAddress": rdr.seg.BaseAddress,
"state": rdr.seg.State,
"size": rdr.seg.Size,
}).Tracef("pread(%d, len == %d, %d) -> %d, %v", fd, len(data), offset, n, err)
if n == 0 {
return n, io.EOF
}
rdr.position += uintptr(n)
return n, err
}
func (rdr *memfileReader) Seek(offset int64, whence int) (pos int64, err error) {
switch whence {
case io.SeekStart:
pos = offset
case io.SeekCurrent:
pos = int64(rdr.position) + offset
case io.SeekEnd:
pos = int64(rdr.seg.Size) + offset
}
if pos < 0 {
pos = 0
err = errors.New("cannot seek before start of segment")
}
rdr.position = uintptr(pos)
return
}
func (rdr *memfileReader) Process() Process {
return rdr.proc
}
func (rdr *memfileReader) Segment() *MemorySegmentInfo {
return rdr.seg
}
func (rdr *memfileReader) Close() error {
return rdr.memfile.Close()
}