ARM64 static native instrumentation: ADRP page mis-relocated for global loads when relocated data straddles a 4 KB page
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 10/100
Línea de trabajo
Start with the attached repro.zip and run repro.ps1 on an ARM64 machine to see the 0xFF0 page-offset mismatch. The log message names CPEA64::FinalAssignAddressPass, the ARM64 pass where ADRP targets are relocated, so begin there. Done means each ADRP page is computed from its own load target (symbol plus addend), and repro.ps1 reports 0 mismatches when instrumented.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Environment
- Visual Studio 2026 Enterprise 18.10, MSVC 14.51.36231, Windows SDK 10.0.26100.0
- Microsoft.CodeCoverage.Console 18.10.0-preview.26374.2
- Target: native ARM64, Debug (
/Od /RTC1 /GS /guard:cf /MDd), linked with/PROFILE, static native instrumentation - Run on Windows 11 ARM64 (26100)
Summary
After static instrumentation, .rdata contents move by 0x10 bytes. For a global struct whose fields end up on two
different 4 KB pages, the adrp instructions addressing that struct get the page of the struct's last field, while each
ldr keeps its own low-12-bit offset. Loads of fields that stayed on the earlier page therefore read memory exactly 4 KB
too high.
In our product this reads an unrelated qword instead of a function pointer and crashes with
FAST_FAIL_GUARD_ICALL_CHECK_FAILURE (0xC0000409), causes C0000005 while copying a global std::set, and produces
"Failed to load the test assembly or its dependencies" in vstest. The same binaries pass without instrumentation, and the
same sources pass under x64 static and dynamic instrumentation.
Repro (attached repro.zip, toy code only)
repro.ps1 generates 3000 const 32-byte structs, each checked field by field by its own function, builds for ARM64 with
/PROFILE, instruments with Microsoft.CodeCoverage.Console instrument, and runs both binaries on an ARM64 machine
(repro.ps1 -BuildOnly on x64, then repro.ps1 -RunOnly on ARM64, or just repro.ps1 on ARM64):
--- uninstrumented:
checked 3000 globals, 0 mismatches
--- instrumented, inside a coverage session:
const 87 at 00007FF6FCEA7FF0: aaaa0000000005d7 bbbb0000000005d7 cccc0000000005d7 dddd0000000005d7
const 215 at 00007FF6FCEAAFF0: aaaa000000000657 bbbb000000000657 cccc000000000657 dddd000000000657
const 316 at 00007FF6FCEACFF0: aaaa00000000017c bbbb00000000017c cccc00000000017c dddd00000000017c
...
Every failing struct sits at page offset 0xFF0 after instrumentation. The address-of (&c_N, adrp + add) is
mis-relocated the same way: const 87 prints the contents of struct 0x5D7, the object 4 KB above it. Both the field
loads and the address computation are 4 KB too high.
Disassembly (check_87, from the attached repro build)
Original - c_87 at 0x140090FE0, all four fields on page 0x140090000:
adrp x8, 0x140090000 ; ldr x8,[x8,#0xFE0] ; f0
adrp x8, 0x140090000 ; ldr x8,[x8,#0xFE8] ; f1
adrp x8, 0x140090000 ; ldr x8,[x8,#0xFF0] ; f2
adrp x8, 0x140090000 ; ldr x8,[x8,#0xFF8] ; f3
adrp x8, 0x140090000 ; add x1,x8,#0xFE0 ; &c_87
Instrumented - c_87 moved to 0x1401A6FF0 (f0, f1 on page 0x1401A6000; f2, f3 on page 0x1401A7000):
adrp x8, 0x1401A7000 ; ldr x8,[x8,#0xFF0] ; f0 -> 0x1401A7FF0, expected 0x1401A6FF0 (WRONG, +4 KB)
adrp x8, 0x1401A7000 ; ldr x8,[x8,#0xFF8] ; f1 -> 0x1401A7FF8, expected 0x1401A6FF8 (WRONG, +4 KB)
adrp x8, 0x1401A7000 ; ldr x8,[x8] ; f2 -> 0x1401A7000, expected 0x1401A7000 (ok)
adrp x8, 0x1401A7000 ; ldr x8,[x8,#8] ; f3 -> 0x1401A7008, expected 0x1401A7008 (ok)
adrp x8, 0x1401A7000 ; add x1,x8,#0xFF0 ; &c_87 -> 0x1401A7FF0, expected 0x1401A6FF0 (WRONG, +4 KB)
Every adrp that originally pointed at the struct's page gets the same new page (the page of the struct's last field),
while each low-12-bit offset is correctly shifted by +0x10. Accesses whose relocated target stayed on the earlier page
therefore land exactly 4 KB too high.
Expected
Each adrp page is computed from its own load target (symbol + addend), so the relocated code reads the same objects as
the original.
Also observed (possibly related)
- Every ARM64
/GSfunction hasbl __security_push_cookieinside its prolog. The instrumenter prints
"CPEA64::FinalAssignAddressPass: prolog unwind codes mismatch" for each one and inserts a NOP plus a probe into the
prolog. On large binaries this is millions of output lines and dominates the run time. - For CRT varargs functions (e.g.
_snprintf_s) the unwind code forstp x4,x5,[sp,#-0x20]!is rewritten tonop
(dumpbin /unwindinfo: "Nop covers for stack-adjusting load/store").
Full crash dumps and binaries from the original product are available to Microsoft engineers on request.
- Lenguaje dominante
- C#
- Estrellas
- 125
- Forks
- 17
- Merge medio
- 1 h 15 min
- PR fusionados (30 d)
- 2
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de microsoft/codecoverage
-
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
microsoft/codecoverage#253 · 1 reacción ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 65/100
microsoft/codecoverage#252 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 52/100
microsoft/codecoverage#251 ·
-
[BUG] Intermittent Windows 0xC0000005 crashes in MTP test hosts with CodeCoverage on .NET 10Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
microsoft/codecoverage#249 · 1 comentario · 1 reacción ·
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
microsoft/codecoverage#220 · 2 comentarios ·
Todos los issues de microsoft/codecoverage
Issues similares
-
clawsweeper:source-repro impact:ux-release-blocker issue-rating: 🦞 diamond lobster P0
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
openclaw/openclaw-windows-node#1723 · 1 comentario · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
good first issue hacktoberfest help wanted new-language
Dificultad 2/5 Medio día Aptitud para principiantes 78/100
-
[Android] Controls.DeviceTests build fails with xUnit2031 analyzer errorPosiblemente ocupada @HarishwaranVijayakumar la tomó hoy. Abiertopartner/syncfusion s/triaged s/verified
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
dotnet/maui#39376 · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
documentation
Dificultad 1/5 1-3 horas Aptitud para principiantes 62/100
-
bug misleading tooling trivial
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día