Commit 78a37347 authored by Jeremy Faller's avatar Jeremy Faller

cmd/link: add notion of multiple compilation units per package

As we move the debug_line generation into the compiler, we need to
upgrade the notion of compilationUnit to not just be on a per package
basis.  That won't be the case as it will be impossible for all
compilationUnits to have the same set of files names used to build the
debug_lines table. (For example, assembled files in a package don't know
about any files but themselves, so the debug_lines table could only
reference themseves. As such, we need to break the 1:1 relationship
between compUnit and package.)

Change-Id: I2e517bb6c01de0115bbf777af828a2fe59c09ce8
Reviewed-on: https://go-review.googlesource.com/c/go/+/189618
Run-TryBot: Jeremy Faller <jeremy@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarAustin Clements <austin@google.com>
Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
parent d979ac33
...@@ -402,7 +402,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) { ...@@ -402,7 +402,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
case objabi.R_ADDRCUOFF: case objabi.R_ADDRCUOFF:
// debug_range and debug_loc elements use this relocation type to get an // debug_range and debug_loc elements use this relocation type to get an
// offset from the start of the compile unit. // offset from the start of the compile unit.
o = Symaddr(r.Sym) + r.Add - Symaddr(r.Sym.Lib.Textp[0]) o = Symaddr(r.Sym) + r.Add - Symaddr(r.Sym.Unit.Lib.Textp[0])
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case objabi.R_GOTPCREL: case objabi.R_GOTPCREL:
...@@ -1782,7 +1782,8 @@ func (ctxt *Link) dodata() { ...@@ -1782,7 +1782,8 @@ func (ctxt *Link) dodata() {
case sym.SDWARFLOC: case sym.SDWARFLOC:
sect = addsection(ctxt.Arch, &Segdwarf, ".debug_loc", 04) sect = addsection(ctxt.Arch, &Segdwarf, ".debug_loc", 04)
default: default:
Errorf(dwarfp[i], "unknown DWARF section %v", curType) // Error is unrecoverable, so panic.
panic(fmt.Sprintf("unknown DWARF section %v", curType))
} }
sect.Align = 1 sect.Align = 1
......
...@@ -126,8 +126,9 @@ func deadcode(ctxt *Link) { ...@@ -126,8 +126,9 @@ func deadcode(ctxt *Link) {
textp := make([]*sym.Symbol, 0, len(ctxt.Textp)) textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
for _, s := range ctxt.Textp { for _, s := range ctxt.Textp {
if s.Attr.Reachable() { if s.Attr.Reachable() {
if s.Lib != nil { if s.Unit != nil {
s.Lib.Textp = append(s.Lib.Textp, s) s.Unit.Lib.Textp = append(s.Unit.Lib.Textp, s)
s.Unit.Textp = append(s.Unit.Textp, s)
} }
textp = append(textp, s) textp = append(textp, s)
} }
......
This diff is collapsed.
...@@ -1624,6 +1624,9 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, ...@@ -1624,6 +1624,9 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
c4 := bgetc(f) c4 := bgetc(f)
f.MustSeek(start, 0) f.MustSeek(start, 0)
unit := &sym.CompilationUnit{Lib: lib}
lib.Units = append(lib.Units, unit)
magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
if magic == 0x7f454c46 { // \x7F E L F if magic == 0x7f454c46 { // \x7F E L F
ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
...@@ -1770,7 +1773,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, ...@@ -1770,7 +1773,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
default: default:
log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups) log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
} }
c := objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, eof-f.Offset(), pn, flags) c := objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, unit, eof-f.Offset(), pn, flags)
strictDupMsgCount += c strictDupMsgCount += c
addImports(ctxt, lib, pn) addImports(ctxt, lib, pn)
return nil return nil
......
...@@ -92,8 +92,8 @@ type Link struct { ...@@ -92,8 +92,8 @@ type Link struct {
// Used to implement field tracking. // Used to implement field tracking.
Reachparent map[*sym.Symbol]*sym.Symbol Reachparent map[*sym.Symbol]*sym.Symbol
compUnits []*compilationUnit // DWARF compilation units compUnits []*sym.CompilationUnit // DWARF compilation units
compUnitByPackage map[*sym.Library]*compilationUnit runtimeCU *sym.CompilationUnit // One of the runtime CUs, the last one seen.
relocbuf []byte // temporary buffer for applying relocations relocbuf []byte // temporary buffer for applying relocations
} }
......
...@@ -39,6 +39,7 @@ type objReader struct { ...@@ -39,6 +39,7 @@ type objReader struct {
arch *sys.Arch arch *sys.Arch
syms *sym.Symbols syms *sym.Symbols
lib *sym.Library lib *sym.Library
unit *sym.CompilationUnit
pn string pn string
dupSym *sym.Symbol dupSym *sym.Symbol
localSymVersion int localSymVersion int
...@@ -81,7 +82,7 @@ const ( ...@@ -81,7 +82,7 @@ const (
// Load loads an object file f into library lib. // Load loads an object file f into library lib.
// The symbols loaded are added to syms. // The symbols loaded are added to syms.
func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, length int64, pn string, flags int) int { func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) int {
start := f.Offset() start := f.Offset()
roObject := f.SliceRO(uint64(length)) roObject := f.SliceRO(uint64(length))
if roObject != nil { if roObject != nil {
...@@ -90,6 +91,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, le ...@@ -90,6 +91,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, le
r := &objReader{ r := &objReader{
rd: f, rd: f,
lib: lib, lib: lib,
unit: unit,
arch: arch, arch: arch,
syms: syms, syms: syms,
pn: pn, pn: pn,
...@@ -254,7 +256,7 @@ func (r *objReader) readSym() { ...@@ -254,7 +256,7 @@ func (r *objReader) readSym() {
overwrite: overwrite:
s.File = r.pkgpref[:len(r.pkgpref)-1] s.File = r.pkgpref[:len(r.pkgpref)-1]
s.Lib = r.lib s.Unit = r.unit
if dupok { if dupok {
s.Attr |= sym.AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
} }
...@@ -405,7 +407,7 @@ overwrite: ...@@ -405,7 +407,7 @@ overwrite:
reason = fmt.Sprintf("new length %d != old length %d", reason = fmt.Sprintf("new length %d != old length %d",
len(data), len(dup.P)) len(data), len(dup.P))
} }
fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Lib, reason) fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Unit.Lib, reason)
// For the moment, whitelist DWARF subprogram DIEs for // For the moment, whitelist DWARF subprogram DIEs for
// auto-generated wrapper functions. What seems to happen // auto-generated wrapper functions. What seems to happen
......
// Copyright 2019 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 sym
import "cmd/internal/dwarf"
// CompilationUnit is an abstraction used by DWARF to represent a chunk of
// debug-related data. We create a CompilationUnit per Object file in a
// library (so, one for all the Go code, one for each assembly file, etc.).
type CompilationUnit struct {
Pkg string // The package name, eg ("fmt", or "runtime")
Lib *Library // Our library
Consts *Symbol // Package constants DIEs
PCs []dwarf.Range // PC ranges, relative to Textp[0]
DWInfo *dwarf.DWDie // CU root DIE
FuncDIEs []*Symbol // Function DIE subtrees
AbsFnDIEs []*Symbol // Abstract function DIE subtrees
RangeSyms []*Symbol // Symbols for debug_range
Textp []*Symbol // Text symbols in this CU
}
...@@ -17,6 +17,7 @@ type Library struct { ...@@ -17,6 +17,7 @@ type Library struct {
DupTextSyms []*Symbol // dupok text symbols defined in this library DupTextSyms []*Symbol // dupok text symbols defined in this library
Main bool Main bool
Safe bool Safe bool
Units []*CompilationUnit
} }
func (l Library) String() string { func (l Library) String() string {
......
...@@ -32,7 +32,7 @@ type Symbol struct { ...@@ -32,7 +32,7 @@ type Symbol struct {
auxinfo *AuxSymbol auxinfo *AuxSymbol
Sect *Section Sect *Section
FuncInfo *FuncInfo FuncInfo *FuncInfo
Lib *Library // Package defining this symbol Unit *CompilationUnit
// P contains the raw symbol data. // P contains the raw symbol data.
P []byte P []byte
R []Reloc R []Reloc
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment