1 | //===-- sanitizer_coverage_win_sections.cpp -------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines delimiters for Sanitizer Coverage's section. It contains |
10 | // Windows specific tricks to coax the linker into giving us the start and stop |
11 | // addresses of a section, as ELF linkers can do, to get the size of certain |
12 | // arrays. According to https://msdn.microsoft.com/en-us/library/7977wcck.aspx |
13 | // sections with the same name before "$" are sorted alphabetically by the |
14 | // string that comes after "$" and merged into one section. We take advantage |
15 | // of this by putting data we want the size of into the middle (M) of a section, |
16 | // by using the letter "M" after "$". We get the start of this data (ie: |
17 | // __start_section_name) by making the start variable come at the start of the |
18 | // section (using the letter A after "$"). We do the same to get the end of the |
19 | // data by using the letter "Z" after "$" to make the end variable come after |
20 | // the data. Note that because of our technique the address of the start |
21 | // variable is actually the address of data that comes before our middle |
22 | // section. We also need to prevent the linker from adding any padding. Each |
23 | // technique we use for this is explained in the comments below. |
24 | //===----------------------------------------------------------------------===// |
25 | |
26 | #include "sanitizer_platform.h" |
27 | #if SANITIZER_WINDOWS |
28 | #include <stdint.h> |
29 | |
30 | extern "C" { |
31 | // Use uint64_t so the linker won't need to add any padding if it tries to word |
32 | // align the start of the 8-bit counters array. The array will always start 8 |
33 | // bytes after __start_sancov_cntrs. |
34 | #pragma section(".SCOV$CA", read, write) |
35 | __declspec(allocate(".SCOV$CA" )) uint64_t __start___sancov_cntrs = 0; |
36 | |
37 | // Even though we said not to align __stop__sancov_cntrs (using the "align" |
38 | // declspec), MSVC's linker may try to align the section, .SCOV$CZ, containing |
39 | // it. This can cause a mismatch between the number of PCs and counters since |
40 | // each PCTable element is 8 bytes (unlike counters which are 1 byte) so no |
41 | // padding would be added to align .SCOVP$Z, However, if .SCOV$CZ section is 1 |
42 | // byte, the linker won't try to align it on an 8-byte boundary, so use a |
43 | // uint8_t for __stop_sancov_cntrs. |
44 | #pragma section(".SCOV$CZ", read, write) |
45 | __declspec(allocate(".SCOV$CZ" )) __declspec(align(1)) uint8_t |
46 | __stop___sancov_cntrs = 0; |
47 | |
48 | #pragma section(".SCOV$GA", read, write) |
49 | __declspec(allocate(".SCOV$GA" )) uint64_t __start___sancov_guards = 0; |
50 | #pragma section(".SCOV$GZ", read, write) |
51 | __declspec(allocate(".SCOV$GZ" )) __declspec(align(1)) uint8_t |
52 | __stop___sancov_guards = 0; |
53 | |
54 | // The guard array and counter array should both be merged into the .data |
55 | // section to reduce the number of PE sections. However, because PCTable is |
56 | // constant it should be merged with the .rdata section. |
57 | #pragma comment(linker, "/MERGE:.SCOV=.data") |
58 | |
59 | #pragma section(".SCOVP$A", read) |
60 | __declspec(allocate(".SCOVP$A" )) uint64_t __start___sancov_pcs = 0; |
61 | #pragma section(".SCOVP$Z", read) |
62 | __declspec(allocate(".SCOVP$Z" )) __declspec(align(1)) uint8_t |
63 | __stop___sancov_pcs = 0; |
64 | |
65 | #pragma comment(linker, "/MERGE:.SCOVP=.rdata") |
66 | } |
67 | #endif // SANITIZER_WINDOWS |
68 | |