Commit c90df0d2 by Ian Lance Taylor

debug/xcoff,cmd: add XCOFF support

    
    Reviewed-on: https://go-review.googlesource.com/64592

From-SVN: r253105
parent f25afa93
1fcb9bb3cefb97cfab1e623826a1cc3f6aadd5f7
e0c1f0b645b12a544b484c0f477f8fb6f5980550
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
......@@ -217,7 +217,8 @@ toolexeclibgodebug_DATA = \
debug/gosym.gox \
debug/macho.gox \
debug/pe.gox \
debug/plan9obj.gox
debug/plan9obj.gox \
debug/xcoff.gox
toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding
......@@ -722,6 +723,7 @@ PACKAGES = \
debug/macho \
debug/pe \
debug/plan9obj \
debug/xcoff \
encoding \
encoding/ascii85 \
encoding/asn1 \
......@@ -1293,6 +1295,7 @@ TEST_PACKAGES = \
debug/macho/check \
debug/pe/check \
debug/plan9obj/check \
debug/xcoff/check \
encoding/ascii85/check \
encoding/asn1/check \
encoding/base32/check \
......
......@@ -612,7 +612,8 @@ toolexeclibgodebug_DATA = \
debug/gosym.gox \
debug/macho.gox \
debug/pe.gox \
debug/plan9obj.gox
debug/plan9obj.gox \
debug/xcoff.gox
toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding
toolexeclibgoencoding_DATA = \
......@@ -873,6 +874,7 @@ PACKAGES = \
debug/macho \
debug/pe \
debug/plan9obj \
debug/xcoff \
encoding \
encoding/ascii85 \
encoding/asn1 \
......@@ -1298,6 +1300,7 @@ TEST_PACKAGES = \
debug/macho/check \
debug/pe/check \
debug/plan9obj/check \
debug/xcoff/check \
encoding/ascii85/check \
encoding/asn1/check \
encoding/base32/check \
......
......@@ -13,6 +13,7 @@ import (
"debug/elf"
"debug/macho"
"debug/pe"
"debug/xcoff"
"encoding/binary"
"errors"
"flag"
......@@ -1289,6 +1290,10 @@ func (p *Package) gccMachine() []string {
return []string{"-mabi=64"}
case "mips", "mipsle":
return []string{"-mabi=32"}
case "ppc64":
if goos == "aix" {
return []string{"-maix64"}
}
}
return nil
}
......@@ -1616,7 +1621,79 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
return d, ints, floats, strs
}
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
if f, err := xcoff.Open(gccTmp()); err == nil {
defer f.Close()
d, err := f.DWARF()
if err != nil {
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
}
bo := binary.BigEndian
for _, s := range f.Symbols {
switch {
case isDebugInts(s.Name):
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
if sdat, err := sect.Data(); err == nil {
data := sdat[s.Value:]
ints = make([]int64, len(data)/8)
for i := range ints {
ints[i] = int64(bo.Uint64(data[i*8:]))
}
}
}
}
case isDebugFloats(s.Name):
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
if sdat, err := sect.Data(); err == nil {
data := sdat[s.Value:]
floats = make([]float64, len(data)/8)
for i := range floats {
floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
}
}
}
}
default:
if n := indexOfDebugStr(s.Name); n != -1 {
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
if sdat, err := sect.Data(); err == nil {
data := sdat[s.Value:]
strdata[n] = string(data)
}
}
}
break
}
if n := indexOfDebugStrlen(s.Name); n != -1 {
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
if sdat, err := sect.Data(); err == nil {
data := sdat[s.Value:]
strlen := bo.Uint64(data[:8])
if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
fatalf("string literal too big")
}
strlens[n] = int(strlen)
}
}
}
break
}
}
}
buildStrings()
return d, ints, floats, strs
}
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", gccTmp())
panic("not reached")
}
......
......@@ -9,6 +9,7 @@ import (
"debug/elf"
"debug/macho"
"debug/pe"
"debug/xcoff"
"fmt"
"go/ast"
"go/printer"
......@@ -324,7 +325,25 @@ func dynimport(obj string) {
return
}
fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
if f, err := xcoff.Open(obj); err == nil {
sym, err := f.ImportedSymbols()
if err != nil {
fatalf("cannot load imported symbols from XCOFF file %s: %v", obj, err)
}
for _, s := range sym {
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, s.Name, s.Library)
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from XCOFF file %s: %v", obj, err)
}
for _, l := range lib {
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
fatalf("cannot parse %s as ELF, Mach-O, PE or XCOFF", obj)
}
// Construct a gcc struct matching the gc argument frame.
......
......@@ -9,6 +9,7 @@ import (
"bytes"
"container/heap"
"debug/elf"
"debug/xcoff"
"errors"
"flag"
"fmt"
......@@ -745,9 +746,13 @@ func (b *Builder) Init() {
func readpkglist(shlibpath string) (pkgs []*load.Package) {
var stk load.ImportStack
if cfg.BuildToolchainName == "gccgo" {
f, _ := elf.Open(shlibpath)
sect := f.Section(".go_export")
data, _ := sect.Data()
var data []byte
if f, err := elf.Open(shlibpath); err == nil {
sect := f.Section(".go_export")
data, _ = sect.Data()
} else if f, err := xcoff.Open(shlibpath); err == nil {
data = f.CSect(".go_export")
}
scanner := bufio.NewScanner(bytes.NewBuffer(data))
for scanner.Scan() {
t := scanner.Text()
......@@ -1815,6 +1820,7 @@ func (b *Builder) cover(a *Action, dst, src string, perm os.FileMode, varName st
var objectMagic = [][]byte{
{'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive
{'<', 'b', 'i', 'g', 'a', 'f', '>', '\n'}, // Package archive (AIX format)
{'\x7F', 'E', 'L', 'F'}, // ELF
{0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit
{0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit
......@@ -1824,6 +1830,8 @@ var objectMagic = [][]byte{
{0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386
{0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64
{0x00, 0x00, 0x06, 0x47}, // Plan 9 arm
{0x01, 0xDF}, // XCOFF32
{0x01, 0xF7}, // XCOFF64
}
func isObject(s string) bool {
......@@ -3308,6 +3316,10 @@ func (b *Builder) gccArchArgs() []string {
return []string{"-mabi=64"}
case "mips", "mipsle":
return []string{"-mabi=32", "-march=mips32"}
case "ppc64":
if cfg.Goos == "aix" {
return []string{"-maix64"}
}
}
return nil
}
......
......@@ -33,7 +33,7 @@ type Data struct {
// New returns a new Data object initialized from the given parameters.
// Rather than calling this function directly, clients should typically use
// the DWARF method of the File type of the appropriate package debug/elf,
// debug/macho, or debug/pe.
// debug/macho, debug/pe, or debug/xcoff.
//
// The []byte arguments are the data from the corresponding debug section
// in the object file; for example, for an ELF object, abbrev is the contents of
......
// Copyright 2014 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-exec",
FileHeader{U802TOCMAGIC},
[]*SectionHeader{
{".text", 0x10000150, 0x00000bbd, STYP_TEXT},
{".data", 0x20000d0d, 0x0000042b, STYP_DATA},
{".bss", 0x20001138, 0x00000218, STYP_BSS},
{".loader", 0x00000000, 0x000004b3, STYP_LOADER},
{".debug", 0x00000000, 0x0000751e, STYP_DEBUG},
},
[]string{"libc.a"},
},
{
"testdata/gcc-ppc64-aix-exec",
FileHeader{U64_TOCMAGIC},
[]*SectionHeader{
{".text", 0x10000240, 0x00000afd, STYP_TEXT},
{".data", 0x20000d3d, 0x000002e3, STYP_DATA},
{".bss", 0x20001020, 0x00000428, STYP_BSS},
{".loader", 0x00000000, 0x00000535, STYP_LOADER},
{".debug", 0x00000000, 0x00008238, STYP_DEBUG},
},
[]string{"libc.a"},
},
{
"testdata/xlc-ppc32-aix-exec",
FileHeader{U802TOCMAGIC},
[]*SectionHeader{
{".text", 0x10000150, 0x00000372, STYP_TEXT},
{".data", 0x200004c2, 0x0000032e, STYP_DATA},
{".bss", 0x200007f0, 0x00000004, STYP_BSS},
{".loader", 0x00000000, 0x0000029d, STYP_LOADER},
{".debug", 0x00000000, 0x0000008f, STYP_DEBUG},
},
[]string{"libc.a"},
},
{
"testdata/xlc-ppc64-aix-exec",
FileHeader{U64_TOCMAGIC},
[]*SectionHeader{
{".text", 0x100000240, 0x00000326, STYP_TEXT},
{".data", 0x110000566, 0x00000182, STYP_DATA},
{".bss", 0x1100006e8, 0x00000008, STYP_BSS},
{".loader", 0x00000000, 0x0000029b, STYP_LOADER},
{".debug", 0x00000000, 0x000000ea, STYP_DEBUG},
},
[]string{"libc.a"},
},
{
"testdata/gcc-ppc32-aix-dwarf2-exec",
FileHeader{U802TOCMAGIC},
[]*SectionHeader{
{".text", 0x10000290, 0x00000bbd, STYP_TEXT},
{".data", 0x20000e4d, 0x00000437, STYP_DATA},
{".bss", 0x20001284, 0x0000021c, STYP_BSS},
{".loader", 0x00000000, 0x000004b3, STYP_LOADER},
{".dwline", 0x00000000, 0x000000df, STYP_DWARF | SSUBTYP_DWLINE},
{".dwinfo", 0x00000000, 0x00000314, STYP_DWARF | SSUBTYP_DWINFO},
{".dwabrev", 0x00000000, 0x000000d6, STYP_DWARF | SSUBTYP_DWABREV},
{".dwarnge", 0x00000000, 0x00000020, STYP_DWARF | SSUBTYP_DWARNGE},
{".dwloc", 0x00000000, 0x00000074, STYP_DWARF | SSUBTYP_DWLOC},
{".debug", 0x00000000, 0x00005e4f, STYP_DEBUG},
},
[]string{"libc.a"},
},
{
"testdata/gcc-ppc64-aix-dwarf2-exec",
FileHeader{U64_TOCMAGIC},
[]*SectionHeader{
{".text", 0x10000480, 0x00000afd, STYP_TEXT},
{".data", 0x20000f7d, 0x000002f3, STYP_DATA},
{".bss", 0x20001270, 0x00000428, STYP_BSS},
{".loader", 0x00000000, 0x00000535, STYP_LOADER},
{".dwline", 0x00000000, 0x000000b4, STYP_DWARF | SSUBTYP_DWLINE},
{".dwinfo", 0x00000000, 0x0000036a, STYP_DWARF | SSUBTYP_DWINFO},
{".dwabrev", 0x00000000, 0x000000b5, STYP_DWARF | SSUBTYP_DWABREV},
{".dwarnge", 0x00000000, 0x00000040, STYP_DWARF | SSUBTYP_DWARNGE},
{".dwloc", 0x00000000, 0x00000062, STYP_DWARF | SSUBTYP_DWLOC},
{".debug", 0x00000000, 0x00006605, STYP_DEBUG},
},
[]string{"libc.a"},
},
}
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)
}
}
#include <stdio.h>
void
main(int argc, char *argv[])
{
printf("hello, world\n");
}
// Copyright 2017 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
// 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
)
// 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
}
// 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
)
// 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
}
......@@ -221,7 +221,7 @@ var pkgDeps = map[string][]string{
"go/constant": {"L4", "go/token", "math/big"},
"go/importer": {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"},
"go/internal/gcimporter": {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"},
"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "text/scanner"},
"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "debug/xcoff", "go/constant", "go/token", "go/types", "text/scanner"},
"go/internal/srcimporter": {"L4", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"},
"go/types": {"L4", "GOPARSER", "container/heap", "go/constant"},
......@@ -243,6 +243,7 @@ var pkgDeps = map[string][]string{
"debug/macho": {"L4", "OS", "debug/dwarf"},
"debug/pe": {"L4", "OS", "debug/dwarf"},
"debug/plan9obj": {"L4", "OS"},
"debug/xcoff": {"L4", "OS", "debug/dwarf"},
"encoding": {"L4"},
"encoding/ascii85": {"L4"},
"encoding/asn1": {"L4", "math/big"},
......
......@@ -8,12 +8,14 @@ package gccgoimporter // import "go/internal/gccgoimporter"
import (
"bytes"
"debug/elf"
"debug/xcoff"
"fmt"
"go/types"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
......@@ -66,11 +68,12 @@ const (
gccgov2Magic = "v2;\n"
goimporterMagic = "\n$$ "
archiveMagic = "!<ar"
aixbigafMagic = "<big"
)
// Opens the export data file at the given path. If this is an ELF file,
// Opens the export data file at the given path. If this is an object file,
// searches for and opens the .go_export section. If this is an archive,
// reads the export data from the first member, which is assumed to be an ELF file.
// reads the export data from the first member, which is assumed to be an object file.
// This is intended to replicate the logic in gofrontend.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
f, err := os.Open(fpath)
......@@ -90,43 +93,58 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
return
}
var elfreader io.ReaderAt
var objreader io.ReaderAt
switch string(magic[:]) {
case gccgov1Magic, gccgov2Magic, goimporterMagic:
// Raw export data.
reader = f
return
case archiveMagic:
case archiveMagic, aixbigafMagic:
// TODO(pcc): Read the archive directly instead of using "ar".
f.Close()
closer = nil
cmd := exec.Command("ar", "p", fpath)
if runtime.GOOS == "aix" && runtime.GOARCH == "ppc64" {
// AIX puts both 32-bit and 64-bit objects in the same archive.
// Tell the AIX "ar" command to only care about 64-bit objects.
cmd.Env = append(os.Environ(), "OBJECT_MODE=64")
}
var out []byte
out, err = cmd.Output()
if err != nil {
return
}
elfreader = bytes.NewReader(out)
objreader = bytes.NewReader(out)
default:
elfreader = f
objreader = f
}
ef, err := elf.NewFile(elfreader)
if err != nil {
ef, err := elf.NewFile(objreader)
if err == nil {
sec := ef.Section(".go_export")
if sec == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath)
return
}
reader = sec.Open()
return
}
sec := ef.Section(".go_export")
if sec == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath)
xf, err := xcoff.NewFile(objreader)
if err == nil {
sdat := xf.CSect(".go_export")
if sdat == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath)
return
}
reader = bytes.NewReader(sdat)
return
}
reader = sec.Open()
return
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment