github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/x/tools/go/gcimporter15/exportdata.go (about) 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. 4 5 // +build go1.5 6 7 // This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go, tagged for go1.5. 8 9 // This file implements FindExportData. 10 11 package gcimporter 12 13 import ( 14 "bufio" 15 "errors" 16 "fmt" 17 "io" 18 "strconv" 19 "strings" 20 ) 21 22 func readGopackHeader(r *bufio.Reader) (name string, size int, err error) { 23 // See $GOROOT/include/ar.h. 24 hdr := make([]byte, 16+12+6+6+8+10+2) 25 _, err = io.ReadFull(r, hdr) 26 if err != nil { 27 return 28 } 29 // leave for debugging 30 if false { 31 fmt.Printf("header: %s", hdr) 32 } 33 s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10])) 34 size, err = strconv.Atoi(s) 35 if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' { 36 err = errors.New("invalid archive header") 37 return 38 } 39 name = strings.TrimSpace(string(hdr[:16])) 40 return 41 } 42 43 // FindExportData positions the reader r at the beginning of the 44 // export data section of an underlying GC-created object/archive 45 // file by reading from it. The reader must be positioned at the 46 // start of the file before calling this function. The hdr result 47 // is the string before the export data, either "$$" or "$$B". 48 // 49 func FindExportData(r *bufio.Reader) (hdr string, err error) { 50 // Read first line to make sure this is an object file. 51 line, err := r.ReadSlice('\n') 52 if err != nil { 53 return 54 } 55 56 if string(line) == "!<arch>\n" { 57 // Archive file. Scan to __.PKGDEF. 58 var name string 59 var size int 60 if name, size, err = readGopackHeader(r); err != nil { 61 return 62 } 63 64 // Optional leading __.GOSYMDEF or __.SYMDEF. 65 // Read and discard. 66 if name == "__.SYMDEF" || name == "__.GOSYMDEF" { 67 const block = 4096 68 tmp := make([]byte, block) 69 for size > 0 { 70 n := size 71 if n > block { 72 n = block 73 } 74 if _, err = io.ReadFull(r, tmp[:n]); err != nil { 75 return 76 } 77 size -= n 78 } 79 80 if name, _, err = readGopackHeader(r); err != nil { 81 return 82 } 83 } 84 85 // First real entry should be __.PKGDEF. 86 if name != "__.PKGDEF" { 87 err = errors.New("go archive is missing __.PKGDEF") 88 return 89 } 90 91 // Read first line of __.PKGDEF data, so that line 92 // is once again the first line of the input. 93 if line, err = r.ReadSlice('\n'); err != nil { 94 return 95 } 96 } 97 98 // Now at __.PKGDEF in archive or still at beginning of file. 99 // Either way, line should begin with "go object ". 100 if !strings.HasPrefix(string(line), "go object ") { 101 err = errors.New("not a go object file") 102 return 103 } 104 105 // Skip over object header to export data. 106 // Begins after first line starting with $$. 107 for line[0] != '$' { 108 if line, err = r.ReadSlice('\n'); err != nil { 109 return 110 } 111 } 112 hdr = string(line) 113 114 return 115 }