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