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  }