1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements FindGcExportData.
18 func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
19 // See $GOROOT/include/ar.h.
20 hdr := make([]byte, 16+12+6+6+8+10+2)
21 _, err = io.ReadFull(r, hdr)
25 // leave for debugging
27 fmt.Printf("header: %s", hdr)
29 s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
30 size, err = strconv.Atoi(s)
31 if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
32 err = errors.New("invalid archive header")
35 name = strings.TrimSpace(string(hdr[:16]))
39 // FindGcExportData positions the reader r at the beginning of the
40 // export data section of an underlying GC-created object/archive
41 // file by reading from it. The reader must be positioned at the
42 // start of the file before calling this function.
44 func FindGcExportData(r *bufio.Reader) (err error) {
45 // Read first line to make sure this is an object file.
46 line, err := r.ReadSlice('\n')
50 if string(line) == "!<arch>\n" {
51 // Archive file. Scan to __.PKGDEF, which should
52 // be second archive entry.
56 // First entry should be __.GOSYMDEF.
57 // Older archives used __.SYMDEF, so allow that too.
59 if name, size, err = readGopackHeader(r); err != nil {
62 if name != "__.SYMDEF" && name != "__.GOSYMDEF" {
63 err = errors.New("go archive does not begin with __.SYMDEF or __.GOSYMDEF")
67 tmp := make([]byte, block)
73 if _, err = io.ReadFull(r, tmp[:n]); err != nil {
79 // Second entry should be __.PKGDEF.
80 if name, size, err = readGopackHeader(r); err != nil {
83 if name != "__.PKGDEF" {
84 err = errors.New("go archive is missing __.PKGDEF")
88 // Read first line of __.PKGDEF data, so that line
89 // is once again the first line of the input.
90 if line, err = r.ReadSlice('\n'); err != nil {
95 // Now at __.PKGDEF in archive or still at beginning of file.
96 // Either way, line should begin with "go object ".
97 if !strings.HasPrefix(string(line), "go object ") {
98 err = errors.New("not a go object file")
102 // Skip over object header to export data.
103 // Begins after first line with $$.
105 if line, err = r.ReadSlice('\n'); err != nil {