mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd: add XCOFF objfile and adapt cmd/nm tests
This commit adds a new file format in cmd/internal/objfile for XCOFF. It also adapts tests inside cmd/nm for AIX. Updates: #25893 Change-Id: I1e55ea0b7f7d08a871343bee27d11e2d3baad254 Reviewed-on: https://go-review.googlesource.com/c/145397 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
5cc8089948
commit
49dafc70c8
3 changed files with 161 additions and 10 deletions
|
|
@ -61,6 +61,7 @@ var openers = []func(io.ReaderAt) (rawFile, error){
|
||||||
openMacho,
|
openMacho,
|
||||||
openPE,
|
openPE,
|
||||||
openPlan9,
|
openPlan9,
|
||||||
|
openXcoff,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens the named file.
|
// Open opens the named file.
|
||||||
|
|
|
||||||
133
src/cmd/internal/objfile/xcoff.go
Normal file
133
src/cmd/internal/objfile/xcoff.go
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Parsing of XCOFF executable (AIX)
|
||||||
|
|
||||||
|
package objfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/internal/xcoff"
|
||||||
|
"debug/dwarf"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type xcoffFile struct {
|
||||||
|
xcoff *xcoff.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func openXcoff(r io.ReaderAt) (rawFile, error) {
|
||||||
|
f, err := xcoff.NewFile(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &xcoffFile{f}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *xcoffFile) symbols() ([]Sym, error) {
|
||||||
|
var syms []Sym
|
||||||
|
for _, s := range f.xcoff.Symbols {
|
||||||
|
const (
|
||||||
|
N_UNDEF = 0 // An undefined (extern) symbol
|
||||||
|
N_ABS = -1 // An absolute symbol (e_value is a constant, not an address)
|
||||||
|
N_DEBUG = -2 // A debugging symbol
|
||||||
|
)
|
||||||
|
sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
|
||||||
|
|
||||||
|
switch s.SectionNumber {
|
||||||
|
case N_UNDEF:
|
||||||
|
sym.Code = 'U'
|
||||||
|
case N_ABS:
|
||||||
|
sym.Code = 'C'
|
||||||
|
case N_DEBUG:
|
||||||
|
sym.Code = '?'
|
||||||
|
default:
|
||||||
|
if s.SectionNumber < 0 || len(f.xcoff.Sections) < int(s.SectionNumber) {
|
||||||
|
return nil, fmt.Errorf("invalid section number in symbol table")
|
||||||
|
}
|
||||||
|
sect := f.xcoff.Sections[s.SectionNumber-1]
|
||||||
|
|
||||||
|
// debug/xcoff returns an offset in the section not the actual address
|
||||||
|
sym.Addr += sect.VirtualAddress
|
||||||
|
|
||||||
|
if s.AuxCSect.SymbolType&0x3 == xcoff.XTY_LD {
|
||||||
|
// The size of a function is contained in the
|
||||||
|
// AUX_FCN entry
|
||||||
|
sym.Size = s.AuxFcn.Size
|
||||||
|
} else {
|
||||||
|
sym.Size = s.AuxCSect.Length
|
||||||
|
}
|
||||||
|
|
||||||
|
sym.Size = s.AuxCSect.Length
|
||||||
|
|
||||||
|
switch sect.Type {
|
||||||
|
case xcoff.STYP_TEXT:
|
||||||
|
if s.AuxCSect.StorageMappingClass == xcoff.XMC_RO {
|
||||||
|
sym.Code = 'R'
|
||||||
|
} else {
|
||||||
|
sym.Code = 'T'
|
||||||
|
}
|
||||||
|
case xcoff.STYP_DATA:
|
||||||
|
sym.Code = 'D'
|
||||||
|
case xcoff.STYP_BSS:
|
||||||
|
sym.Code = 'B'
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StorageClass == xcoff.C_HIDEXT {
|
||||||
|
// Local symbol
|
||||||
|
sym.Code = unicode.ToLower(sym.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
syms = append(syms, sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
return syms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *xcoffFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
|
||||||
|
if sect := f.xcoff.Section(".text"); sect != nil {
|
||||||
|
textStart = sect.VirtualAddress
|
||||||
|
}
|
||||||
|
if sect := f.xcoff.Section(".gosymtab"); sect != nil {
|
||||||
|
if symtab, err = sect.Data(); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sect := f.xcoff.Section(".gopclntab"); sect != nil {
|
||||||
|
if pclntab, err = sect.Data(); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textStart, symtab, pclntab, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *xcoffFile) text() (textStart uint64, text []byte, err error) {
|
||||||
|
sect := f.xcoff.Section(".text")
|
||||||
|
if sect == nil {
|
||||||
|
return 0, nil, fmt.Errorf("text section not found")
|
||||||
|
}
|
||||||
|
textStart = sect.VirtualAddress
|
||||||
|
text, err = sect.Data()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *xcoffFile) goarch() string {
|
||||||
|
switch f.xcoff.TargetMachine {
|
||||||
|
case xcoff.U802TOCMAGIC:
|
||||||
|
return "ppc"
|
||||||
|
case xcoff.U64_TOCMAGIC:
|
||||||
|
return "ppc64"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *xcoffFile) loadAddress() (uint64, error) {
|
||||||
|
return 0, fmt.Errorf("unknown load address")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *xcoffFile) dwarf() (*dwarf.Data, error) {
|
||||||
|
return f.xcoff.DWARF()
|
||||||
|
}
|
||||||
|
|
@ -56,17 +56,18 @@ func testMain(m *testing.M) int {
|
||||||
|
|
||||||
func TestNonGoExecs(t *testing.T) {
|
func TestNonGoExecs(t *testing.T) {
|
||||||
testfiles := []string{
|
testfiles := []string{
|
||||||
"elf/testdata/gcc-386-freebsd-exec",
|
"debug/elf/testdata/gcc-386-freebsd-exec",
|
||||||
"elf/testdata/gcc-amd64-linux-exec",
|
"debug/elf/testdata/gcc-amd64-linux-exec",
|
||||||
"macho/testdata/gcc-386-darwin-exec",
|
"debug/macho/testdata/gcc-386-darwin-exec",
|
||||||
"macho/testdata/gcc-amd64-darwin-exec",
|
"debug/macho/testdata/gcc-amd64-darwin-exec",
|
||||||
// "pe/testdata/gcc-amd64-mingw-exec", // no symbols!
|
// "debug/pe/testdata/gcc-amd64-mingw-exec", // no symbols!
|
||||||
"pe/testdata/gcc-386-mingw-exec",
|
"debug/pe/testdata/gcc-386-mingw-exec",
|
||||||
"plan9obj/testdata/amd64-plan9-exec",
|
"debug/plan9obj/testdata/amd64-plan9-exec",
|
||||||
"plan9obj/testdata/386-plan9-exec",
|
"debug/plan9obj/testdata/386-plan9-exec",
|
||||||
|
"cmd/internal/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec",
|
||||||
}
|
}
|
||||||
for _, f := range testfiles {
|
for _, f := range testfiles {
|
||||||
exepath := filepath.Join(runtime.GOROOT(), "src", "debug", f)
|
exepath := filepath.Join(runtime.GOROOT(), "src", f)
|
||||||
cmd := exec.Command(testnmpath, exepath)
|
cmd := exec.Command(testnmpath, exepath)
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -139,6 +140,20 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("go tool nm: %v\n%s", err, string(out))
|
t.Fatalf("go tool nm: %v\n%s", err, string(out))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relocated := func(code string) bool {
|
||||||
|
if runtime.GOOS == "aix" {
|
||||||
|
// On AIX, .data and .bss addresses are changed by the loader.
|
||||||
|
// Therefore, the values returned by the exec aren't the same
|
||||||
|
// than the ones inside the symbol table.
|
||||||
|
switch code {
|
||||||
|
case "D", "d", "B", "b":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(bytes.NewBuffer(out))
|
scanner := bufio.NewScanner(bytes.NewBuffer(out))
|
||||||
dups := make(map[string]bool)
|
dups := make(map[string]bool)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
|
|
@ -149,7 +164,9 @@ func testGoExec(t *testing.T, iscgo, isexternallinker bool) {
|
||||||
name := f[2]
|
name := f[2]
|
||||||
if addr, found := names[name]; found {
|
if addr, found := names[name]; found {
|
||||||
if want, have := addr, "0x"+f[0]; have != want {
|
if want, have := addr, "0x"+f[0]; have != want {
|
||||||
t.Errorf("want %s address for %s symbol, but have %s", want, name, have)
|
if !relocated(f[1]) {
|
||||||
|
t.Errorf("want %s address for %s symbol, but have %s", want, name, have)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete(names, name)
|
delete(names, name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue