[dev.link] cmd/link: support new object file format

Parse new object file format in the linker. At least we can link
a hello-world program.

Add a basic "loader", which handles symbol references in the
object file.
- mapping between local and global indices
- resolve by-name references
  (TODO: the overwrite logic isn't implemented yet)

Currently we still create sym.Symbol rather early, and, after all
the object files are loaded and indexed references are resolved,
add all symbols to sym.Symbols.

The code here is probably not going in the final version. This
is basically only for debugging purposes -- to make sure the
writer and the reader work as expected.

Change-Id: I895aeea68326fabdb7e5aa1371b8cac7211a09dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/196032
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2019-09-17 16:14:37 -04:00
parent d79380026c
commit 6051fd0ad9
7 changed files with 513 additions and 12 deletions

View file

@ -375,15 +375,8 @@ func (ctxt *Link) findLibPath(libname string) string {
}
func (ctxt *Link) loadlib() {
switch ctxt.BuildMode {
case BuildModeCShared, BuildModePlugin:
s := ctxt.Syms.Lookup("runtime.islibrary", 0)
s.Attr |= sym.AttrDuplicateOK
s.AddUint8(1)
case BuildModeCArchive:
s := ctxt.Syms.Lookup("runtime.isarchive", 0)
s.Attr |= sym.AttrDuplicateOK
s.AddUint8(1)
if *flagNewobj {
ctxt.loader = objfile.NewLoader()
}
loadinternal(ctxt, "runtime")
@ -408,6 +401,11 @@ func (ctxt *Link) loadlib() {
}
}
// XXX do it here for now
if *flagNewobj {
ctxt.loadlibfull()
}
for _, lib := range ctxt.Library {
if lib.Shlib != "" {
if ctxt.Debugvlog > 1 {
@ -417,6 +415,19 @@ func (ctxt *Link) loadlib() {
}
}
switch ctxt.BuildMode {
case BuildModeCShared, BuildModePlugin:
s := ctxt.Syms.Lookup("runtime.islibrary", 0)
s.Type = sym.SNOPTRDATA
s.Attr |= sym.AttrDuplicateOK
s.AddUint8(1)
case BuildModeCArchive:
s := ctxt.Syms.Lookup("runtime.isarchive", 0)
s.Type = sym.SNOPTRDATA
s.Attr |= sym.AttrDuplicateOK
s.AddUint8(1)
}
iscgo = ctxt.Syms.ROLookup("x_cgo_init", 0) != nil
// We now have enough information to determine the link mode.
@ -843,7 +854,7 @@ func loadobjfile(ctxt *Link, lib *sym.Library) {
if err != nil {
Exitf("cannot open file %s: %v", lib.File, err)
}
defer f.Close()
//defer f.Close()
defer func() {
if pkg == "main" && !lib.Main {
Exitf("%s: not package main", lib.File)
@ -1773,7 +1784,12 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
default:
log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
}
c := objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, flags)
var c int
if *flagNewobj {
objfile.LoadNew(ctxt.loader, ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, flags)
} else {
c = objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, flags)
}
strictDupMsgCount += c
addImports(ctxt, lib, pn)
return nil
@ -2545,3 +2561,40 @@ func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library
mark[lib] = visited
*order = append(*order, lib)
}
func (ctxt *Link) loadlibfull() {
// Add references of externally defined symbols.
for _, lib := range ctxt.Library {
for _, r := range lib.Readers {
objfile.LoadRefs(ctxt.loader, r.Reader, lib, ctxt.Arch, ctxt.Syms, r.Version)
}
}
// Load full symbol contents, resolve indexed references.
for _, lib := range ctxt.Library {
for _, r := range lib.Readers {
objfile.LoadFull(ctxt.loader, r.Reader, lib, ctxt.Syms, r.Version, ctxt.LibraryByPkg)
}
}
// For now, add all symbols to ctxt.Syms.
for _, s := range ctxt.loader.Syms {
if s != nil && s.Name != "" {
ctxt.Syms.Add(s)
}
}
// Now load cgo directives.
for _, p := range ctxt.cgodata {
loadcgo(ctxt, p[0], p[1], p[2])
}
}
func (ctxt *Link) dumpsyms() {
for _, s := range ctxt.Syms.Allsym {
fmt.Printf("%s %s %p\n", s, s.Type, s)
for i := range s.R {
fmt.Println("\t", s.R[i].Type, s.R[i].Sym)
}
}
}