From patchwork Fri Sep 22 18:49:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 817669 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-462805-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="DNQKEXJ2"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xzMxB2qB9z9s5L for ; Sat, 23 Sep 2017 04:50:20 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=AOG3WIU3oFTfoKJ0dSz/tUFT4OEs9psdTxhkGXnHVj7kB7 R5UjRllDssARVip9qG73o0lWR5PGQmeAVYLArW6lRvFioYMxR554ZnwgO8at+Ecj pPgfIEJ5W/zRKNHEu3SrT/OeQokCxzjezLnELItKbUT0W4q3K0C7C2XiS0fVY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=D5YMCuVPf+4JGTXey4f7gDN8UBI=; b=DNQKEXJ2Xt3cxl+dBtXF RcQJ928seXlnIgNTjbt8YpF89y9fEWbYTow1qxDZDmZGjsr6bq2nfsH6pfDPpgq9 5xTFpF0gsp7SEW0Wb1/7D0JY6yQU7eWZ+8iRp5hKcCV3y9JFaEj++aQjVBWZYtsi tSRUeYBiCa2Wb6cd2+NpG1g= Received: (qmail 62466 invoked by alias); 22 Sep 2017 18:50:09 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 61170 invoked by uid 89); 22 Sep 2017 18:50:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-15.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=supervisor, inte, importer, PACKAGES X-HELO: mail-wm0-f47.google.com Received: from mail-wm0-f47.google.com (HELO mail-wm0-f47.google.com) (74.125.82.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 22 Sep 2017 18:50:02 +0000 Received: by mail-wm0-f47.google.com with SMTP id m72so6287761wmc.1 for ; Fri, 22 Sep 2017 11:50:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=zv98icL2uMD0KpcLyo/s+nCJmTwHAK0pfewCESWjCuM=; b=TSBs2o2cO8YFxUI7/DXnPruOY4EHPRJmlKeInb231WQh/WTnsJt0NA6YPX5ESBWNCM JJADxPQ6qfkafdGnWWBBnLelJI1jmK297gj0i5xj/Y/7Cv3jH4wOpa/3VPKd7A4ybFDF ZQzdJSg/3hr26tLoHtlRwbCNAEntnKuppwZZcvbNI7uB8wrYeu6kSHPoK70T717JjXrv hQFmdU7eci8aE2hrHQxZgkYVxD9xgmMH9qZTicL9AImqLVsJnosEOVKzgmeabfAf7S5W fqdTxricHnPPsSNsSTHAlC//1E0XtwgGkHDXXbgA0ITlJ9uTHXRMTBBfua0urpFDcKh2 uDYQ== X-Gm-Message-State: AHPjjUh80+ysm77MfoFt01tXSUtS9a9Ayz6PM9DIEOZFaomwVm20Mp3J 4Aeg815P5mib2/znNErgOEKdxkdxR8iA03etSljn2Dbm X-Google-Smtp-Source: AOwi7QA6fliUIgNSrpoznlDUfrAOmQIhnlFW3qWgn2OqtVstuDEToeSg2J6gQGzlUWxO9KZcaKma7xSt5jZKse5ujj8= X-Received: by 10.80.153.27 with SMTP id k27mr5824662edb.208.1506106200301; Fri, 22 Sep 2017 11:50:00 -0700 (PDT) MIME-Version: 1.0 Received: by 10.80.179.240 with HTTP; Fri, 22 Sep 2017 11:49:55 -0700 (PDT) From: Ian Lance Taylor Date: Fri, 22 Sep 2017 11:49:55 -0700 Message-ID: Subject: libgo patch committed: Add XCOFF support To: gcc-patches , "gofrontend-dev@googlegroups.com" This patch by Tony Reix adds XCOFF support to libgo and to the go and cgo commands. Bootstrapped and ran Go tests on x86_64-pc-linux-gnu. Committed to mainline. Ian Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 253042) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -1fcb9bb3cefb97cfab1e623826a1cc3f6aadd5f7 +e0c1f0b645b12a544b484c0f477f8fb6f5980550 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: libgo/Makefile.am =================================================================== --- libgo/Makefile.am (revision 253042) +++ libgo/Makefile.am (working copy) @@ -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 \ Index: libgo/go/cmd/cgo/gcc.go =================================================================== --- libgo/go/cmd/cgo/gcc.go (revision 253025) +++ libgo/go/cmd/cgo/gcc.go (working copy) @@ -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, 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") } Index: libgo/go/cmd/cgo/out.go =================================================================== --- libgo/go/cmd/cgo/out.go (revision 253025) +++ libgo/go/cmd/cgo/out.go (working copy) @@ -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. Index: libgo/go/cmd/go/internal/work/build.go =================================================================== --- libgo/go/cmd/go/internal/work/build.go (revision 253025) +++ libgo/go/cmd/go/internal/work/build.go (working copy) @@ -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, 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 } Index: libgo/go/debug/dwarf/open.go =================================================================== --- libgo/go/debug/dwarf/open.go (revision 253025) +++ libgo/go/debug/dwarf/open.go (working copy) @@ -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 Index: libgo/go/debug/xcoff/file.go =================================================================== --- libgo/go/debug/xcoff/file.go (revision 0) +++ libgo/go/debug/xcoff/file.go (working copy) @@ -0,0 +1,539 @@ +// 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 implements access to XCOFF (Extended Common Object File Format) files. +package xcoff + +import ( + "debug/dwarf" + "encoding/binary" + "fmt" + "io" + "os" + "strings" +) + +// Information we store about an XCOFF section header. +type SectionHeader struct { + Name string + VirtualAddress uint64 + Size uint64 + Type uint32 +} +type Section struct { + SectionHeader + io.ReaderAt + sr *io.SectionReader +} + +// Information we store about an XCOFF symbol. +type AuxiliaryCSect struct { + Length int64 + StorageMappingClass int + SymbolType int +} +type Symbol struct { + Name string + Value uint64 + SectionNumber int + StorageClass int + AuxCSect AuxiliaryCSect +} + +// Information we store about an imported XCOFF symbol. +type ImportedSymbol struct { + Name string + Library string +} + +// A File represents an open XCOFF file. +type FileHeader struct { + TargetMachine uint16 +} +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 +} + +// 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", magic) + } + + f := new(File) + f.TargetMachine = magic + + // Read XCOFF file header + sr.Seek(0, io.SeekStart) + 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 + sr.Seek(int64(offset), io.SeekStart) + // The first 4 bytes contain the length (in bytes). + var l uint32 + binary.Read(sr, binary.BigEndian, &l) + if l > 4 { + sr.Seek(int64(offset), io.SeekStart) + f.StringTable = make([]byte, l) + io.ReadFull(sr, f.StringTable) + } + + // Read section headers + sr.Seek(int64(hdrsz)+int64(opthdr), io.SeekStart) + 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 + 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 + } + 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 + } + + // Read symbol table + sr.Seek(int64(symptr), io.SeekStart) + f.Symbols = make([]*Symbol, 0) + for i := 0; i < int(nsyms); i++ { + var numaux int + var ok 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) + 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 + 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 < 1 || sym.SectionNumber > int(nscns) { + goto skip + } + sym.Value -= f.Sections[sym.SectionNumber-1].VirtualAddress + + // Read csect auxiliary entry (by convention, it is the last). + sr.Seek(int64((numaux-1)*SYMESZ), io.SeekCurrent) + 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 + sr.Seek(int64(numaux)*SYMESZ, io.SeekCurrent) + } + + 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[0: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_DWARNGE, 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) +} + +// Read a loader section import file IDs. +func (f *File) readImportIDs(s *Section) ([]string, error) { + // Read loader header + s.sr.Seek(0, io.SeekStart) + 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 + s.sr.Seek(int64(impoff), io.SeekStart) + table := make([]byte, istlen) + io.ReadFull(s.sr, table) + + 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 + } else { + path = impidbase + } + 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 + s.sr.Seek(0, io.SeekStart) + 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 + s.sr.Seek(int64(stoff), io.SeekStart) + st := make([]byte, stlen) + io.ReadFull(s.sr, st) + + // Read imported libraries + libs, err := f.readImportIDs(s) + if err != nil { + return nil, err + } + + // Read loader symbol table + s.sr.Seek(int64(symoff), io.SeekStart) + 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 +} + +// FormatError is unused. +// The type is retained for compatibility. +type FormatError struct { +} + +func (e *FormatError) Error() string { + return "unknown error" +} Index: libgo/go/debug/xcoff/file_test.go =================================================================== --- libgo/go/debug/xcoff/file_test.go (revision 0) +++ libgo/go/debug/xcoff/file_test.go (working copy) @@ -0,0 +1,150 @@ +// 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) + } +} Index: libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec =================================================================== --- libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec (revision 0) +++ libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec (working copy) Property changes on: libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-exec =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-exec =================================================================== --- libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-exec (revision 0) +++ libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-exec (working copy) Property changes on: libgo/go/debug/xcoff/testdata/gcc-ppc32-aix-exec ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec =================================================================== --- libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec (revision 0) +++ libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec (working copy) Property changes on: libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-exec =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-exec =================================================================== --- libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-exec (revision 0) +++ libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-exec (working copy) Property changes on: libgo/go/debug/xcoff/testdata/gcc-ppc64-aix-exec ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: libgo/go/debug/xcoff/testdata/hello.c =================================================================== --- libgo/go/debug/xcoff/testdata/hello.c (revision 0) +++ libgo/go/debug/xcoff/testdata/hello.c (working copy) @@ -0,0 +1,7 @@ +#include + +void +main(int argc, char *argv[]) +{ + printf("hello, world\n"); +} Index: libgo/go/debug/xcoff/testdata/xlc-ppc32-aix-exec =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libgo/go/debug/xcoff/testdata/xlc-ppc32-aix-exec =================================================================== --- libgo/go/debug/xcoff/testdata/xlc-ppc32-aix-exec (revision 0) +++ libgo/go/debug/xcoff/testdata/xlc-ppc32-aix-exec (working copy) Property changes on: libgo/go/debug/xcoff/testdata/xlc-ppc32-aix-exec ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: libgo/go/debug/xcoff/testdata/xlc-ppc64-aix-exec =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libgo/go/debug/xcoff/testdata/xlc-ppc64-aix-exec =================================================================== --- libgo/go/debug/xcoff/testdata/xlc-ppc64-aix-exec (revision 0) +++ libgo/go/debug/xcoff/testdata/xlc-ppc64-aix-exec (working copy) Property changes on: libgo/go/debug/xcoff/testdata/xlc-ppc64-aix-exec ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: libgo/go/debug/xcoff/xcoff.go =================================================================== --- libgo/go/debug/xcoff/xcoff.go (revision 0) +++ libgo/go/debug/xcoff/xcoff.go (working copy) @@ -0,0 +1,262 @@ +// 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 +} Index: libgo/go/go/build/deps_test.go =================================================================== --- libgo/go/go/build/deps_test.go (revision 253025) +++ libgo/go/go/build/deps_test.go (working copy) @@ -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"}, Index: libgo/go/go/internal/gccgoimporter/importer.go =================================================================== --- libgo/go/go/internal/gccgoimporter/importer.go (revision 253025) +++ libgo/go/go/internal/gccgoimporter/importer.go (working copy) @@ -8,12 +8,14 @@ package gccgoimporter // import "go/inte 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 = "!