Nico Weber | 19a88c1 | 2019-07-31 18:51:27 +0000 | [diff] [blame] | 1 | //===-- sanitizer_coverage_win_sections.cpp -------------------------------===// |
Marcos Pividori | e329a83 | 2017-02-02 23:02:15 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 0748fbc | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Marcos Pividori | e329a83 | 2017-02-02 23:02:15 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
Matt Morehouse | dda104c | 2018-08-30 15:54:44 +0000 | [diff] [blame] | 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. |
Marcos Pividori | e329a83 | 2017-02-02 23:02:15 +0000 | [diff] [blame] | 24 | //===----------------------------------------------------------------------===// |
| 25 | |
| 26 | #include "sanitizer_platform.h" |
| 27 | #if SANITIZER_WINDOWS |
| 28 | #include <stdint.h> |
Matt Morehouse | dda104c | 2018-08-30 15:54:44 +0000 | [diff] [blame] | 29 | |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 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. |
Vitaly Buka | 124b2ba | 2019-09-11 23:19:48 +0000 | [diff] [blame] | 34 | #pragma section(".SCOV$CA", read, write) |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 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. |
Vitaly Buka | 124b2ba | 2019-09-11 23:19:48 +0000 | [diff] [blame] | 44 | #pragma section(".SCOV$CZ", read, write) |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 45 | __declspec(allocate(".SCOV$CZ")) __declspec(align(1)) uint8_t |
Matt Morehouse | dda104c | 2018-08-30 15:54:44 +0000 | [diff] [blame] | 46 | __stop___sancov_cntrs = 0; |
| 47 | |
Vitaly Buka | 124b2ba | 2019-09-11 23:19:48 +0000 | [diff] [blame] | 48 | #pragma section(".SCOV$GA", read, write) |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 49 | __declspec(allocate(".SCOV$GA")) uint64_t __start___sancov_guards = 0; |
Vitaly Buka | 124b2ba | 2019-09-11 23:19:48 +0000 | [diff] [blame] | 50 | #pragma section(".SCOV$GZ", read, write) |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 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. |
Matt Morehouse | dda104c | 2018-08-30 15:54:44 +0000 | [diff] [blame] | 57 | #pragma comment(linker, "/MERGE:.SCOV=.data") |
| 58 | |
Vitaly Buka | 124b2ba | 2019-09-11 23:19:48 +0000 | [diff] [blame] | 59 | #pragma section(".SCOVP$A", read) |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 60 | __declspec(allocate(".SCOVP$A")) uint64_t __start___sancov_pcs = 0; |
Vitaly Buka | 124b2ba | 2019-09-11 23:19:48 +0000 | [diff] [blame] | 61 | #pragma section(".SCOVP$Z", read) |
Jonathan Metzman | 79dbf9b | 2019-01-21 02:15:29 +0000 | [diff] [blame] | 62 | __declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t |
Matt Morehouse | dda104c | 2018-08-30 15:54:44 +0000 | [diff] [blame] | 63 | __stop___sancov_pcs = 0; |
| 64 | |
| 65 | #pragma comment(linker, "/MERGE:.SCOVP=.rdata") |
Marcos Pividori | e329a83 | 2017-02-02 23:02:15 +0000 | [diff] [blame] | 66 | } |
Matt Morehouse | dda104c | 2018-08-30 15:54:44 +0000 | [diff] [blame] | 67 | #endif // SANITIZER_WINDOWS |