mirror of
https://github.com/golang/go
synced 2024-11-11 21:50:21 -07:00
cmd/internal/xcoff: add new debug package for cmd
This commit adds a new package in cmd/internal which aims to debug and load XCOFF files. Updates: #25893, #28037 Change-Id: I47db495bedfa43e9129a831b9b8bbc35b703567b Reviewed-on: https://go-review.googlesource.com/c/138727 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
be0f3c286b
commit
38df4c177b
@ -37,6 +37,9 @@ go src=..
|
|||||||
buildid
|
buildid
|
||||||
testdata
|
testdata
|
||||||
+
|
+
|
||||||
|
xcoff
|
||||||
|
testdata
|
||||||
|
+
|
||||||
gofmt
|
gofmt
|
||||||
gofmt.go
|
gofmt.go
|
||||||
gofmt_test.go
|
gofmt_test.go
|
||||||
|
687
src/cmd/internal/xcoff/file.go
Normal file
687
src/cmd/internal/xcoff/file.go
Normal file
@ -0,0 +1,687 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package xcoff implements access to XCOFF (Extended Common Object File Format) files.
|
||||||
|
package xcoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/dwarf"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SectionHeader holds information about an XCOFF section header.
|
||||||
|
type SectionHeader struct {
|
||||||
|
Name string
|
||||||
|
VirtualAddress uint64
|
||||||
|
Size uint64
|
||||||
|
Type uint32
|
||||||
|
Relptr uint64
|
||||||
|
Nreloc uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Section struct {
|
||||||
|
SectionHeader
|
||||||
|
Relocs []Reloc
|
||||||
|
io.ReaderAt
|
||||||
|
sr *io.SectionReader
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuxiliaryCSect holds information about an XCOFF symbol in an AUX_CSECT entry.
|
||||||
|
type AuxiliaryCSect struct {
|
||||||
|
Length int64
|
||||||
|
StorageMappingClass int
|
||||||
|
SymbolType int
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuxiliaryFcn holds information about an XCOFF symbol in an AUX_FCN entry.
|
||||||
|
type AuxiliaryFcn struct {
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Symbol struct {
|
||||||
|
Name string
|
||||||
|
Value uint64
|
||||||
|
SectionNumber int
|
||||||
|
StorageClass int
|
||||||
|
AuxFcn AuxiliaryFcn
|
||||||
|
AuxCSect AuxiliaryCSect
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reloc struct {
|
||||||
|
VirtualAddress uint64
|
||||||
|
Symbol *Symbol
|
||||||
|
Signed bool
|
||||||
|
InstructionFixed bool
|
||||||
|
Length uint8
|
||||||
|
Type uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportedSymbol holds information about an imported XCOFF symbol.
|
||||||
|
type ImportedSymbol struct {
|
||||||
|
Name string
|
||||||
|
Library string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileHeader holds information about an XCOFF file header.
|
||||||
|
type FileHeader struct {
|
||||||
|
TargetMachine uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// A File represents an open XCOFF file.
|
||||||
|
type File struct {
|
||||||
|
FileHeader
|
||||||
|
Sections []*Section
|
||||||
|
Symbols []*Symbol
|
||||||
|
StringTable []byte
|
||||||
|
LibraryPaths []string
|
||||||
|
|
||||||
|
closer io.Closer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens the named file using os.Open and prepares it for use as an XCOFF binary.
|
||||||
|
func Open(name string) (*File, error) {
|
||||||
|
f, err := os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ff, err := NewFile(f)
|
||||||
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ff.closer = f
|
||||||
|
return ff, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the File.
|
||||||
|
// If the File was created using NewFile directly instead of Open,
|
||||||
|
// Close has no effect.
|
||||||
|
func (f *File) Close() error {
|
||||||
|
var err error
|
||||||
|
if f.closer != nil {
|
||||||
|
err = f.closer.Close()
|
||||||
|
f.closer = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section returns the first section with the given name, or nil if no such
|
||||||
|
// section exists.
|
||||||
|
// Xcoff have section's name limited to 8 bytes. Some sections like .gosymtab
|
||||||
|
// can be trunked but this method will still find them.
|
||||||
|
func (f *File) Section(name string) *Section {
|
||||||
|
for _, s := range f.Sections {
|
||||||
|
if s.Name == name || (len(name) > 8 && s.Name == name[:8]) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SectionByType returns the first section in f with the
|
||||||
|
// given type, or nil if there is no such section.
|
||||||
|
func (f *File) SectionByType(typ uint32) *Section {
|
||||||
|
for _, s := range f.Sections {
|
||||||
|
if s.Type == typ {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// cstring converts ASCII byte sequence b to string.
|
||||||
|
// It stops once it finds 0 or reaches end of b.
|
||||||
|
func cstring(b []byte) string {
|
||||||
|
var i int
|
||||||
|
for i = 0; i < len(b) && b[i] != 0; i++ {
|
||||||
|
}
|
||||||
|
return string(b[:i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// getString extracts a string from an XCOFF string table.
|
||||||
|
func getString(st []byte, offset uint32) (string, bool) {
|
||||||
|
if offset < 4 || int(offset) >= len(st) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return cstring(st[offset:]), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFile creates a new File for accessing an XCOFF binary in an underlying reader.
|
||||||
|
func NewFile(r io.ReaderAt) (*File, error) {
|
||||||
|
sr := io.NewSectionReader(r, 0, 1<<63-1)
|
||||||
|
// Read XCOFF target machine
|
||||||
|
var magic uint16
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, &magic); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if magic != U802TOCMAGIC && magic != U64_TOCMAGIC {
|
||||||
|
return nil, fmt.Errorf("unrecognised XCOFF magic: 0x%x", magic)
|
||||||
|
}
|
||||||
|
|
||||||
|
f := new(File)
|
||||||
|
f.TargetMachine = magic
|
||||||
|
|
||||||
|
// Read XCOFF file header
|
||||||
|
if _, err := sr.Seek(0, os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var nscns uint16
|
||||||
|
var symptr uint64
|
||||||
|
var nsyms int32
|
||||||
|
var opthdr uint16
|
||||||
|
var hdrsz int
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
fhdr := new(FileHeader32)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, fhdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nscns = fhdr.Fnscns
|
||||||
|
symptr = uint64(fhdr.Fsymptr)
|
||||||
|
nsyms = fhdr.Fnsyms
|
||||||
|
opthdr = fhdr.Fopthdr
|
||||||
|
hdrsz = FILHSZ_32
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
fhdr := new(FileHeader64)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, fhdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nscns = fhdr.Fnscns
|
||||||
|
symptr = fhdr.Fsymptr
|
||||||
|
nsyms = fhdr.Fnsyms
|
||||||
|
opthdr = fhdr.Fopthdr
|
||||||
|
hdrsz = FILHSZ_64
|
||||||
|
}
|
||||||
|
|
||||||
|
if symptr == 0 || nsyms <= 0 {
|
||||||
|
return nil, fmt.Errorf("no symbol table")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read string table (located right after symbol table).
|
||||||
|
offset := symptr + uint64(nsyms)*SYMESZ
|
||||||
|
if _, err := sr.Seek(int64(offset), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// The first 4 bytes contain the length (in bytes).
|
||||||
|
var l uint32
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, &l); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if l > 4 {
|
||||||
|
if _, err := sr.Seek(int64(offset), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.StringTable = make([]byte, l)
|
||||||
|
if _, err := io.ReadFull(sr, f.StringTable); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read section headers
|
||||||
|
if _, err := sr.Seek(int64(hdrsz)+int64(opthdr), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Sections = make([]*Section, nscns)
|
||||||
|
for i := 0; i < int(nscns); i++ {
|
||||||
|
var scnptr uint64
|
||||||
|
s := new(Section)
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
shdr := new(SectionHeader32)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, shdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.Name = cstring(shdr.Sname[:])
|
||||||
|
s.VirtualAddress = uint64(shdr.Svaddr)
|
||||||
|
s.Size = uint64(shdr.Ssize)
|
||||||
|
scnptr = uint64(shdr.Sscnptr)
|
||||||
|
s.Type = shdr.Sflags
|
||||||
|
s.Relptr = uint64(shdr.Srelptr)
|
||||||
|
s.Nreloc = uint32(shdr.Snreloc)
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
shdr := new(SectionHeader64)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, shdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.Name = cstring(shdr.Sname[:])
|
||||||
|
s.VirtualAddress = shdr.Svaddr
|
||||||
|
s.Size = shdr.Ssize
|
||||||
|
scnptr = shdr.Sscnptr
|
||||||
|
s.Type = shdr.Sflags
|
||||||
|
s.Relptr = shdr.Srelptr
|
||||||
|
s.Nreloc = shdr.Snreloc
|
||||||
|
}
|
||||||
|
r2 := r
|
||||||
|
if scnptr == 0 { // .bss must have all 0s
|
||||||
|
r2 = zeroReaderAt{}
|
||||||
|
}
|
||||||
|
s.sr = io.NewSectionReader(r2, int64(scnptr), int64(s.Size))
|
||||||
|
s.ReaderAt = s.sr
|
||||||
|
f.Sections[i] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Symbol map needed by relocation
|
||||||
|
var idxToSym = make(map[int]*Symbol)
|
||||||
|
|
||||||
|
// Read symbol table
|
||||||
|
if _, err := sr.Seek(int64(symptr), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Symbols = make([]*Symbol, 0)
|
||||||
|
for i := 0; i < int(nsyms); i++ {
|
||||||
|
var numaux int
|
||||||
|
var ok, needAuxFcn bool
|
||||||
|
sym := new(Symbol)
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
se := new(SymEnt32)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, se); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
numaux = int(se.Nnumaux)
|
||||||
|
sym.SectionNumber = int(se.Nscnum)
|
||||||
|
sym.StorageClass = int(se.Nsclass)
|
||||||
|
sym.Value = uint64(se.Nvalue)
|
||||||
|
needAuxFcn = se.Ntype&SYM_TYPE_FUNC != 0 && numaux > 1
|
||||||
|
zeroes := binary.BigEndian.Uint32(se.Nname[:4])
|
||||||
|
if zeroes != 0 {
|
||||||
|
sym.Name = cstring(se.Nname[:])
|
||||||
|
} else {
|
||||||
|
offset := binary.BigEndian.Uint32(se.Nname[4:])
|
||||||
|
sym.Name, ok = getString(f.StringTable, offset)
|
||||||
|
if !ok {
|
||||||
|
goto skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
se := new(SymEnt64)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, se); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
numaux = int(se.Nnumaux)
|
||||||
|
sym.SectionNumber = int(se.Nscnum)
|
||||||
|
sym.StorageClass = int(se.Nsclass)
|
||||||
|
sym.Value = se.Nvalue
|
||||||
|
needAuxFcn = se.Ntype&SYM_TYPE_FUNC != 0 && numaux > 1
|
||||||
|
sym.Name, ok = getString(f.StringTable, se.Noffset)
|
||||||
|
if !ok {
|
||||||
|
goto skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sym.StorageClass != C_EXT && sym.StorageClass != C_WEAKEXT && sym.StorageClass != C_HIDEXT {
|
||||||
|
goto skip
|
||||||
|
}
|
||||||
|
// Must have at least one csect auxiliary entry.
|
||||||
|
if numaux < 1 || i+numaux >= int(nsyms) {
|
||||||
|
goto skip
|
||||||
|
}
|
||||||
|
|
||||||
|
if sym.SectionNumber > int(nscns) {
|
||||||
|
goto skip
|
||||||
|
}
|
||||||
|
if sym.SectionNumber == 0 {
|
||||||
|
sym.Value = 0
|
||||||
|
} else {
|
||||||
|
sym.Value -= f.Sections[sym.SectionNumber-1].VirtualAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
idxToSym[i] = sym
|
||||||
|
|
||||||
|
// If this symbol is a function, it must retrieve its size from
|
||||||
|
// its AUX_FCN entry.
|
||||||
|
// It can happend that a function symbol doesn't have any AUX_FCN.
|
||||||
|
// In this case, needAuxFcn is false and their size will be set to 0
|
||||||
|
if needAuxFcn {
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
aux := new(AuxFcn32)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, aux); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sym.AuxFcn.Size = int64(aux.Xfsize)
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
aux := new(AuxFcn64)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, aux); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sym.AuxFcn.Size = int64(aux.Xfsize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read csect auxiliary entry (by convention, it is the last).
|
||||||
|
if !needAuxFcn {
|
||||||
|
if _, err := sr.Seek(int64(numaux-1)*SYMESZ, io.SeekCurrent); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += numaux
|
||||||
|
numaux = 0
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
aux := new(AuxCSect32)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, aux); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sym.AuxCSect.SymbolType = int(aux.Xsmtyp & 0x7)
|
||||||
|
sym.AuxCSect.StorageMappingClass = int(aux.Xsmclas)
|
||||||
|
sym.AuxCSect.Length = int64(aux.Xscnlen)
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
aux := new(AuxCSect64)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, aux); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sym.AuxCSect.SymbolType = int(aux.Xsmtyp & 0x7)
|
||||||
|
sym.AuxCSect.StorageMappingClass = int(aux.Xsmclas)
|
||||||
|
sym.AuxCSect.Length = int64(aux.Xscnlenhi)<<32 | int64(aux.Xscnlenlo)
|
||||||
|
}
|
||||||
|
f.Symbols = append(f.Symbols, sym)
|
||||||
|
skip:
|
||||||
|
i += numaux // Skip auxiliary entries
|
||||||
|
if _, err := sr.Seek(int64(numaux)*SYMESZ, io.SeekCurrent); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read relocations
|
||||||
|
// Only for .data or .text section
|
||||||
|
for _, sect := range f.Sections {
|
||||||
|
if sect.Type != STYP_TEXT && sect.Type != STYP_DATA {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sect.Relocs = make([]Reloc, sect.Nreloc)
|
||||||
|
if sect.Relptr == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := sr.Seek(int64(sect.Relptr), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i := uint32(0); i < sect.Nreloc; i++ {
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
rel := new(Reloc32)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, rel); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sect.Relocs[i].VirtualAddress = uint64(rel.Rvaddr)
|
||||||
|
sect.Relocs[i].Symbol = idxToSym[int(rel.Rsymndx)]
|
||||||
|
sect.Relocs[i].Type = rel.Rtype
|
||||||
|
sect.Relocs[i].Length = rel.Rsize&0x3F + 1
|
||||||
|
|
||||||
|
if rel.Rsize&0x80 == 1 {
|
||||||
|
sect.Relocs[i].Signed = true
|
||||||
|
}
|
||||||
|
if rel.Rsize&0x40 == 1 {
|
||||||
|
sect.Relocs[i].InstructionFixed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
rel := new(Reloc64)
|
||||||
|
if err := binary.Read(sr, binary.BigEndian, rel); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sect.Relocs[i].VirtualAddress = rel.Rvaddr
|
||||||
|
sect.Relocs[i].Symbol = idxToSym[int(rel.Rsymndx)]
|
||||||
|
sect.Relocs[i].Type = rel.Rtype
|
||||||
|
sect.Relocs[i].Length = rel.Rsize&0x3F + 1
|
||||||
|
if rel.Rsize&0x80 == 1 {
|
||||||
|
sect.Relocs[i].Signed = true
|
||||||
|
}
|
||||||
|
if rel.Rsize&0x40 == 1 {
|
||||||
|
sect.Relocs[i].InstructionFixed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// zeroReaderAt is ReaderAt that reads 0s.
|
||||||
|
type zeroReaderAt struct{}
|
||||||
|
|
||||||
|
// ReadAt writes len(p) 0s into p.
|
||||||
|
func (w zeroReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
|
||||||
|
for i := range p {
|
||||||
|
p[i] = 0
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data reads and returns the contents of the XCOFF section s.
|
||||||
|
func (s *Section) Data() ([]byte, error) {
|
||||||
|
dat := make([]byte, s.sr.Size())
|
||||||
|
n, err := s.sr.ReadAt(dat, 0)
|
||||||
|
if n == len(dat) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return dat[:n], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSect reads and returns the contents of a csect.
|
||||||
|
func (f *File) CSect(name string) []byte {
|
||||||
|
for _, sym := range f.Symbols {
|
||||||
|
if sym.Name == name && sym.AuxCSect.SymbolType == XTY_SD {
|
||||||
|
if i := sym.SectionNumber - 1; 0 <= i && i < len(f.Sections) {
|
||||||
|
s := f.Sections[i]
|
||||||
|
if sym.Value+uint64(sym.AuxCSect.Length) <= s.Size {
|
||||||
|
dat := make([]byte, sym.AuxCSect.Length)
|
||||||
|
_, err := s.sr.ReadAt(dat, int64(sym.Value))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return dat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) DWARF() (*dwarf.Data, error) {
|
||||||
|
// There are many other DWARF sections, but these
|
||||||
|
// are the ones the debug/dwarf package uses.
|
||||||
|
// Don't bother loading others.
|
||||||
|
var subtypes = [...]uint32{SSUBTYP_DWABREV, SSUBTYP_DWINFO, SSUBTYP_DWLINE, SSUBTYP_DWRNGES, SSUBTYP_DWSTR}
|
||||||
|
var dat [len(subtypes)][]byte
|
||||||
|
for i, subtype := range subtypes {
|
||||||
|
s := f.SectionByType(STYP_DWARF | subtype)
|
||||||
|
if s != nil {
|
||||||
|
b, err := s.Data()
|
||||||
|
if err != nil && uint64(len(b)) < s.Size {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dat[i] = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4]
|
||||||
|
return dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// readImportID returns the import file IDs stored inside the .loader section.
|
||||||
|
// Library name pattern is either path/base/member or base/member
|
||||||
|
func (f *File) readImportIDs(s *Section) ([]string, error) {
|
||||||
|
// Read loader header
|
||||||
|
if _, err := s.sr.Seek(0, os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var istlen uint32
|
||||||
|
var nimpid int32
|
||||||
|
var impoff uint64
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
lhdr := new(LoaderHeader32)
|
||||||
|
if err := binary.Read(s.sr, binary.BigEndian, lhdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
istlen = lhdr.Listlen
|
||||||
|
nimpid = lhdr.Lnimpid
|
||||||
|
impoff = uint64(lhdr.Limpoff)
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
lhdr := new(LoaderHeader64)
|
||||||
|
if err := binary.Read(s.sr, binary.BigEndian, lhdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
istlen = lhdr.Listlen
|
||||||
|
nimpid = lhdr.Lnimpid
|
||||||
|
impoff = lhdr.Limpoff
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read loader import file ID table
|
||||||
|
if _, err := s.sr.Seek(int64(impoff), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
table := make([]byte, istlen)
|
||||||
|
if _, err := io.ReadFull(s.sr, table); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := 0
|
||||||
|
// First import file ID is the default LIBPATH value
|
||||||
|
libpath := cstring(table[offset:])
|
||||||
|
f.LibraryPaths = strings.Split(libpath, ":")
|
||||||
|
offset += len(libpath) + 3 // 3 null bytes
|
||||||
|
all := make([]string, 0)
|
||||||
|
for i := 1; i < int(nimpid); i++ {
|
||||||
|
impidpath := cstring(table[offset:])
|
||||||
|
offset += len(impidpath) + 1
|
||||||
|
impidbase := cstring(table[offset:])
|
||||||
|
offset += len(impidbase) + 1
|
||||||
|
impidmem := cstring(table[offset:])
|
||||||
|
offset += len(impidmem) + 1
|
||||||
|
var path string
|
||||||
|
if len(impidpath) > 0 {
|
||||||
|
path = impidpath + "/" + impidbase + "/" + impidmem
|
||||||
|
} else {
|
||||||
|
path = impidbase + "/" + impidmem
|
||||||
|
}
|
||||||
|
all = append(all, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return all, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportedSymbols returns the names of all symbols
|
||||||
|
// referred to by the binary f that are expected to be
|
||||||
|
// satisfied by other libraries at dynamic load time.
|
||||||
|
// It does not return weak symbols.
|
||||||
|
func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
|
||||||
|
s := f.SectionByType(STYP_LOADER)
|
||||||
|
if s == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
// Read loader header
|
||||||
|
if _, err := s.sr.Seek(0, os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var stlen uint32
|
||||||
|
var stoff uint64
|
||||||
|
var nsyms int32
|
||||||
|
var symoff uint64
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
lhdr := new(LoaderHeader32)
|
||||||
|
if err := binary.Read(s.sr, binary.BigEndian, lhdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
stlen = lhdr.Lstlen
|
||||||
|
stoff = uint64(lhdr.Lstoff)
|
||||||
|
nsyms = lhdr.Lnsyms
|
||||||
|
symoff = LDHDRSZ_32
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
lhdr := new(LoaderHeader64)
|
||||||
|
if err := binary.Read(s.sr, binary.BigEndian, lhdr); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
stlen = lhdr.Lstlen
|
||||||
|
stoff = lhdr.Lstoff
|
||||||
|
nsyms = lhdr.Lnsyms
|
||||||
|
symoff = lhdr.Lsymoff
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read loader section string table
|
||||||
|
if _, err := s.sr.Seek(int64(stoff), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
st := make([]byte, stlen)
|
||||||
|
if _, err := io.ReadFull(s.sr, st); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read imported libraries
|
||||||
|
libs, err := f.readImportIDs(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read loader symbol table
|
||||||
|
if _, err := s.sr.Seek(int64(symoff), os.SEEK_SET); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
all := make([]ImportedSymbol, 0)
|
||||||
|
for i := 0; i < int(nsyms); i++ {
|
||||||
|
var name string
|
||||||
|
var ifile int32
|
||||||
|
var ok bool
|
||||||
|
switch f.TargetMachine {
|
||||||
|
case U802TOCMAGIC:
|
||||||
|
ldsym := new(LoaderSymbol32)
|
||||||
|
if err := binary.Read(s.sr, binary.BigEndian, ldsym); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ldsym.Lsmtype&0x40 == 0 {
|
||||||
|
continue // Imported symbols only
|
||||||
|
}
|
||||||
|
zeroes := binary.BigEndian.Uint32(ldsym.Lname[:4])
|
||||||
|
if zeroes != 0 {
|
||||||
|
name = cstring(ldsym.Lname[:])
|
||||||
|
} else {
|
||||||
|
offset := binary.BigEndian.Uint32(ldsym.Lname[4:])
|
||||||
|
name, ok = getString(st, offset)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ifile = ldsym.Lifile
|
||||||
|
case U64_TOCMAGIC:
|
||||||
|
ldsym := new(LoaderSymbol64)
|
||||||
|
if err := binary.Read(s.sr, binary.BigEndian, ldsym); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ldsym.Lsmtype&0x40 == 0 {
|
||||||
|
continue // Imported symbols only
|
||||||
|
}
|
||||||
|
name, ok = getString(st, ldsym.Loffset)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ifile = ldsym.Lifile
|
||||||
|
}
|
||||||
|
var sym ImportedSymbol
|
||||||
|
sym.Name = name
|
||||||
|
if ifile >= 1 && int(ifile) <= len(libs) {
|
||||||
|
sym.Library = libs[ifile-1]
|
||||||
|
}
|
||||||
|
all = append(all, sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
return all, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportedLibraries returns the names of all libraries
|
||||||
|
// referred to by the binary f that are expected to be
|
||||||
|
// linked with the binary at dynamic link time.
|
||||||
|
func (f *File) ImportedLibraries() ([]string, error) {
|
||||||
|
s := f.SectionByType(STYP_LOADER)
|
||||||
|
if s == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
all, err := f.readImportIDs(s)
|
||||||
|
return all, err
|
||||||
|
}
|
102
src/cmd/internal/xcoff/file_test.go
Normal file
102
src/cmd/internal/xcoff/file_test.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package xcoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fileTest struct {
|
||||||
|
file string
|
||||||
|
hdr FileHeader
|
||||||
|
sections []*SectionHeader
|
||||||
|
needed []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileTests = []fileTest{
|
||||||
|
{
|
||||||
|
"testdata/gcc-ppc32-aix-dwarf2-exec",
|
||||||
|
FileHeader{U802TOCMAGIC},
|
||||||
|
[]*SectionHeader{
|
||||||
|
{".text", 0x10000290, 0x00000bbd, STYP_TEXT, 0x7ae6, 0x36},
|
||||||
|
{".data", 0x20000e4d, 0x00000437, STYP_DATA, 0x7d02, 0x2b},
|
||||||
|
{".bss", 0x20001284, 0x0000021c, STYP_BSS, 0, 0},
|
||||||
|
{".loader", 0x00000000, 0x000004b3, STYP_LOADER, 0, 0},
|
||||||
|
{".dwline", 0x00000000, 0x000000df, STYP_DWARF | SSUBTYP_DWLINE, 0x7eb0, 0x7},
|
||||||
|
{".dwinfo", 0x00000000, 0x00000314, STYP_DWARF | SSUBTYP_DWINFO, 0x7ef6, 0xa},
|
||||||
|
{".dwabrev", 0x00000000, 0x000000d6, STYP_DWARF | SSUBTYP_DWABREV, 0, 0},
|
||||||
|
{".dwarnge", 0x00000000, 0x00000020, STYP_DWARF | SSUBTYP_DWARNGE, 0x7f5a, 0x2},
|
||||||
|
{".dwloc", 0x00000000, 0x00000074, STYP_DWARF | SSUBTYP_DWLOC, 0, 0},
|
||||||
|
{".debug", 0x00000000, 0x00005e4f, STYP_DEBUG, 0, 0},
|
||||||
|
},
|
||||||
|
[]string{"libc.a/shr.o"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testdata/gcc-ppc64-aix-dwarf2-exec",
|
||||||
|
FileHeader{U64_TOCMAGIC},
|
||||||
|
[]*SectionHeader{
|
||||||
|
{".text", 0x10000480, 0x00000afd, STYP_TEXT, 0x8322, 0x34},
|
||||||
|
{".data", 0x20000f7d, 0x000002f3, STYP_DATA, 0x85fa, 0x25},
|
||||||
|
{".bss", 0x20001270, 0x00000428, STYP_BSS, 0, 0},
|
||||||
|
{".loader", 0x00000000, 0x00000535, STYP_LOADER, 0, 0},
|
||||||
|
{".dwline", 0x00000000, 0x000000b4, STYP_DWARF | SSUBTYP_DWLINE, 0x8800, 0x4},
|
||||||
|
{".dwinfo", 0x00000000, 0x0000036a, STYP_DWARF | SSUBTYP_DWINFO, 0x8838, 0x7},
|
||||||
|
{".dwabrev", 0x00000000, 0x000000b5, STYP_DWARF | SSUBTYP_DWABREV, 0, 0},
|
||||||
|
{".dwarnge", 0x00000000, 0x00000040, STYP_DWARF | SSUBTYP_DWARNGE, 0x889a, 0x2},
|
||||||
|
{".dwloc", 0x00000000, 0x00000062, STYP_DWARF | SSUBTYP_DWLOC, 0, 0},
|
||||||
|
{".debug", 0x00000000, 0x00006605, STYP_DEBUG, 0, 0},
|
||||||
|
},
|
||||||
|
[]string{"libc.a/shr_64.o"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpen(t *testing.T) {
|
||||||
|
for i := range fileTests {
|
||||||
|
tt := &fileTests[i]
|
||||||
|
|
||||||
|
f, err := Open(tt.file)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
|
||||||
|
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sh := range f.Sections {
|
||||||
|
if i >= len(tt.sections) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
have := &sh.SectionHeader
|
||||||
|
want := tt.sections[i]
|
||||||
|
if !reflect.DeepEqual(have, want) {
|
||||||
|
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tn := len(tt.sections)
|
||||||
|
fn := len(f.Sections)
|
||||||
|
if tn != fn {
|
||||||
|
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
|
||||||
|
}
|
||||||
|
tl := tt.needed
|
||||||
|
fl, err := f.ImportedLibraries()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tl, fl) {
|
||||||
|
t.Errorf("open %s: loader import = %v, want %v", tt.file, tl, fl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpenFailure(t *testing.T) {
|
||||||
|
filename := "file.go" // not an XCOFF object file
|
||||||
|
_, err := Open(filename) // don't crash
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("open %s: succeeded unexpectedly", filename)
|
||||||
|
}
|
||||||
|
}
|
BIN
src/cmd/internal/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec
vendored
Normal file
BIN
src/cmd/internal/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec
vendored
Normal file
Binary file not shown.
BIN
src/cmd/internal/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec
vendored
Normal file
BIN
src/cmd/internal/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec
vendored
Normal file
Binary file not shown.
7
src/cmd/internal/xcoff/testdata/hello.c
vendored
Normal file
7
src/cmd/internal/xcoff/testdata/hello.c
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
printf("hello, world\n");
|
||||||
|
}
|
367
src/cmd/internal/xcoff/xcoff.go
Normal file
367
src/cmd/internal/xcoff/xcoff.go
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package xcoff
|
||||||
|
|
||||||
|
// File Header.
|
||||||
|
type FileHeader32 struct {
|
||||||
|
Fmagic uint16 // Target machine
|
||||||
|
Fnscns uint16 // Number of sections
|
||||||
|
Ftimedat int32 // Time and date of file creation
|
||||||
|
Fsymptr uint32 // Byte offset to symbol table start
|
||||||
|
Fnsyms int32 // Number of entries in symbol table
|
||||||
|
Fopthdr uint16 // Number of bytes in optional header
|
||||||
|
Fflags uint16 // Flags
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileHeader64 struct {
|
||||||
|
Fmagic uint16 // Target machine
|
||||||
|
Fnscns uint16 // Number of sections
|
||||||
|
Ftimedat int32 // Time and date of file creation
|
||||||
|
Fsymptr uint64 // Byte offset to symbol table start
|
||||||
|
Fopthdr uint16 // Number of bytes in optional header
|
||||||
|
Fflags uint16 // Flags
|
||||||
|
Fnsyms int32 // Number of entries in symbol table
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
FILHSZ_32 = 20
|
||||||
|
FILHSZ_64 = 24
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
U802TOCMAGIC = 0737 // AIX 32-bit XCOFF
|
||||||
|
U64_TOCMAGIC = 0767 // AIX 64-bit XCOFF
|
||||||
|
)
|
||||||
|
|
||||||
|
// Flags that describe the type of the object file.
|
||||||
|
const (
|
||||||
|
F_RELFLG = 0x0001
|
||||||
|
F_EXEC = 0x0002
|
||||||
|
F_LNNO = 0x0004
|
||||||
|
F_FDPR_PROF = 0x0010
|
||||||
|
F_FDPR_OPTI = 0x0020
|
||||||
|
F_DSA = 0x0040
|
||||||
|
F_VARPG = 0x0100
|
||||||
|
F_DYNLOAD = 0x1000
|
||||||
|
F_SHROBJ = 0x2000
|
||||||
|
F_LOADONLY = 0x4000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Section Header.
|
||||||
|
type SectionHeader32 struct {
|
||||||
|
Sname [8]byte // Section name
|
||||||
|
Spaddr uint32 // Physical address
|
||||||
|
Svaddr uint32 // Virtual address
|
||||||
|
Ssize uint32 // Section size
|
||||||
|
Sscnptr uint32 // Offset in file to raw data for section
|
||||||
|
Srelptr uint32 // Offset in file to relocation entries for section
|
||||||
|
Slnnoptr uint32 // Offset in file to line number entries for section
|
||||||
|
Snreloc uint16 // Number of relocation entries
|
||||||
|
Snlnno uint16 // Number of line number entries
|
||||||
|
Sflags uint32 // Flags to define the section type
|
||||||
|
}
|
||||||
|
|
||||||
|
type SectionHeader64 struct {
|
||||||
|
Sname [8]byte // Section name
|
||||||
|
Spaddr uint64 // Physical address
|
||||||
|
Svaddr uint64 // Virtual address
|
||||||
|
Ssize uint64 // Section size
|
||||||
|
Sscnptr uint64 // Offset in file to raw data for section
|
||||||
|
Srelptr uint64 // Offset in file to relocation entries for section
|
||||||
|
Slnnoptr uint64 // Offset in file to line number entries for section
|
||||||
|
Snreloc uint32 // Number of relocation entries
|
||||||
|
Snlnno uint32 // Number of line number entries
|
||||||
|
Sflags uint32 // Flags to define the section type
|
||||||
|
Spad uint32 // Needs to be 72 bytes long
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags defining the section type.
|
||||||
|
const (
|
||||||
|
STYP_DWARF = 0x0010
|
||||||
|
STYP_TEXT = 0x0020
|
||||||
|
STYP_DATA = 0x0040
|
||||||
|
STYP_BSS = 0x0080
|
||||||
|
STYP_EXCEPT = 0x0100
|
||||||
|
STYP_INFO = 0x0200
|
||||||
|
STYP_TDATA = 0x0400
|
||||||
|
STYP_TBSS = 0x0800
|
||||||
|
STYP_LOADER = 0x1000
|
||||||
|
STYP_DEBUG = 0x2000
|
||||||
|
STYP_TYPCHK = 0x4000
|
||||||
|
STYP_OVRFLO = 0x8000
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
SSUBTYP_DWINFO = 0x10000 // DWARF info section
|
||||||
|
SSUBTYP_DWLINE = 0x20000 // DWARF line-number section
|
||||||
|
SSUBTYP_DWPBNMS = 0x30000 // DWARF public names section
|
||||||
|
SSUBTYP_DWPBTYP = 0x40000 // DWARF public types section
|
||||||
|
SSUBTYP_DWARNGE = 0x50000 // DWARF aranges section
|
||||||
|
SSUBTYP_DWABREV = 0x60000 // DWARF abbreviation section
|
||||||
|
SSUBTYP_DWSTR = 0x70000 // DWARF strings section
|
||||||
|
SSUBTYP_DWRNGES = 0x80000 // DWARF ranges section
|
||||||
|
SSUBTYP_DWLOC = 0x90000 // DWARF location lists section
|
||||||
|
SSUBTYP_DWFRAME = 0xA0000 // DWARF frames section
|
||||||
|
SSUBTYP_DWMAC = 0xB0000 // DWARF macros section
|
||||||
|
)
|
||||||
|
|
||||||
|
// Symbol Table Entry.
|
||||||
|
type SymEnt32 struct {
|
||||||
|
Nname [8]byte // Symbol name
|
||||||
|
Nvalue uint32 // Symbol value
|
||||||
|
Nscnum int16 // Section number of symbol
|
||||||
|
Ntype uint16 // Basic and derived type specification
|
||||||
|
Nsclass int8 // Storage class of symbol
|
||||||
|
Nnumaux int8 // Number of auxiliary entries
|
||||||
|
}
|
||||||
|
|
||||||
|
type SymEnt64 struct {
|
||||||
|
Nvalue uint64 // Symbol value
|
||||||
|
Noffset uint32 // Offset of the name in string table or .debug section
|
||||||
|
Nscnum int16 // Section number of symbol
|
||||||
|
Ntype uint16 // Basic and derived type specification
|
||||||
|
Nsclass int8 // Storage class of symbol
|
||||||
|
Nnumaux int8 // Number of auxiliary entries
|
||||||
|
}
|
||||||
|
|
||||||
|
const SYMESZ = 18
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Nscnum
|
||||||
|
N_DEBUG = -2
|
||||||
|
N_ABS = -1
|
||||||
|
N_UNDEF = 0
|
||||||
|
|
||||||
|
//Ntype
|
||||||
|
SYM_V_INTERNAL = 0x1000
|
||||||
|
SYM_V_HIDDEN = 0x2000
|
||||||
|
SYM_V_PROTECTED = 0x3000
|
||||||
|
SYM_V_EXPORTED = 0x4000
|
||||||
|
SYM_TYPE_FUNC = 0x0020 // is function
|
||||||
|
)
|
||||||
|
|
||||||
|
// Storage Class.
|
||||||
|
const (
|
||||||
|
C_NULL = 0 // Symbol table entry marked for deletion
|
||||||
|
C_EXT = 2 // External symbol
|
||||||
|
C_STAT = 3 // Static symbol
|
||||||
|
C_BLOCK = 100 // Beginning or end of inner block
|
||||||
|
C_FCN = 101 // Beginning or end of function
|
||||||
|
C_FILE = 103 // Source file name and compiler information
|
||||||
|
C_HIDEXT = 107 // Unnamed external symbol
|
||||||
|
C_BINCL = 108 // Beginning of include file
|
||||||
|
C_EINCL = 109 // End of include file
|
||||||
|
C_WEAKEXT = 111 // Weak external symbol
|
||||||
|
C_DWARF = 112 // DWARF symbol
|
||||||
|
C_GSYM = 128 // Global variable
|
||||||
|
C_LSYM = 129 // Automatic variable allocated on stack
|
||||||
|
C_PSYM = 130 // Argument to subroutine allocated on stack
|
||||||
|
C_RSYM = 131 // Register variable
|
||||||
|
C_RPSYM = 132 // Argument to function or procedure stored in register
|
||||||
|
C_STSYM = 133 // Statically allocated symbol
|
||||||
|
C_BCOMM = 135 // Beginning of common block
|
||||||
|
C_ECOML = 136 // Local member of common block
|
||||||
|
C_ECOMM = 137 // End of common block
|
||||||
|
C_DECL = 140 // Declaration of object
|
||||||
|
C_ENTRY = 141 // Alternate entry
|
||||||
|
C_FUN = 142 // Function or procedure
|
||||||
|
C_BSTAT = 143 // Beginning of static block
|
||||||
|
C_ESTAT = 144 // End of static block
|
||||||
|
C_GTLS = 145 // Global thread-local variable
|
||||||
|
C_STTLS = 146 // Static thread-local variable
|
||||||
|
)
|
||||||
|
|
||||||
|
// File Auxiliary Entry
|
||||||
|
type AuxFile64 struct {
|
||||||
|
Xfname [8]byte // Name or offset inside string table
|
||||||
|
Xftype uint8 // Source file string type
|
||||||
|
Xauxtype uint8 // Type of auxiliary entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function Auxiliary Entry
|
||||||
|
type AuxFcn32 struct {
|
||||||
|
Xexptr uint32 // File offset to exception table entry
|
||||||
|
Xfsize uint32 // Size of function in bytes
|
||||||
|
Xlnnoptr uint32 // File pointer to line number
|
||||||
|
Xendndx uint32 // Symbol table index of next entry
|
||||||
|
Xpad uint16 // Unused
|
||||||
|
}
|
||||||
|
type AuxFcn64 struct {
|
||||||
|
Xlnnoptr uint64 // File pointer to line number
|
||||||
|
Xfsize uint32 // Size of function in bytes
|
||||||
|
Xendndx uint32 // Symbol table index of next entry
|
||||||
|
Xpad uint8 // Unused
|
||||||
|
Xauxtype uint8 // Type of auxiliary entry
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuxSect64 struct {
|
||||||
|
Xscnlen uint64 // section length
|
||||||
|
Xnreloc uint64 // Num RLDs
|
||||||
|
pad uint8
|
||||||
|
Xauxtype uint8 // Type of auxiliary entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// csect Auxiliary Entry.
|
||||||
|
type AuxCSect32 struct {
|
||||||
|
Xscnlen int32 // Length or symbol table index
|
||||||
|
Xparmhash uint32 // Offset of parameter type-check string
|
||||||
|
Xsnhash uint16 // .typchk section number
|
||||||
|
Xsmtyp uint8 // Symbol alignment and type
|
||||||
|
Xsmclas uint8 // Storage-mapping class
|
||||||
|
Xstab uint32 // Reserved
|
||||||
|
Xsnstab uint16 // Reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuxCSect64 struct {
|
||||||
|
Xscnlenlo uint32 // Lower 4 bytes of length or symbol table index
|
||||||
|
Xparmhash uint32 // Offset of parameter type-check string
|
||||||
|
Xsnhash uint16 // .typchk section number
|
||||||
|
Xsmtyp uint8 // Symbol alignment and type
|
||||||
|
Xsmclas uint8 // Storage-mapping class
|
||||||
|
Xscnlenhi int32 // Upper 4 bytes of length or symbol table index
|
||||||
|
Xpad uint8 // Unused
|
||||||
|
Xauxtype uint8 // Type of auxiliary entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auxiliary type
|
||||||
|
const (
|
||||||
|
_AUX_EXCEPT = 255
|
||||||
|
_AUX_FCN = 254
|
||||||
|
_AUX_SYM = 253
|
||||||
|
_AUX_FILE = 252
|
||||||
|
_AUX_CSECT = 251
|
||||||
|
_AUX_SECT = 250
|
||||||
|
)
|
||||||
|
|
||||||
|
// Symbol type field.
|
||||||
|
const (
|
||||||
|
XTY_ER = 0 // External reference
|
||||||
|
XTY_SD = 1 // Section definition
|
||||||
|
XTY_LD = 2 // Label definition
|
||||||
|
XTY_CM = 3 // Common csect definition
|
||||||
|
)
|
||||||
|
|
||||||
|
// Defines for File auxiliary definitions: x_ftype field of x_file
|
||||||
|
const (
|
||||||
|
XFT_FN = 0 // Source File Name
|
||||||
|
XFT_CT = 1 // Compile Time Stamp
|
||||||
|
XFT_CV = 2 // Compiler Version Number
|
||||||
|
XFT_CD = 128 // Compiler Defined Information
|
||||||
|
)
|
||||||
|
|
||||||
|
// Storage-mapping class.
|
||||||
|
const (
|
||||||
|
XMC_PR = 0 // Program code
|
||||||
|
XMC_RO = 1 // Read-only constant
|
||||||
|
XMC_DB = 2 // Debug dictionary table
|
||||||
|
XMC_TC = 3 // TOC entry
|
||||||
|
XMC_UA = 4 // Unclassified
|
||||||
|
XMC_RW = 5 // Read/Write data
|
||||||
|
XMC_GL = 6 // Global linkage
|
||||||
|
XMC_XO = 7 // Extended operation
|
||||||
|
XMC_SV = 8 // 32-bit supervisor call descriptor
|
||||||
|
XMC_BS = 9 // BSS class
|
||||||
|
XMC_DS = 10 // Function descriptor
|
||||||
|
XMC_UC = 11 // Unnamed FORTRAN common
|
||||||
|
XMC_TC0 = 15 // TOC anchor
|
||||||
|
XMC_TD = 16 // Scalar data entry in the TOC
|
||||||
|
XMC_SV64 = 17 // 64-bit supervisor call descriptor
|
||||||
|
XMC_SV3264 = 18 // Supervisor call descriptor for both 32-bit and 64-bit
|
||||||
|
XMC_TL = 20 // Read/Write thread-local data
|
||||||
|
XMC_UL = 21 // Read/Write thread-local data (.tbss)
|
||||||
|
XMC_TE = 22 // TOC entry
|
||||||
|
)
|
||||||
|
|
||||||
|
// Loader Header.
|
||||||
|
type LoaderHeader32 struct {
|
||||||
|
Lversion int32 // Loader section version number
|
||||||
|
Lnsyms int32 // Number of symbol table entries
|
||||||
|
Lnreloc int32 // Number of relocation table entries
|
||||||
|
Listlen uint32 // Length of import file ID string table
|
||||||
|
Lnimpid int32 // Number of import file IDs
|
||||||
|
Limpoff uint32 // Offset to start of import file IDs
|
||||||
|
Lstlen uint32 // Length of string table
|
||||||
|
Lstoff uint32 // Offset to start of string table
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoaderHeader64 struct {
|
||||||
|
Lversion int32 // Loader section version number
|
||||||
|
Lnsyms int32 // Number of symbol table entries
|
||||||
|
Lnreloc int32 // Number of relocation table entries
|
||||||
|
Listlen uint32 // Length of import file ID string table
|
||||||
|
Lnimpid int32 // Number of import file IDs
|
||||||
|
Lstlen uint32 // Length of string table
|
||||||
|
Limpoff uint64 // Offset to start of import file IDs
|
||||||
|
Lstoff uint64 // Offset to start of string table
|
||||||
|
Lsymoff uint64 // Offset to start of symbol table
|
||||||
|
Lrldoff uint64 // Offset to start of relocation entries
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
LDHDRSZ_32 = 32
|
||||||
|
LDHDRSZ_64 = 56
|
||||||
|
)
|
||||||
|
|
||||||
|
// Loader Symbol.
|
||||||
|
type LoaderSymbol32 struct {
|
||||||
|
Lname [8]byte // Symbol name or byte offset into string table
|
||||||
|
Lvalue uint32 // Address field
|
||||||
|
Lscnum int16 // Section number containing symbol
|
||||||
|
Lsmtype int8 // Symbol type, export, import flags
|
||||||
|
Lsmclas int8 // Symbol storage class
|
||||||
|
Lifile int32 // Import file ID; ordinal of import file IDs
|
||||||
|
Lparm uint32 // Parameter type-check field
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoaderSymbol64 struct {
|
||||||
|
Lvalue uint64 // Address field
|
||||||
|
Loffset uint32 // Byte offset into string table of symbol name
|
||||||
|
Lscnum int16 // Section number containing symbol
|
||||||
|
Lsmtype int8 // Symbol type, export, import flags
|
||||||
|
Lsmclas int8 // Symbol storage class
|
||||||
|
Lifile int32 // Import file ID; ordinal of import file IDs
|
||||||
|
Lparm uint32 // Parameter type-check field
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reloc32 struct {
|
||||||
|
Rvaddr uint32 // (virtual) address of reference
|
||||||
|
Rsymndx uint32 // Index into symbol table
|
||||||
|
Rsize uint8 // Sign and reloc bit len
|
||||||
|
Rtype uint8 // Toc relocation type
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reloc64 struct {
|
||||||
|
Rvaddr uint64 // (virtual) address of reference
|
||||||
|
Rsymndx uint32 // Index into symbol table
|
||||||
|
Rsize uint8 // Sign and reloc bit len
|
||||||
|
Rtype uint8 // Toc relocation type
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
R_POS = 0x00 // A(sym) Positive Relocation
|
||||||
|
R_NEG = 0x01 // -A(sym) Negative Relocation
|
||||||
|
R_REL = 0x02 // A(sym-*) Relative to self
|
||||||
|
R_TOC = 0x03 // A(sym-TOC) Relative to TOC
|
||||||
|
R_TRL = 0x12 // A(sym-TOC) TOC Relative indirect load.
|
||||||
|
|
||||||
|
R_TRLA = 0x13 // A(sym-TOC) TOC Rel load address. modifiable inst
|
||||||
|
R_GL = 0x05 // A(external TOC of sym) Global Linkage
|
||||||
|
R_TCL = 0x06 // A(local TOC of sym) Local object TOC address
|
||||||
|
R_RL = 0x0C // A(sym) Pos indirect load. modifiable instruction
|
||||||
|
R_RLA = 0x0D // A(sym) Pos Load Address. modifiable instruction
|
||||||
|
R_REF = 0x0F // AL0(sym) Non relocating ref. No garbage collect
|
||||||
|
R_BA = 0x08 // A(sym) Branch absolute. Cannot modify instruction
|
||||||
|
R_RBA = 0x18 // A(sym) Branch absolute. modifiable instruction
|
||||||
|
R_BR = 0x0A // A(sym-*) Branch rel to self. non modifiable
|
||||||
|
R_RBR = 0x1A // A(sym-*) Branch rel to self. modifiable instr
|
||||||
|
|
||||||
|
R_TLS = 0x20 // General-dynamic reference to TLS symbol
|
||||||
|
R_TLS_IE = 0x21 // Initial-exec reference to TLS symbol
|
||||||
|
R_TLS_LD = 0x22 // Local-dynamic reference to TLS symbol
|
||||||
|
R_TLS_LE = 0x23 // Local-exec reference to TLS symbol
|
||||||
|
R_TLSM = 0x24 // Module reference to TLS symbol
|
||||||
|
R_TLSML = 0x25 // Module reference to local (own) module
|
||||||
|
|
||||||
|
R_TOCU = 0x30 // Relative to TOC - high order bits
|
||||||
|
R_TOCL = 0x31 // Relative to TOC - low order bits
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user