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