cmd/link/internal/loadpe: fix .xdata unwind info parsing

Unwind info in .xdata was being parsed incorrectly, causing targetOff to
be incorrect and miss finding data in .xdata that it should have found.
This causes a linker issue when using the MinGW MSVCRT compiler.

Contains several fixes based on the exception handling docs: the offset
used to get the number of unwind codes, the calculation of the target
offset based on the dynamic size of the unwind data, and the
UNW_FLAG_CHAININFO flag's value.

Fixes #64200

Change-Id: I6483d921b2bf8a2512a95223bf3c8ce8bc63dc4a
Reviewed-on: https://go-review.googlesource.com/c/go/+/544415
TryBot-Result: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Davis Goodin 2023-11-21 17:12:48 -08:00 committed by Quim Muntal
parent 37971b31df
commit d4430f6913
1 changed files with 5 additions and 4 deletions

View File

@ -16,8 +16,9 @@ import (
const (
UNW_FLAG_EHANDLER = 1 << 3
UNW_FLAG_UHANDLER = 2 << 3
UNW_FLAG_CHAININFO = 3 << 3
unwStaticDataSize = 8
UNW_FLAG_CHAININFO = 4 << 3
unwStaticDataSize = 4 // Bytes of unwind data before the variable length part.
unwCodeSize = 2 // Bytes per unwind code.
)
// processSEH walks all pdata relocations looking for exception handler function symbols.
@ -81,14 +82,14 @@ func findHandlerInXDataAMD64(ldr *loader.Loader, xsym sym.LoaderSym, add int64)
// Nothing to do.
return 0
}
codes := data[3]
codes := data[2]
if codes%2 != 0 {
// There are always an even number of unwind codes, even if the last one is unused.
codes += 1
}
// The exception handler relocation is the first relocation after the unwind codes,
// unless it is chained, but we will handle this case later.
targetOff := add + unwStaticDataSize*(1+int64(codes))
targetOff := add + unwStaticDataSize + unwCodeSize*int64(codes)
xrels := ldr.Relocs(xsym)
xrelsCount := xrels.Count()
idx := sort.Search(xrelsCount, func(i int) bool {