...

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) < 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	}
   166	

View as plain text