aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/debug/elf/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/debug/elf/reader.go')
-rw-r--r--libgo/go/debug/elf/reader.go108
1 files changed, 108 insertions, 0 deletions
diff --git a/libgo/go/debug/elf/reader.go b/libgo/go/debug/elf/reader.go
new file mode 100644
index 00000000000..17b57165bc3
--- /dev/null
+++ b/libgo/go/debug/elf/reader.go
@@ -0,0 +1,108 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elf
+
+import (
+ "io"
+ "os"
+)
+
+// errorReader returns error from all operations.
+type errorReader struct {
+ error
+}
+
+func (r errorReader) Read(p []byte) (n int, err error) {
+ return 0, r.error
+}
+
+func (r errorReader) ReadAt(p []byte, off int64) (n int, err error) {
+ return 0, r.error
+}
+
+func (r errorReader) Seek(offset int64, whence int) (int64, error) {
+ return 0, r.error
+}
+
+func (r errorReader) Close() error {
+ return r.error
+}
+
+// readSeekerFromReader converts an io.Reader into an io.ReadSeeker.
+// In general Seek may not be efficient, but it is optimized for
+// common cases such as seeking to the end to find the length of the
+// data.
+type readSeekerFromReader struct {
+ reset func() (io.Reader, error)
+ r io.Reader
+ size int64
+ offset int64
+}
+
+func (r *readSeekerFromReader) start() {
+ x, err := r.reset()
+ if err != nil {
+ r.r = errorReader{err}
+ } else {
+ r.r = x
+ }
+ r.offset = 0
+}
+
+func (r *readSeekerFromReader) Read(p []byte) (n int, err error) {
+ if r.r == nil {
+ r.start()
+ }
+ n, err = r.r.Read(p)
+ r.offset += int64(n)
+ return n, err
+}
+
+func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) {
+ var newOffset int64
+ switch whence {
+ case 0:
+ newOffset = offset
+ case 1:
+ newOffset = r.offset + offset
+ case 2:
+ newOffset = r.size + offset
+ default:
+ return 0, os.ErrInvalid
+ }
+
+ switch {
+ case newOffset == r.offset:
+ return newOffset, nil
+
+ case newOffset < 0, newOffset > r.size:
+ return 0, os.ErrInvalid
+
+ case newOffset == 0:
+ r.r = nil
+
+ case newOffset == r.size:
+ r.r = errorReader{io.EOF}
+
+ default:
+ if newOffset < r.offset {
+ // Restart at the beginning.
+ r.start()
+ }
+ // Read until we reach offset.
+ var buf [512]byte
+ for r.offset < newOffset {
+ b := buf[:]
+ if newOffset-r.offset < int64(len(buf)) {
+ b = buf[:newOffset-r.offset]
+ }
+ if _, err := r.Read(b); err != nil {
+ return 0, err
+ }
+ }
+ }
+ r.offset = newOffset
+ return r.offset, nil
+}