]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link/internal/loadpe: fix .xdata unwind info parsing
authorDavis Goodin <dagood@microsoft.com>
Wed, 22 Nov 2023 01:12:48 +0000 (17:12 -0800)
committerQuim Muntal <quimmuntal@gmail.com>
Wed, 22 Nov 2023 16:20:28 +0000 (16:20 +0000)
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>
src/cmd/link/internal/loadpe/seh.go

index 0e2cda21ddc551eb3210642e77d5ff25b18aace4..545958f1d60beedb2492a36e92879d9e72536656 100644 (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 {