Source file src/cmd/internal/objfile/xcoff.go

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

View as plain text