github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/link/load.go (about)

     1  // Copyright 2014 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  // Loading of code and data fragments from package files into final image.
     6  
     7  package main
     8  
     9  import "os"
    10  
    11  // load allocates segment images, populates them with data
    12  // read from package files, and applies relocations to the data.
    13  func (p *Prog) load() {
    14  	// TODO(rsc): mmap the output file and store the data directly.
    15  	// That will make writing the output file more efficient.
    16  	for _, seg := range p.Segments {
    17  		seg.Data = make([]byte, seg.FileSize)
    18  	}
    19  	for _, pkg := range p.Packages {
    20  		p.loadPackage(pkg)
    21  	}
    22  }
    23  
    24  // loadPackage loads and relocates data for all the
    25  // symbols needed in the given package.
    26  func (p *Prog) loadPackage(pkg *Package) {
    27  	if pkg.File == "" {
    28  		// This "package" contains internally generated symbols only.
    29  		// All such symbols have a sym.Bytes field holding the actual data
    30  		// (if any), plus relocations.
    31  		for _, sym := range pkg.Syms {
    32  			if sym.Bytes == nil {
    33  				continue
    34  			}
    35  			seg := sym.Section.Segment
    36  			off := sym.Addr - seg.VirtAddr
    37  			data := seg.Data[off : off+Addr(sym.Size)]
    38  			copy(data, sym.Bytes)
    39  			p.relocateSym(sym, data)
    40  		}
    41  		return
    42  	}
    43  
    44  	// Package stored in file.
    45  	f, err := os.Open(pkg.File)
    46  	if err != nil {
    47  		p.errorf("%v", err)
    48  		return
    49  	}
    50  	defer f.Close()
    51  
    52  	// TODO(rsc): Mmap file into memory.
    53  
    54  	for _, sym := range pkg.Syms {
    55  		if sym.Data.Size == 0 {
    56  			continue
    57  		}
    58  		// TODO(rsc): If not using mmap, at least coalesce nearby reads.
    59  		if sym.Section == nil {
    60  			p.errorf("internal error: missing section for %s", sym.Name)
    61  		}
    62  		seg := sym.Section.Segment
    63  		off := sym.Addr - seg.VirtAddr
    64  		if off >= Addr(len(seg.Data)) || off+Addr(sym.Data.Size) > Addr(len(seg.Data)) {
    65  			p.errorf("internal error: allocated space for %s too small: %d bytes for %d+%d (%d)", sym, len(seg.Data), off, sym.Data.Size, sym.Size)
    66  		}
    67  		data := seg.Data[off : off+Addr(sym.Data.Size)]
    68  		_, err := f.ReadAt(data, sym.Data.Offset)
    69  		if err != nil {
    70  			p.errorf("reading %v: %v", sym.SymID, err)
    71  		}
    72  		p.relocateSym(sym, data)
    73  	}
    74  }
    75  
    76  // TODO(rsc): Define full enumeration for relocation types.
    77  const (
    78  	R_ADDR    = 1
    79  	R_SIZE    = 2
    80  	R_CALL    = 3
    81  	R_CALLARM = 4
    82  	R_CALLIND = 5
    83  	R_CONST   = 6
    84  	R_PCREL   = 7
    85  )
    86  
    87  // relocateSym applies relocations to sym's data.
    88  func (p *Prog) relocateSym(sym *Sym, data []byte) {
    89  	for i := range sym.Reloc {
    90  		r := &sym.Reloc[i]
    91  		targ := p.Syms[r.Sym]
    92  		if targ == nil {
    93  			p.errorf("%v: reference to undefined symbol %v", sym, r.Sym)
    94  			continue
    95  		}
    96  		val := targ.Addr + Addr(r.Add)
    97  		switch r.Type {
    98  		default:
    99  			p.errorf("%v: unknown relocation type %d", sym, r.Type)
   100  		case R_ADDR, R_CALLIND:
   101  			// ok
   102  		case R_PCREL, R_CALL:
   103  			val -= sym.Addr + Addr(r.Offset+r.Size)
   104  		}
   105  		frag := data[r.Offset : r.Offset+r.Size]
   106  		switch r.Size {
   107  		default:
   108  			p.errorf("%v: unknown relocation size %d", sym, r.Size)
   109  		case 4:
   110  			// TODO(rsc): Check for overflow?
   111  			p.byteorder.PutUint32(frag, uint32(val))
   112  		case 8:
   113  			p.byteorder.PutUint64(frag, uint64(val))
   114  		}
   115  	}
   116  }