...

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

     1	// Copyright 2014 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 Plan 9 a.out executables.
     6	
     7	package objfile
     8	
     9	import (
    10		"debug/dwarf"
    11		"debug/plan9obj"
    12		"errors"
    13		"fmt"
    14		"io"
    15		"sort"
    16	)
    17	
    18	var validSymType = map[rune]bool{
    19		'T': true,
    20		't': true,
    21		'D': true,
    22		'd': true,
    23		'B': true,
    24		'b': true,
    25	}
    26	
    27	type plan9File struct {
    28		plan9 *plan9obj.File
    29	}
    30	
    31	func openPlan9(r io.ReaderAt) (rawFile, error) {
    32		f, err := plan9obj.NewFile(r)
    33		if err != nil {
    34			return nil, err
    35		}
    36		return &plan9File{f}, nil
    37	}
    38	
    39	func (f *plan9File) symbols() ([]Sym, error) {
    40		plan9Syms, err := f.plan9.Symbols()
    41		if err != nil {
    42			return nil, err
    43		}
    44	
    45		// Build sorted list of addresses of all symbols.
    46		// We infer the size of a symbol by looking at where the next symbol begins.
    47		var addrs []uint64
    48		for _, s := range plan9Syms {
    49			if !validSymType[s.Type] {
    50				continue
    51			}
    52			addrs = append(addrs, s.Value)
    53		}
    54		sort.Sort(uint64s(addrs))
    55	
    56		var syms []Sym
    57	
    58		for _, s := range plan9Syms {
    59			if !validSymType[s.Type] {
    60				continue
    61			}
    62			sym := Sym{Addr: s.Value, Name: s.Name, Code: s.Type}
    63			i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
    64			if i < len(addrs) {
    65				sym.Size = int64(addrs[i] - s.Value)
    66			}
    67			syms = append(syms, sym)
    68		}
    69	
    70		return syms, nil
    71	}
    72	
    73	func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
    74		textStart = f.plan9.LoadAddress + f.plan9.HdrSize
    75		if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil {
    76			// We didn't find the symbols, so look for the names used in 1.3 and earlier.
    77			// TODO: Remove code looking for the old symbols when we no longer care about 1.3.
    78			var err2 error
    79			if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil {
    80				return 0, nil, nil, err
    81			}
    82		}
    83		if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil {
    84			// Same as above.
    85			var err2 error
    86			if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil {
    87				return 0, nil, nil, err
    88			}
    89		}
    90		return textStart, symtab, pclntab, nil
    91	}
    92	
    93	func (f *plan9File) text() (textStart uint64, text []byte, err error) {
    94		sect := f.plan9.Section("text")
    95		if sect == nil {
    96			return 0, nil, fmt.Errorf("text section not found")
    97		}
    98		textStart = f.plan9.LoadAddress + f.plan9.HdrSize
    99		text, err = sect.Data()
   100		return
   101	}
   102	
   103	func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
   104		syms, err := f.Symbols()
   105		if err != nil {
   106			return nil, err
   107		}
   108		for _, s := range syms {
   109			if s.Name != name {
   110				continue
   111			}
   112			return &s, nil
   113		}
   114		return nil, fmt.Errorf("no %s symbol found", name)
   115	}
   116	
   117	func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
   118		ssym, err := findPlan9Symbol(f, sname)
   119		if err != nil {
   120			return nil, err
   121		}
   122		esym, err := findPlan9Symbol(f, ename)
   123		if err != nil {
   124			return nil, err
   125		}
   126		sect := f.Section("text")
   127		if sect == nil {
   128			return nil, err
   129		}
   130		data, err := sect.Data()
   131		if err != nil {
   132			return nil, err
   133		}
   134		textStart := f.LoadAddress + f.HdrSize
   135		return data[ssym.Value-textStart : esym.Value-textStart], nil
   136	}
   137	
   138	func (f *plan9File) goarch() string {
   139		switch f.plan9.Magic {
   140		case plan9obj.Magic386:
   141			return "386"
   142		case plan9obj.MagicAMD64:
   143			return "amd64"
   144		case plan9obj.MagicARM:
   145			return "arm"
   146		}
   147		return ""
   148	}
   149	
   150	func (f *plan9File) loadAddress() (uint64, error) {
   151		return 0, fmt.Errorf("unknown load address")
   152	}
   153	
   154	func (f *plan9File) dwarf() (*dwarf.Data, error) {
   155		return nil, errors.New("no DWARF data in Plan 9 file")
   156	}
   157	

View as plain text