github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/link/internal/loadxcoff/ldxcoff.go (about)

     1  // Copyright 2018 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  // Package loadxcoff implements a XCOFF file reader.
     6  package loadxcoff
     7  
     8  import (
     9  	"cmd/internal/bio"
    10  	"cmd/internal/objabi"
    11  	"cmd/internal/sys"
    12  	"cmd/link/internal/sym"
    13  	"errors"
    14  	"fmt"
    15  	"internal/xcoff"
    16  )
    17  
    18  // ldSection is an XCOFF section with its symbols.
    19  type ldSection struct {
    20  	xcoff.Section
    21  	sym *sym.Symbol
    22  }
    23  
    24  // TODO(brainman): maybe just add ReadAt method to bio.Reader instead of creating xcoffBiobuf
    25  
    26  // xcoffBiobuf makes bio.Reader look like io.ReaderAt.
    27  type xcoffBiobuf bio.Reader
    28  
    29  func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
    30  	ret := ((*bio.Reader)(f)).Seek(off, 0)
    31  	if ret < 0 {
    32  		return 0, errors.New("fail to seek")
    33  	}
    34  	n, err := f.Read(p)
    35  	if err != nil {
    36  		return 0, err
    37  	}
    38  	return n, nil
    39  }
    40  
    41  // Load loads the Xcoff file pn from f.
    42  // Symbols are written into syms, and a slice of the text symbols is returned.
    43  func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
    44  	errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
    45  		return nil, fmt.Errorf("loadxcoff: %v: %v", pn, fmt.Sprintf(str, args...))
    46  	}
    47  	localSymVersion := syms.IncVersion()
    48  
    49  	var ldSections []*ldSection
    50  
    51  	f, err := xcoff.NewFile((*xcoffBiobuf)(input))
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	defer f.Close()
    56  
    57  	for _, sect := range f.Sections {
    58  		//only text, data and bss section
    59  		if sect.Type < xcoff.STYP_TEXT || sect.Type > xcoff.STYP_BSS {
    60  			continue
    61  		}
    62  		lds := new(ldSection)
    63  		lds.Section = *sect
    64  		name := fmt.Sprintf("%s(%s)", pkg, lds.Name)
    65  		s := syms.Lookup(name, localSymVersion)
    66  
    67  		switch lds.Type {
    68  		default:
    69  			return errorf("unrecognized section type 0x%x", lds.Type)
    70  		case xcoff.STYP_TEXT:
    71  			s.Type = sym.STEXT
    72  		case xcoff.STYP_DATA:
    73  			s.Type = sym.SNOPTRDATA
    74  		case xcoff.STYP_BSS:
    75  			s.Type = sym.SNOPTRBSS
    76  		}
    77  
    78  		s.Size = int64(lds.Size)
    79  		if s.Type != sym.SNOPTRBSS {
    80  			data, err := lds.Section.Data()
    81  			if err != nil {
    82  				return nil, err
    83  			}
    84  			s.P = data
    85  		}
    86  
    87  		lds.sym = s
    88  		ldSections = append(ldSections, lds)
    89  	}
    90  
    91  	// sx = symbol from file
    92  	// s = symbol for syms
    93  	for _, sx := range f.Symbols {
    94  		// get symbol type
    95  		stype, errmsg := getSymbolType(f, sx)
    96  		if errmsg != "" {
    97  			return errorf("error reading symbol %s: %s", sx.Name, errmsg)
    98  		}
    99  		if stype == sym.Sxxx {
   100  			continue
   101  		}
   102  
   103  		s := syms.Lookup(sx.Name, 0)
   104  
   105  		// Text symbol
   106  		if s.Type == sym.STEXT {
   107  			if s.Attr.OnList() {
   108  				return errorf("symbol %s listed multiple times", s.Name)
   109  			}
   110  			s.Attr |= sym.AttrOnList
   111  			textp = append(textp, s)
   112  		}
   113  	}
   114  
   115  	// Read relocations
   116  	for _, sect := range ldSections {
   117  		// TODO(aix): Dwarf section relocation if needed
   118  		if sect.Type != xcoff.STYP_TEXT && sect.Type != xcoff.STYP_DATA {
   119  			continue
   120  		}
   121  		rs := make([]sym.Reloc, sect.Nreloc)
   122  		for i, rx := range sect.Relocs {
   123  			r := &rs[i]
   124  
   125  			r.Sym = syms.Lookup(rx.Symbol.Name, 0)
   126  			if uint64(int32(rx.VirtualAddress)) != rx.VirtualAddress {
   127  				return errorf("virtual address of a relocation is too big: 0x%x", rx.VirtualAddress)
   128  			}
   129  			r.Off = int32(rx.VirtualAddress)
   130  			switch rx.Type {
   131  			default:
   132  				return errorf("section %s: unknown relocation of type 0x%x", sect.Name, rx.Type)
   133  			case xcoff.R_POS:
   134  				// Reloc the address of r.Sym
   135  				// Length should be 64
   136  				if rx.Length != 64 {
   137  					return errorf("section %s: relocation R_POS has length different from 64: %d", sect.Name, rx.Length)
   138  				}
   139  				r.Siz = 8
   140  				r.Type = objabi.R_CONST
   141  				r.Add = int64(rx.Symbol.Value)
   142  
   143  			case xcoff.R_RBR:
   144  				r.Siz = 4
   145  				r.Type = objabi.R_CALLPOWER
   146  				r.Add = 0 //
   147  
   148  			}
   149  		}
   150  		s := sect.sym
   151  		s.R = rs
   152  		s.R = s.R[:sect.Nreloc]
   153  	}
   154  	return textp, nil
   155  
   156  }
   157  
   158  // Convert symbol xcoff type to sym.SymKind
   159  // Returns nil if this shouldn't be added into syms (like .file or .dw symbols )
   160  func getSymbolType(f *xcoff.File, s *xcoff.Symbol) (stype sym.SymKind, err string) {
   161  	// .file symbol
   162  	if s.SectionNumber == -2 {
   163  		if s.StorageClass == xcoff.C_FILE {
   164  			return sym.Sxxx, ""
   165  		}
   166  		return sym.Sxxx, "unrecognised StorageClass for sectionNumber = -2"
   167  	}
   168  
   169  	// extern symbols
   170  	// TODO(aix)
   171  	if s.SectionNumber == 0 {
   172  		return sym.Sxxx, ""
   173  	}
   174  
   175  	sectType := f.Sections[s.SectionNumber-1].SectionHeader.Type
   176  	switch sectType {
   177  	default:
   178  		return sym.Sxxx, fmt.Sprintf("getSymbolType for Section type 0x%x not implemented", sectType)
   179  	case xcoff.STYP_DWARF, xcoff.STYP_DEBUG:
   180  		return sym.Sxxx, ""
   181  	case xcoff.STYP_DATA, xcoff.STYP_BSS, xcoff.STYP_TEXT:
   182  	}
   183  
   184  	switch s.StorageClass {
   185  	default:
   186  		return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x not implemented", s.StorageClass)
   187  	case xcoff.C_HIDEXT, xcoff.C_EXT, xcoff.C_WEAKEXT:
   188  		switch s.AuxCSect.StorageMappingClass {
   189  		default:
   190  			return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x and Storage Map 0x%x not implemented", s.StorageClass, s.AuxCSect.StorageMappingClass)
   191  
   192  		// Program Code
   193  		case xcoff.XMC_PR:
   194  			if sectType == xcoff.STYP_TEXT {
   195  				return sym.STEXT, ""
   196  			}
   197  			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_PR", sectType, s.StorageClass)
   198  
   199  		// Read/Write Data
   200  		case xcoff.XMC_RW:
   201  			if sectType == xcoff.STYP_DATA {
   202  				return sym.SDATA, ""
   203  			}
   204  			if sectType == xcoff.STYP_BSS {
   205  				return sym.SBSS, ""
   206  			}
   207  			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_RW", sectType, s.StorageClass)
   208  
   209  		// Function descriptor
   210  		case xcoff.XMC_DS:
   211  			if sectType == xcoff.STYP_DATA {
   212  				return sym.SDATA, ""
   213  			}
   214  			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
   215  
   216  		// TOC anchor and TOC entry
   217  		case xcoff.XMC_TC0, xcoff.XMC_TE:
   218  			if sectType == xcoff.STYP_DATA {
   219  				return sym.SXCOFFTOC, ""
   220  			}
   221  			return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
   222  
   223  		}
   224  	}
   225  }