Skip to content

Commit

Permalink
cmd/link: allow enabling DWARF with -s
Browse files Browse the repository at this point in the history
The -s flag is to documented to disable symbol table, not DWARF
(which is the -w flag). However, due to a bug (#15166), -s was
made to also disable DWARF. That bug can be fixed without
disabling DWARF. So do that, and make it possible to enable DWARF
with -s.

Since -s has been disabling DWARF for quite some time, and users
who use -s may want to suppress all symbol information, as DWARF
also contains symbol information, we keep the current behavior,
having -s continue to disable DWARF by default. But we allow
enabling DWARF by specifying -w=0 (or false).

In summary, this is the behavior now:
-s       no symbol table, no DWARF
-w       has symbol table, no DWARF
-s -w    no symbol table, no DWARF (same as -s)
-s -w=0	 no symbol table, has DWARF

Change-Id: I1883f0aa3618abccfd735d104d983f7f531813d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/492984
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Than McIntosh <[email protected]>
Run-TryBot: Cherry Mui <[email protected]>
  • Loading branch information
cherrymui committed Jul 21, 2023
1 parent f29c4fa commit 15eea6a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/cmd/link/internal/ld/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ func (mode *BuildMode) Set(s string) error {
return nil
}

func (mode *BuildMode) String() string {
switch *mode {
func (mode BuildMode) String() string {
switch mode {
case BuildModeUnset:
return "" // avoid showing a default in usage message
case BuildModeExe:
Expand All @@ -75,7 +75,7 @@ func (mode *BuildMode) String() string {
case BuildModePlugin:
return "plugin"
}
return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
return fmt.Sprintf("BuildMode(%d)", uint8(mode))
}

// LinkMode indicates whether an external linker is used for the final link.
Expand Down
3 changes: 0 additions & 3 deletions src/cmd/link/internal/ld/dwarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -1633,9 +1633,6 @@ func dwarfEnabled(ctxt *Link) bool {
if *FlagW { // disable dwarf
return false
}
if *FlagS && ctxt.HeadType != objabi.Hdarwin {
return false
}
if ctxt.HeadType == objabi.Hplan9 || ctxt.HeadType == objabi.Hjs || ctxt.HeadType == objabi.Hwasip1 {
return false
}
Expand Down
2 changes: 2 additions & 0 deletions src/cmd/link/internal/ld/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,8 @@ func (ctxt *Link) doelf() {
if !*FlagS {
shstrtabAddstring(".symtab")
shstrtabAddstring(".strtab")
}
if !*FlagW {
dwarfaddshstrings(ctxt, shstrtabAddstring)
}

Expand Down
59 changes: 58 additions & 1 deletion src/cmd/link/internal/ld/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"os"
"runtime"
"runtime/pprof"
"strconv"
"strings"
)

Expand All @@ -56,6 +57,7 @@ func init() {
flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
flag.Var(&flagExtld, "extld", "use `linker` when linking in external mode")
flag.Var(&flagExtldflags, "extldflags", "pass `flags` to external linker")
flag.Var(&flagW, "w", "disable DWARF generation")
}

// Flags used by the linker. The exported flags are used by the architecture-specific packages.
Expand Down Expand Up @@ -90,7 +92,6 @@ var (
flagH = flag.Bool("h", false, "halt on error")
flagN = flag.Bool("n", false, "dump symbol table")
FlagS = flag.Bool("s", false, "disable symbol table")
FlagW = flag.Bool("w", false, "disable DWARF generation")
flag8 bool // use 64-bit addresses in symbol table
flagInterpreter = flag.String("I", "", "use `linker` as ELF dynamic linker")
FlagDebugTramp = flag.Int("debugtramp", 0, "debug trampolines")
Expand All @@ -106,8 +107,48 @@ var (
memprofilerate = flag.Int64("memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
benchmarkFlag = flag.String("benchmark", "", "set to 'mem' or 'cpu' to enable phase benchmarking")
benchmarkFileFlag = flag.String("benchmarkprofile", "", "emit phase profiles to `base`_phase.{cpu,mem}prof")

flagW ternaryFlag
FlagW = new(bool) // the -w flag, computed in main from flagW
)

// ternaryFlag is like a boolean flag, but has a default value that is
// neither true nor false, allowing it to be set from context (e.g. from another
// flag).
// *ternaryFlag implements flag.Value.
type ternaryFlag int

const (
ternaryFlagUnset ternaryFlag = iota
ternaryFlagFalse
ternaryFlagTrue
)

func (t *ternaryFlag) Set(s string) error {
v, err := strconv.ParseBool(s)
if err != nil {
return err
}
if v {
*t = ternaryFlagTrue
} else {
*t = ternaryFlagFalse
}
return nil
}

func (t *ternaryFlag) String() string {
switch *t {
case ternaryFlagFalse:
return "false"
case ternaryFlagTrue:
return "true"
}
return "unset"
}

func (t *ternaryFlag) IsBoolFlag() bool { return true } // parse like a boolean flag

// Main is the main entry point for the linker code.
func Main(arch *sys.Arch, theArch Arch) {
log.SetPrefix("link: ")
Expand Down Expand Up @@ -197,6 +238,15 @@ func Main(arch *sys.Arch, theArch Arch) {

checkStrictDups = *FlagStrictDups

switch flagW {
case ternaryFlagFalse:
*FlagW = false
case ternaryFlagTrue:
*FlagW = true
case ternaryFlagUnset:
*FlagW = *FlagS // -s implies -w if not explicitly set
}

if !buildcfg.Experiment.RegabiWrappers {
abiInternalVer = 0
}
Expand Down Expand Up @@ -252,6 +302,13 @@ func Main(arch *sys.Arch, theArch Arch) {
}

if ctxt.Debugvlog != 0 {
onOff := func(b bool) string {
if b {
return "on"
}
return "off"
}
ctxt.Logf("build mode: %s, symbol table: %s, DWARF: %s\n", ctxt.BuildMode, onOff(!*FlagS), onOff(dwarfEnabled(ctxt)))
ctxt.Logf("HEADER = -H%d -T0x%x -R0x%x\n", ctxt.HeadType, uint64(*FlagTextAddr), uint32(*FlagRound))
}

Expand Down

0 comments on commit 15eea6a

Please sign in to comment.