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.