github.com/bir3/gocompiler@v0.9.2202/src/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/bir3/gocompiler/src/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 symtab, _ = loadXCOFFTable(f.xcoff, "runtime.symtab", "runtime.esymtab") // ignore error, this symbol is not useful anyway 98 return textStart, symtab, pclntab, nil 99 } 100 101 func (f *xcoffFile) text() (textStart uint64, text []byte, err error) { 102 sect := f.xcoff.Section(".text") 103 if sect == nil { 104 return 0, nil, fmt.Errorf("text section not found") 105 } 106 textStart = sect.VirtualAddress 107 text, err = sect.Data() 108 return 109 } 110 111 func findXCOFFSymbol(f *xcoff.File, name string) (*xcoff.Symbol, error) { 112 for _, s := range f.Symbols { 113 if s.Name != name { 114 continue 115 } 116 if s.SectionNumber <= 0 { 117 return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) 118 } 119 if len(f.Sections) < int(s.SectionNumber) { 120 return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) 121 } 122 return s, nil 123 } 124 return nil, fmt.Errorf("no %s symbol found", name) 125 } 126 127 func loadXCOFFTable(f *xcoff.File, sname, ename string) ([]byte, error) { 128 ssym, err := findXCOFFSymbol(f, sname) 129 if err != nil { 130 return nil, err 131 } 132 esym, err := findXCOFFSymbol(f, ename) 133 if err != nil { 134 return nil, err 135 } 136 if ssym.SectionNumber != esym.SectionNumber { 137 return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) 138 } 139 sect := f.Sections[ssym.SectionNumber-1] 140 data, err := sect.Data() 141 if err != nil { 142 return nil, err 143 } 144 return data[ssym.Value:esym.Value], nil 145 } 146 147 func (f *xcoffFile) goarch() string { 148 switch f.xcoff.TargetMachine { 149 case xcoff.U802TOCMAGIC: 150 return "ppc" 151 case xcoff.U64_TOCMAGIC: 152 return "ppc64" 153 } 154 return "" 155 } 156 157 func (f *xcoffFile) loadAddress() (uint64, error) { 158 return 0, fmt.Errorf("unknown load address") 159 } 160 161 func (f *xcoffFile) dwarf() (*dwarf.Data, error) { 162 return f.xcoff.DWARF() 163 }