[go] cmd/objdump: read file/line information for ELF PIE binaries

2 views
Skip to first unread message

Cherry Mui (Gerrit)

unread,
Sep 22, 2022, 7:46:33 PM9/22/22
to goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Gopher Robot, Than McIntosh, Joel Sing, Ian Lance Taylor

Cherry Mui submitted this change.

View Change



5 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:

```
The name of the file: src/cmd/objdump/objdump_test.go
Insertions: 1, Deletions: 1.

@@ -193,7 +193,7 @@
}
}
if pie {
- // In PPC64 PIE binaries we use a "lacal entry point" which is
+ // In PPC64 PIE binaries we use a "local entry point" which is
// function symbol address + 8. Currently we don't symbolize that.
// Expect a different output.
need = append(need, ppcPIENeed...)
```
```
The name of the file: src/cmd/internal/objfile/elf.go
Insertions: 2, Deletions: 3.

@@ -160,15 +160,14 @@
break
}
}
- if addr == 0 {
+ if addr == 0 || eaddr < addr {
return nil
}
size := eaddr - addr
data := make([]byte, size)
for _, prog := range f.elf.Progs {
if prog.Vaddr <= addr && addr+size-1 <= prog.Vaddr+prog.Filesz-1 {
- _, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
- if err != nil {
+ if _, err := prog.ReadAt(data, int64(addr-prog.Vaddr)); err != nil {
return nil
}
return data
```

Approvals: Cherry Mui: Run TryBots Than McIntosh: Looks good to me, approved Joel Sing: Looks good to me, but someone else must approve Gopher Robot: TryBots succeeded
cmd/internal/objfile: read file/line information for ELF PIE binaries

For PIE binaries, the .gopclntab section doesn't have the usual
name, but .data.rel.ro.gopclntab. Try the relro version as well.
If both failed (e.g. for externally linked PIE binaries), try
runtime.pclntab symbol.

This should make cmd/objdump able to print the file/line
information for PIE binaries.

I attempted to do this a few years ago, but that wasn't enough,
because the pclntab itself contains dynamic relocations which are
not applied by the tool. As of Go 1.18 the pclntab is mostly
position independent and does not contain dynamic relocations, so
this should be possible now.

Fixes #17883.
Updates #46639.

Change-Id: I85dc3d50ffcc1a4b187a349479a6a162de1ab2b5
Reviewed-on: https://go-review.googlesource.com/c/go/+/227483
Run-TryBot: Cherry Mui <cher...@google.com>
Reviewed-by: Than McIntosh <th...@google.com>
Reviewed-by: Joel Sing <jo...@sing.id.au>
TryBot-Result: Gopher Robot <go...@golang.org>
---
M src/cmd/internal/objfile/elf.go
M src/cmd/objdump/objdump_test.go
2 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/src/cmd/internal/objfile/elf.go b/src/cmd/internal/objfile/elf.go
index a48a9df..c64c254 100644
--- a/src/cmd/internal/objfile/elf.go
+++ b/src/cmd/internal/objfile/elf.go
@@ -68,16 +68,35 @@
if sect := f.elf.Section(".text"); sect != nil {
textStart = sect.Addr
}
- if sect := f.elf.Section(".gosymtab"); sect != nil {
+
+ sect := f.elf.Section(".gosymtab")
+ if sect == nil {
+ // try .data.rel.ro.gosymtab, for PIE binaries
+ sect = f.elf.Section(".data.rel.ro.gosymtab")
+ }
+ if sect != nil {
if symtab, err = sect.Data(); err != nil {
return 0, nil, nil, err
}
+ } else {
+ // if both sections failed, try the symbol
+ symtab = f.symbolData("runtime.symtab", "runtime.esymtab")
}
- if sect := f.elf.Section(".gopclntab"); sect != nil {
+
+ sect = f.elf.Section(".gopclntab")
+ if sect == nil {
+ // try .data.rel.ro.gopclntab, for PIE binaries
+ sect = f.elf.Section(".data.rel.ro.gopclntab")
+ }
+ if sect != nil {
if pclntab, err = sect.Data(); err != nil {
return 0, nil, nil, err
}
+ } else {
+ // if both sections failed, try the symbol
+ pclntab = f.symbolData("runtime.pclntab", "runtime.epclntab")
}
+
return textStart, symtab, pclntab, nil
}

@@ -124,3 +143,35 @@
func (f *elfFile) dwarf() (*dwarf.Data, error) {
return f.elf.DWARF()
}
+
+func (f *elfFile) symbolData(start, end string) []byte {
+ elfSyms, err := f.elf.Symbols()
+ if err != nil {
+ return nil
+ }
+ var addr, eaddr uint64
+ for _, s := range elfSyms {
+ if s.Name == start {
+ addr = s.Value
+ } else if s.Name == end {
+ eaddr = s.Value
+ }
+ if addr != 0 && eaddr != 0 {
+ break
+ }
+ }
+ if addr == 0 || eaddr < addr {
+ return nil
+ }
+ size := eaddr - addr
+ data := make([]byte, size)
+ for _, prog := range f.elf.Progs {
+ if prog.Vaddr <= addr && addr+size-1 <= prog.Vaddr+prog.Filesz-1 {
+ if _, err := prog.ReadAt(data, int64(addr-prog.Vaddr)); err != nil {
+ return nil
+ }
+ return data
+ }
+ }
+ return nil
+}
diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
index e984ef2..86e904d 100644
--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -6,6 +6,7 @@

import (
"cmd/internal/notsha256"
+ "cmd/internal/sys"
"flag"
"fmt"
"go/build"
@@ -99,6 +100,12 @@
"RET",
}

+var ppcPIENeed = []string{
+ "BR",
+ "CALL",
+ "RET",
+}
+
var ppcGnuNeed = []string{
"mflr",
"lbz",
@@ -178,7 +185,21 @@
case "arm64":
need = append(need, arm64Need...)
case "ppc64", "ppc64le":
- need = append(need, ppcNeed...)
+ var pie bool
+ for _, flag := range flags {
+ if flag == "-buildmode=pie" {
+ pie = true
+ break
+ }
+ }
+ if pie {
+ // In PPC64 PIE binaries we use a "local entry point" which is
+ // function symbol address + 8. Currently we don't symbolize that.
+ // Expect a different output.
+ need = append(need, ppcPIENeed...)
+ } else {
+ need = append(need, ppcNeed...)
+ }
}

if printGnuAsm {
@@ -265,6 +286,14 @@
testDisasm(t, "fmthello.go", false, false, "-ldflags=-linkmode=external")
}

+func TestDisasmPIE(t *testing.T) {
+ if !sys.BuildModeSupported("gc", "pie", runtime.GOOS, runtime.GOARCH) {
+ t.Skipf("skipping on %s/%s, PIE buildmode not supported", runtime.GOOS, runtime.GOARCH)
+ }
+ t.Parallel()
+ testDisasm(t, "fmthello.go", false, false, "-buildmode=pie")
+}
+
func TestDisasmGoobj(t *testing.T) {
mustHaveDisasm(t)


To view, visit change 227483. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I85dc3d50ffcc1a4b187a349479a6a162de1ab2b5
Gerrit-Change-Number: 227483
Gerrit-PatchSet: 7
Gerrit-Owner: Cherry Mui <cher...@google.com>
Gerrit-Reviewer: Cherry Mui <cher...@google.com>
Gerrit-Reviewer: Gopher Robot <go...@golang.org>
Gerrit-Reviewer: Joel Sing <jo...@sing.id.au>
Gerrit-Reviewer: Than McIntosh <th...@google.com>
Gerrit-CC: Ian Lance Taylor <ia...@golang.org>
Gerrit-MessageType: merged
Reply all
Reply to author
Forward
0 new messages