github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/internal/objfile/xcoff.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 // Parsing of XCOFF executable (AIX) 6 7 package objfile 8 9 import ( 10 "debug/dwarf" 11 "fmt" 12 "github.com/gagliardetto/golang-go/not-internal/xcoff" 13 "io" 14 "unicode" 15 ) 16 17 type xcoffFile struct { 18 xcoff *xcoff.File 19 } 20 21 func openXcoff(r io.ReaderAt) (rawFile, error) { 22 f, err := xcoff.NewFile(r) 23 if err != nil { 24 return nil, err 25 } 26 return &xcoffFile{f}, nil 27 } 28 29 func (f *xcoffFile) symbols() ([]Sym, error) { 30 var syms []Sym 31 for _, s := range f.xcoff.Symbols { 32 const ( 33 N_UNDEF = 0 // An undefined (extern) symbol 34 N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) 35 N_DEBUG = -2 // A debugging symbol 36 ) 37 sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} 38 39 switch s.SectionNumber { 40 case N_UNDEF: 41 sym.Code = 'U' 42 case N_ABS: 43 sym.Code = 'C' 44 case N_DEBUG: 45 sym.Code = '?' 46 default: 47 if s.SectionNumber < 0 || len(f.xcoff.Sections) < int(s.SectionNumber) { 48 return nil, fmt.Errorf("invalid section number in symbol table") 49 } 50 sect := f.xcoff.Sections[s.SectionNumber-1] 51 52 // debug/xcoff returns an offset in the section not the actual address 53 sym.Addr += sect.VirtualAddress 54 55 if s.AuxCSect.SymbolType&0x3 == xcoff.XTY_LD { 56 // The size of a function is contained in the 57 // AUX_FCN entry 58 sym.Size = s.AuxFcn.Size 59 } else { 60 sym.Size = s.AuxCSect.Length 61 } 62 63 sym.Size = s.AuxCSect.Length 64 65 switch sect.Type { 66 case xcoff.STYP_TEXT: 67 if s.AuxCSect.StorageMappingClass == xcoff.XMC_RO { 68 sym.Code = 'R' 69 } else { 70 sym.Code = 'T' 71 } 72 case xcoff.STYP_DATA: 73 sym.Code = 'D' 74 case xcoff.STYP_BSS: 75 sym.Code = 'B' 76 } 77 78 if s.StorageClass == xcoff.C_HIDEXT { 79 // Local symbol 80 sym.Code = unicode.ToLower(sym.Code) 81 } 82 83 } 84 syms = append(syms, sym) 85 } 86 87 return syms, nil 88 } 89 90 func (f *xcoffFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 91 if sect := f.xcoff.Section(".text"); sect != nil { 92 textStart = sect.VirtualAddress 93 } 94 if pclntab, err = loadXCOFFTable(f.xcoff, "runtime.pclntab", "runtime.epclntab"); err != nil { 95 return 0, nil, nil, err 96 } 97 if symtab, err = loadXCOFFTable(f.xcoff, "runtime.symtab", "runtime.esymtab"); err != nil { 98 return 0, nil, nil, err 99 } 100 return textStart, symtab, pclntab, nil 101 } 102 103 func (f *xcoffFile) text() (textStart uint64, text []byte, err error) { 104 sect := f.xcoff.Section(".text") 105 if sect == nil { 106 return 0, nil, fmt.Errorf("text section not found") 107 } 108 textStart = sect.VirtualAddress 109 text, err = sect.Data() 110 return 111 } 112 113 func findXCOFFSymbol(f *xcoff.File, name string) (*xcoff.Symbol, error) { 114 for _, s := range f.Symbols { 115 if s.Name != name { 116 continue 117 } 118 if s.SectionNumber <= 0 { 119 return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) 120 } 121 if len(f.Sections) < int(s.SectionNumber) { 122 return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) 123 } 124 return s, nil 125 } 126 return nil, fmt.Errorf("no %s symbol found", name) 127 } 128 129 func loadXCOFFTable(f *xcoff.File, sname, ename string) ([]byte, error) { 130 ssym, err := findXCOFFSymbol(f, sname) 131 if err != nil { 132 return nil, err 133 } 134 esym, err := findXCOFFSymbol(f, ename) 135 if err != nil { 136 return nil, err 137 } 138 if ssym.SectionNumber != esym.SectionNumber { 139 return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) 140 } 141 sect := f.Sections[ssym.SectionNumber-1] 142 data, err := sect.Data() 143 if err != nil { 144 return nil, err 145 } 146 return data[ssym.Value:esym.Value], nil 147 } 148 149 func (f *xcoffFile) goarch() string { 150 switch f.xcoff.TargetMachine { 151 case xcoff.U802TOCMAGIC: 152 return "ppc" 153 case xcoff.U64_TOCMAGIC: 154 return "ppc64" 155 } 156 return "" 157 } 158 159 func (f *xcoffFile) loadAddress() (uint64, error) { 160 return 0, fmt.Errorf("unknown load address") 161 } 162 163 func (f *xcoffFile) dwarf() (*dwarf.Data, error) { 164 return f.xcoff.DWARF() 165 }