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