Skip to content
This repository has been archived by the owner on Sep 7, 2022. It is now read-only.

Commit

Permalink
Merge pull request #3 from dependabot/re-extract-20190731
Browse files Browse the repository at this point in the history
Re-extract (2019-07-31)
  • Loading branch information
hmarr authored Jul 31, 2019
2 parents 1b2f850 + 95ccb2e commit 9a4f14f
Show file tree
Hide file tree
Showing 66 changed files with 4,082 additions and 712 deletions.
140 changes: 140 additions & 0 deletions _internal_/goroot/gc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// 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.

// +build gc

package goroot

import (
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
)

// IsStandardPackage reports whether path is a standard package,
// given goroot and compiler.
func IsStandardPackage(goroot, compiler, path string) bool {
switch compiler {
case "gc":
dir := filepath.Join(goroot, "src", path)
_, err := os.Stat(dir)
return err == nil
case "gccgo":
return gccgoSearch.isStandard(path)
default:
panic("unknown compiler " + compiler)
}
}

// gccgoSearch holds the gccgo search directories.
type gccgoDirs struct {
once sync.Once
dirs []string
}

// gccgoSearch is used to check whether a gccgo package exists in the
// standard library.
var gccgoSearch gccgoDirs

// init finds the gccgo search directories. If this fails it leaves dirs == nil.
func (gd *gccgoDirs) init() {
gccgo := os.Getenv("GCCGO")
if gccgo == "" {
gccgo = "gccgo"
}
bin, err := exec.LookPath(gccgo)
if err != nil {
return
}

allDirs, err := exec.Command(bin, "-print-search-dirs").Output()
if err != nil {
return
}
versionB, err := exec.Command(bin, "-dumpversion").Output()
if err != nil {
return
}
version := strings.TrimSpace(string(versionB))
machineB, err := exec.Command(bin, "-dumpmachine").Output()
if err != nil {
return
}
machine := strings.TrimSpace(string(machineB))

dirsEntries := strings.Split(string(allDirs), "\n")
const prefix = "libraries: ="
var dirs []string
for _, dirEntry := range dirsEntries {
if strings.HasPrefix(dirEntry, prefix) {
dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix))
break
}
}
if len(dirs) == 0 {
return
}

var lastDirs []string
for _, dir := range dirs {
goDir := filepath.Join(dir, "go", version)
if fi, err := os.Stat(goDir); err == nil && fi.IsDir() {
gd.dirs = append(gd.dirs, goDir)
goDir = filepath.Join(goDir, machine)
if fi, err = os.Stat(goDir); err == nil && fi.IsDir() {
gd.dirs = append(gd.dirs, goDir)
}
}
if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
lastDirs = append(lastDirs, dir)
}
}
gd.dirs = append(gd.dirs, lastDirs...)
}

// isStandard reports whether path is a standard library for gccgo.
func (gd *gccgoDirs) isStandard(path string) bool {
// Quick check: if the first path component has a '.', it's not
// in the standard library. This skips most GOPATH directories.
i := strings.Index(path, "/")
if i < 0 {
i = len(path)
}
if strings.Contains(path[:i], ".") {
return false
}

if path == "unsafe" {
// Special case.
return true
}

gd.once.Do(gd.init)
if gd.dirs == nil {
// We couldn't find the gccgo search directories.
// Best guess, since the first component did not contain
// '.', is that this is a standard library package.
return true
}

for _, dir := range gd.dirs {
full := filepath.Join(dir, path)
pkgdir, pkg := filepath.Split(full)
for _, p := range [...]string{
full,
full + ".gox",
pkgdir + "lib" + pkg + ".so",
pkgdir + "lib" + pkg + ".a",
full + ".o",
} {
if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
return true
}
}
}

return false
}
228 changes: 228 additions & 0 deletions _internal_/xcoff/ar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// 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 (
"encoding/binary"
"fmt"
"io"
"os"
"strconv"
"strings"
)

const (
SAIAMAG = 0x8
AIAFMAG = "`\n"
AIAMAG = "<aiaff>\n"
AIAMAGBIG = "<bigaf>\n"

// Sizeof
FL_HSZ_BIG = 0x80
AR_HSZ_BIG = 0x70
)

type bigarFileHeader struct {
Flmagic [SAIAMAG]byte // Archive magic string
Flmemoff [20]byte // Member table offset
Flgstoff [20]byte // 32-bits global symtab offset
Flgst64off [20]byte // 64-bits global symtab offset
Flfstmoff [20]byte // First member offset
Fllstmoff [20]byte // Last member offset
Flfreeoff [20]byte // First member on free list offset
}

type bigarMemberHeader struct {
Arsize [20]byte // File member size
Arnxtmem [20]byte // Next member pointer
Arprvmem [20]byte // Previous member pointer
Ardate [12]byte // File member date
Aruid [12]byte // File member uid
Argid [12]byte // File member gid
Armode [12]byte // File member mode (octal)
Arnamlen [4]byte // File member name length
// _ar_nam is removed because it's easier to get name without it.
}

// Archive represents an open AIX big archive.
type Archive struct {
ArchiveHeader
Members []*Member

closer io.Closer
}

// MemberHeader holds information about a big archive file header
type ArchiveHeader struct {
magic string
}

// Member represents a member of an AIX big archive.
type Member struct {
MemberHeader
sr *io.SectionReader
}

// MemberHeader holds information about a big archive member
type MemberHeader struct {
Name string
Size uint64
}

// OpenArchive opens the named archive using os.Open and prepares it for use
// as an AIX big archive.
func OpenArchive(name string) (*Archive, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
arch, err := NewArchive(f)
if err != nil {
f.Close()
return nil, err
}
arch.closer = f
return arch, nil
}

// Close closes the Archive.
// If the Archive was created using NewArchive directly instead of OpenArchive,
// Close has no effect.
func (a *Archive) Close() error {
var err error
if a.closer != nil {
err = a.closer.Close()
a.closer = nil
}
return err
}

// NewArchive creates a new Archive for accessing an AIX big archive in an underlying reader.
func NewArchive(r io.ReaderAt) (*Archive, error) {
parseDecimalBytes := func(b []byte) (int64, error) {
return strconv.ParseInt(strings.TrimSpace(string(b)), 10, 64)
}
sr := io.NewSectionReader(r, 0, 1<<63-1)

// Read File Header
var magic [SAIAMAG]byte
if _, err := sr.ReadAt(magic[:], 0); err != nil {
return nil, err
}

arch := new(Archive)
switch string(magic[:]) {
case AIAMAGBIG:
arch.magic = string(magic[:])
case AIAMAG:
return nil, fmt.Errorf("small AIX archive not supported")
default:
return nil, fmt.Errorf("unrecognised archive magic: 0x%x", magic)
}

var fhdr bigarFileHeader
if _, err := sr.Seek(0, os.SEEK_SET); err != nil {
return nil, err
}
if err := binary.Read(sr, binary.BigEndian, &fhdr); err != nil {
return nil, err
}

off, err := parseDecimalBytes(fhdr.Flfstmoff[:])
if err != nil {
return nil, fmt.Errorf("error parsing offset of first member in archive header(%q); %v", fhdr, err)
}

if off == 0 {
// Occurs if the archive is empty.
return arch, nil
}

lastoff, err := parseDecimalBytes(fhdr.Fllstmoff[:])
if err != nil {
return nil, fmt.Errorf("error parsing offset of first member in archive header(%q); %v", fhdr, err)
}

// Read members
for {
// Read Member Header
// The member header is normally 2 bytes larger. But it's easier
// to read the name if the header is read without _ar_nam.
// However, AIAFMAG must be read afterward.
if _, err := sr.Seek(off, os.SEEK_SET); err != nil {
return nil, err
}

var mhdr bigarMemberHeader
if err := binary.Read(sr, binary.BigEndian, &mhdr); err != nil {
return nil, err
}

member := new(Member)
arch.Members = append(arch.Members, member)

size, err := parseDecimalBytes(mhdr.Arsize[:])
if err != nil {
return nil, fmt.Errorf("error parsing size in member header(%q); %v", mhdr, err)
}
member.Size = uint64(size)

// Read name
namlen, err := parseDecimalBytes(mhdr.Arnamlen[:])
if err != nil {
return nil, fmt.Errorf("error parsing name length in member header(%q); %v", mhdr, err)
}
name := make([]byte, namlen)
if err := binary.Read(sr, binary.BigEndian, name); err != nil {
return nil, err
}
member.Name = string(name)

fileoff := off + AR_HSZ_BIG + namlen
if fileoff&1 != 0 {
fileoff++
if _, err := sr.Seek(1, os.SEEK_CUR); err != nil {
return nil, err
}
}

// Read AIAFMAG string
var fmag [2]byte
if err := binary.Read(sr, binary.BigEndian, &fmag); err != nil {
return nil, err
}
if string(fmag[:]) != AIAFMAG {
return nil, fmt.Errorf("AIAFMAG not found after member header")
}

fileoff += 2 // Add the two bytes of AIAFMAG
member.sr = io.NewSectionReader(sr, fileoff, size)

if off == lastoff {
break
}
off, err = parseDecimalBytes(mhdr.Arnxtmem[:])
if err != nil {
return nil, fmt.Errorf("error parsing offset of first member in archive header(%q); %v", fhdr, err)
}

}

return arch, nil

}

// GetFile returns the XCOFF file defined by member name.
// FIXME: This doesn't work if an archive has two members with the same
// name which can occur if a archive has both 32-bits and 64-bits files.
func (arch *Archive) GetFile(name string) (*File, error) {
for _, mem := range arch.Members {
if mem.Name == name {
return NewFile(mem.sr)
}
}
return nil, fmt.Errorf("unknown member %s in archive", name)

}
Loading

0 comments on commit 9a4f14f

Please sign in to comment.