| commit | fdf0ed6f7420cefec0131eab86ba54755245fee2 | [log] [tgz] |
|---|---|---|
| author | Nicolas Hillegeer <aktau@google.com> | Wed Oct 09 07:44:18 2024 -0700 |
| committer | Gopher Robot <gobot@golang.org> | Wed Oct 09 16:02:30 2024 +0000 |
| tree | ade34da338c958f75b10e955fb23e78e686d65cd | |
| parent | 60d51dfed16480aef9c21690a1e1767c19dd9393 [diff] |
internal/gocore: support PIE ELF binaries
Go binaries built with `-buildmode=pie` are loaded at random addresses
(ASLR) in memory by Linux.
Before this change, the mappings read from the `NT_NOTE` section of the
ELF binary matches the exe mappings:
# From NT_NOTE:
0x400000-0x491000 ---- 593920 /tmp/TestVersionsgoroot#003207751013/001/test.exe+0x0
0x491000-0x54b000 ---- 761856 /tmp/TestVersionsgoroot#003207751013/001/test.exe+0x91000
0x54b000-0x556000 ---- 45056 /tmp/TestVersionsgoroot#003207751013/001/test.exe+0x14b000
# From executable:
0x400000-0x491000 r-xp 593920 /tmp/TestVersionsgoroot#003207751013/001/test.exe+0x0
0x491000-0x54b000 r--p 761856 /tmp/TestVersionsgoroot#003207751013/001/test.exe+0x91000
0x54b000-0x555000 rw-p 40960 /tmp/TestVersionsgoroot#003207751013/001/test.exe+0x14b000
0x555000-0x579000 rw-p 147456 anon+0x-440
# From core
0xc000000000-0xc000400000 rw-p 4194304 /tmp/TestVersionsgoroot#003207751013/001/core+0x32000
0x7f8b17c00000-0x7f8b19c00000 rw-p 33554432 /tmp/TestVersionsgoroot#003207751013/001/core+0x432000
0x7f8b29d80000-0x7f8b29d81000 rw-p 4096 /tmp/TestVersionsgoroot#003207751013/001/core+0x2432000
0x7f8b49d80000-0x7f8b49d81000 rw-p 4096 /tmp/TestVersionsgoroot#003207751013/001/core+0x2433000
0x7f8b5bc30000-0x7f8b5bc31000 rw-p 4096 /tmp/TestVersionsgoroot#003207751013/001/core+0x2434000
0x7f8b5e006000-0x7f8b5e007000 rw-p 4096 /tmp/TestVersionsgoroot#003207751013/001/core+0x2435000
0x7f8b5e466000-0x7f8b5e4c6000 rw-p 393216 /tmp/TestVersionsgoroot#003207751013/001/core+0x2436000
0x7f8b5e4c6000-0x7f8b5e5c6000 rw-p 1048576 /tmp/TestVersionsgoroot#003207751013/001/core+0x2496000
0x7f8b5e5c6000-0x7f8b5e5d7000 rw-p 69632 /tmp/TestVersionsgoroot#003207751013/001/core+0x2596000
0x7f8b5e657000-0x7f8b5e658000 rw-p 4096 /tmp/TestVersionsgoroot#003207751013/001/core+0x25a7000
0x7f8b5e6d7000-0x7f8b5e737000 rw-p 393216 /tmp/TestVersionsgoroot#003207751013/001/core+0x25a8000
0x7f8b5e737000-0x7f8b5e73b000 r--p 16384 /tmp/TestVersionsgoroot#003207751013/001/core+0x2608000
0x7f8b5e73b000-0x7f8b5e73d000 r-xp 8192 /tmp/TestVersionsgoroot#003207751013/001/core+0x260c000
0x7ffd88d3c000-0x7ffd88d5e000 rw-p 139264 /tmp/TestVersionsgoroot#003207751013/001/core+0x260e000
And things worked fine. But, with PIE binaries, we see the following raw
addresses when loading (e.g.):
# From NT_NOTE:
0x563f53d35000-0x563f53dc7000 ---- 598016 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0x0
0x563f53dc7000-0x563f53e10000 ---- 299008 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0x92000
0x563f53e10000-0x563f53ea3000 ---- 602112 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0xdb000
0x563f53ea3000-0x563f53eaf000 ---- 49152 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0x16e000
0x7ff5d0deb000-0x7ff5d0dec000 ---- 4096 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2+0x0
0x7ff5d0dec000-0x7ff5d0e11000 ---- 151552 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2+0x1000
0x7ff5d0e11000-0x7ff5d0e1b000 ---- 40960 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2+0x26000
0x7ff5d0e1b000-0x7ff5d0e1f000 ---- 16384 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2+0x30000
# From executable:
0x400000-0x492000 r-xp 598016 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0x0
0x492000-0x4db000 r--p 299008 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0x92000
0x4db000-0x56f000 rw-p 606208 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0xdb000
0x56f000-0x579000 rw-p 40960 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/test.exe+0x16f000
0x579000-0x59d000 rw-p 147456 anon+0x-460
# From core
0xc000000000-0xc000400000 rw-p 4194304 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x3000
0x563f53d35000-0x563f53d36000 r-xp 4096 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x403000
0x563f53d36000-0x563f53dc7000 r-xp 593920 anon+0x0
0x563f53dc7000-0x563f53e10000 r--p 299008 anon+0x0
0x563f53e10000-0x563f53ea3000 r--p 602112 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x404000
0x563f53ea3000-0x563f53eaf000 rw-p 49152 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x497000
0x563f53eaf000-0x563f53ed2000 rw-p 143360 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x4a3000
...
0x7ff5d0deb000-0x7ff5d0dec000 r--p 4096 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x26a4000
0x7ff5d0dec000-0x7ff5d0e11000 r-xp 151552 anon+0x0
0x7ff5d0e11000-0x7ff5d0e1b000 r--p 40960 anon+0x0
0x7ff5d0e1b000-0x7ff5d0e1f000 rw-p 16384 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x26a5000
0x7fff34a26000-0x7fff34a48000 rw-p 139264 /tmp/TestVersionsgoroot-buildmode=pie3327190927/001/core+0x26a9000
This caused two issues:
1. The mappings from the executable and the core were not unified
properly done in `addProgMappings -> splicedMemory.Add` due to the
address ranges being different. Both existeded in the
`splicedMemory` set. Normally, the core mappings would override the
executable mappings when they overlap. To correct for this, add the
load offset (`staticBase`) to the executable addresses.
2. DWARF data (contained in the executable) references the base
addresses (for example, `allgs` is at 0x4003c4). Due to #1, a lookup
*would not crash*, but it would read the location from the
executable. In a PIE binary, such a lookup into the `.data` section
would be a relocation, and be present in the binary as all zeroes
(0x0). If #1 were fixed to offset by `staticBase` without fixing #2
would result in a read from unmapped memory.
Inspiration was taken from the Delve commit that added PIE support for
multiple platforms/architectures in
https://github.com/go-delve/delve/commit/025d47c6e96e8ab5a2d2c142ae554e760cddabf8.
Also add tests that this works. I verified that if the changes from
non-test files are omitted, the test fails.
Change-Id: Ifa08f71e7ed22320b78bc6015554e997b8ae521d
Reviewed-on: https://go-review.googlesource.com/c/debug/+/618977
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicolas Hillegeer <aktau@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This repository holds utilities and libraries for debugging Go programs.
WARNING! Please expect breaking changes and unstable APIs. Most of them are currently are at an early, experimental stage.
This repository uses Gerrit for code changes. To learn how to submit changes to this repository, see https://golang.org/doc/contribute.html.
The main issue tracker for the debug repository is located at https://github.com/golang/go/issues. Prefix your issue with “x/debug:” in the subject line, so it is easy to find.