OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [exp/] [types/] [exportdata.go] - Rev 747

Compare with Previous | Blame | View Log

// Copyright 2011 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.

// This file implements ExportData.

package types

import (
        "bufio"
        "errors"
        "fmt"
        "io"
        "os"
        "strconv"
        "strings"
)

func readGopackHeader(buf *bufio.Reader) (name string, size int, err error) {
        // See $GOROOT/include/ar.h.
        hdr := make([]byte, 16+12+6+6+8+10+2)
        _, err = io.ReadFull(buf, hdr)
        if err != nil {
                return
        }
        if trace {
                fmt.Printf("header: %s", hdr)
        }
        s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
        size, err = strconv.Atoi(s)
        if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
                err = errors.New("invalid archive header")
                return
        }
        name = strings.TrimSpace(string(hdr[:16]))
        return
}

type dataReader struct {
        *bufio.Reader
        io.Closer
}

// ExportData returns a readCloser positioned at the beginning of the
// export data section of the given object/archive file, or an error.
// It is the caller's responsibility to close the readCloser.
//
func ExportData(filename string) (rc io.ReadCloser, err error) {
        file, err := os.Open(filename)
        if err != nil {
                return
        }

        defer func() {
                if err != nil {
                        file.Close()
                        // Add file name to error.
                        err = fmt.Errorf("reading export data: %s: %v", filename, err)
                }
        }()

        buf := bufio.NewReader(file)

        // Read first line to make sure this is an object file.
        line, err := buf.ReadSlice('\n')
        if err != nil {
                return
        }
        if string(line) == "!<arch>\n" {
                // Archive file.  Scan to __.PKGDEF, which should
                // be second archive entry.
                var name string
                var size int

                // First entry should be __.SYMDEF.
                // Read and discard.
                if name, size, err = readGopackHeader(buf); err != nil {
                        return
                }
                if name != "__.SYMDEF" {
                        err = errors.New("go archive does not begin with __.SYMDEF")
                        return
                }
                const block = 4096
                tmp := make([]byte, block)
                for size > 0 {
                        n := size
                        if n > block {
                                n = block
                        }
                        _, err = io.ReadFull(buf, tmp[:n])
                        if err != nil {
                                return
                        }
                        size -= n
                }

                // Second entry should be __.PKGDEF.
                if name, size, err = readGopackHeader(buf); err != nil {
                        return
                }
                if name != "__.PKGDEF" {
                        err = errors.New("go archive is missing __.PKGDEF")
                        return
                }

                // Read first line of __.PKGDEF data, so that line
                // is once again the first line of the input.
                line, err = buf.ReadSlice('\n')
                if err != nil {
                        return
                }
        }

        // Now at __.PKGDEF in archive or still at beginning of file.
        // Either way, line should begin with "go object ".
        if !strings.HasPrefix(string(line), "go object ") {
                err = errors.New("not a go object file")
                return
        }

        // Skip over object header to export data.
        // Begins after first line with $$.
        for line[0] != '$' {
                line, err = buf.ReadSlice('\n')
                if err != nil {
                        return
                }
        }

        rc = &dataReader{buf, file}
        return
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.