Skip to content

Commit b171b28

Browse files
Clément Chigotianlancetaylor
Clément Chigot
authored andcommitted
cmd/link: add new loading package for XCOFF files
This commit adds the new package cmd/link/internal/loadxcoff. It also adds a new symbol kind in cmd/link/internal/sym package, which aims to represent TOC entries for XCOFF files. cmd/dist is updated to add this new package and cmd/internal/xcoff during the bootstrap. Updates: #25893 Change-Id: I42b6578cf0ba4cc28ad4aa98122a91ab1d1bbf6e Reviewed-on: https://go-review.googlesource.com/c/138728 Run-TryBot: Tobias Klauser <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent daaf361 commit b171b28

File tree

4 files changed

+229
-2
lines changed

4 files changed

+229
-2
lines changed

src/cmd/dist/buildtool.go

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ var bootstrapDirs = []string{
7474
"cmd/link/internal/loadelf",
7575
"cmd/link/internal/loadmacho",
7676
"cmd/link/internal/loadpe",
77+
"cmd/link/internal/loadxcoff",
7778
"cmd/link/internal/mips",
7879
"cmd/link/internal/mips64",
7980
"cmd/link/internal/objfile",
+225
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package loadxcoff implements a XCOFF file reader.
6+
package loadxcoff
7+
8+
import (
9+
"cmd/internal/bio"
10+
"cmd/internal/objabi"
11+
"cmd/internal/sys"
12+
"cmd/internal/xcoff"
13+
"cmd/link/internal/sym"
14+
"errors"
15+
"fmt"
16+
)
17+
18+
// ldSection is an XCOFF section with its symbols.
19+
type ldSection struct {
20+
xcoff.Section
21+
sym *sym.Symbol
22+
}
23+
24+
// TODO(brainman): maybe just add ReadAt method to bio.Reader instead of creating xcoffBiobuf
25+
26+
// xcoffBiobuf makes bio.Reader look like io.ReaderAt.
27+
type xcoffBiobuf bio.Reader
28+
29+
func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
30+
ret := ((*bio.Reader)(f)).Seek(off, 0)
31+
if ret < 0 {
32+
return 0, errors.New("fail to seek")
33+
}
34+
n, err := f.Read(p)
35+
if err != nil {
36+
return 0, err
37+
}
38+
return n, nil
39+
}
40+
41+
// Load loads the Xcoff file pn from f.
42+
// Symbols are written into syms, and a slice of the text symbols is returned.
43+
func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
44+
errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
45+
return nil, fmt.Errorf("loadxcoff: %v: %v", pn, fmt.Sprintf(str, args...))
46+
}
47+
localSymVersion := syms.IncVersion()
48+
49+
var ldSections []*ldSection
50+
51+
f, err := xcoff.NewFile((*xcoffBiobuf)(input))
52+
if err != nil {
53+
return nil, err
54+
}
55+
defer f.Close()
56+
57+
for _, sect := range f.Sections {
58+
//only text, data and bss section
59+
if sect.Type < xcoff.STYP_TEXT || sect.Type > xcoff.STYP_BSS {
60+
continue
61+
}
62+
lds := new(ldSection)
63+
lds.Section = *sect
64+
name := fmt.Sprintf("%s(%s)", pkg, lds.Name)
65+
s := syms.Lookup(name, localSymVersion)
66+
67+
switch lds.Type {
68+
default:
69+
return errorf("unrecognized section type 0x%x", lds.Type)
70+
case xcoff.STYP_TEXT:
71+
s.Type = sym.STEXT
72+
case xcoff.STYP_DATA:
73+
s.Type = sym.SNOPTRDATA
74+
case xcoff.STYP_BSS:
75+
s.Type = sym.SNOPTRBSS
76+
}
77+
78+
s.Size = int64(lds.Size)
79+
if s.Type != sym.SNOPTRBSS {
80+
data, err := lds.Section.Data()
81+
if err != nil {
82+
return nil, err
83+
}
84+
s.P = data
85+
}
86+
87+
lds.sym = s
88+
ldSections = append(ldSections, lds)
89+
}
90+
91+
// sx = symbol from file
92+
// s = symbol for syms
93+
for _, sx := range f.Symbols {
94+
// get symbol type
95+
stype, errmsg := getSymbolType(f, sx)
96+
if errmsg != "" {
97+
return errorf("error reading symbol %s: %s", sx.Name, errmsg)
98+
}
99+
if stype == sym.Sxxx {
100+
continue
101+
}
102+
103+
s := syms.Lookup(sx.Name, 0)
104+
105+
// Text symbol
106+
if s.Type == sym.STEXT {
107+
if s.Attr.OnList() {
108+
return errorf("symbol %s listed multiple times", s.Name)
109+
}
110+
s.Attr |= sym.AttrOnList
111+
textp = append(textp, s)
112+
}
113+
}
114+
115+
// Read relocations
116+
for _, sect := range ldSections {
117+
// TODO(aix): Dwarf section relocation if needed
118+
if sect.Type != xcoff.STYP_TEXT && sect.Type != xcoff.STYP_DATA {
119+
continue
120+
}
121+
rs := make([]sym.Reloc, sect.Nreloc)
122+
for i, rx := range sect.Relocs {
123+
r := &rs[i]
124+
125+
r.Sym = syms.Lookup(rx.Symbol.Name, 0)
126+
if uint64(int32(rx.VirtualAddress)) != rx.VirtualAddress {
127+
return errorf("virtual address of a relocation is too big: 0x%x", rx.VirtualAddress)
128+
}
129+
r.Off = int32(rx.VirtualAddress)
130+
switch rx.Type {
131+
default:
132+
return errorf("section %s: unknown relocation of type 0x%x", sect.Name, rx.Type)
133+
case xcoff.R_POS:
134+
// Reloc the address of r.Sym
135+
// Length should be 64
136+
if rx.Length != 64 {
137+
return errorf("section %s: relocation R_POS has length different from 64: %d", sect.Name, rx.Length)
138+
}
139+
r.Siz = 8
140+
r.Type = objabi.R_CONST
141+
r.Add = int64(rx.Symbol.Value)
142+
143+
case xcoff.R_RBR:
144+
r.Siz = 4
145+
r.Type = objabi.R_CALLPOWER
146+
r.Add = 0 //
147+
148+
}
149+
}
150+
s := sect.sym
151+
s.R = rs
152+
s.R = s.R[:sect.Nreloc]
153+
}
154+
return textp, nil
155+
156+
}
157+
158+
// Convert symbol xcoff type to sym.SymKind
159+
// Returns nil if this shouldn't be added into syms (like .file or .dw symbols )
160+
func getSymbolType(f *xcoff.File, s *xcoff.Symbol) (stype sym.SymKind, err string) {
161+
// .file symbol
162+
if s.SectionNumber == -2 {
163+
if s.StorageClass == xcoff.C_FILE {
164+
return sym.Sxxx, ""
165+
}
166+
return sym.Sxxx, "unrecognised StorageClass for sectionNumber = -2"
167+
}
168+
169+
// extern symbols
170+
// TODO(aix)
171+
if s.SectionNumber == 0 {
172+
return sym.Sxxx, ""
173+
}
174+
175+
sectType := f.Sections[s.SectionNumber-1].SectionHeader.Type
176+
switch sectType {
177+
default:
178+
return sym.Sxxx, fmt.Sprintf("getSymbolType for Section type 0x%x not implemented", sectType)
179+
case xcoff.STYP_DWARF, xcoff.STYP_DEBUG:
180+
return sym.Sxxx, ""
181+
case xcoff.STYP_DATA, xcoff.STYP_BSS, xcoff.STYP_TEXT:
182+
}
183+
184+
switch s.StorageClass {
185+
default:
186+
return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x not implemented", s.StorageClass)
187+
case xcoff.C_HIDEXT, xcoff.C_EXT, xcoff.C_WEAKEXT:
188+
switch s.AuxCSect.StorageMappingClass {
189+
default:
190+
return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x and Storage Map 0x%x not implemented", s.StorageClass, s.AuxCSect.StorageMappingClass)
191+
192+
// Program Code
193+
case xcoff.XMC_PR:
194+
if sectType == xcoff.STYP_TEXT {
195+
return sym.STEXT, ""
196+
}
197+
return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_PR", sectType, s.StorageClass)
198+
199+
// Read/Write Data
200+
case xcoff.XMC_RW:
201+
if sectType == xcoff.STYP_DATA {
202+
return sym.SDATA, ""
203+
}
204+
if sectType == xcoff.STYP_BSS {
205+
return sym.SBSS, ""
206+
}
207+
return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_RW", sectType, s.StorageClass)
208+
209+
// Function descriptor
210+
case xcoff.XMC_DS:
211+
if sectType == xcoff.STYP_DATA {
212+
return sym.SDATA, ""
213+
}
214+
return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
215+
216+
// TOC anchor and TOC entry
217+
case xcoff.XMC_TC0, xcoff.XMC_TE:
218+
if sectType == xcoff.STYP_DATA {
219+
return sym.SXCOFFTOC, ""
220+
}
221+
return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
222+
223+
}
224+
}
225+
}

src/cmd/link/internal/sym/symkind.go

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ const (
9292
SBSS
9393
SNOPTRBSS
9494
STLSBSS
95+
SXCOFFTOC
9596
SXREF
9697
SMACHOSYMSTR
9798
SMACHOSYMTAB

src/cmd/link/internal/sym/symkind_string.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)