1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_ZUCCHINI_TYPE_WIN_PE_H_ 6 #define COMPONENTS_ZUCCHINI_TYPE_WIN_PE_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 namespace zucchini { 12 13 // Structures and constants taken from WINNT.h and following identical layout. 14 // This is used for parsing of Portable Executable (PE) file format. 15 namespace pe { 16 // Supported by MSVC, g++, and clang++. Ensures no gaps in packing. 17 #pragma pack(push, 1) 18 19 // IMAGE_NUMBEROF_DIRECTORY_ENTRIES 20 constexpr size_t kImageNumberOfDirectoryEntries = 16; 21 22 // IMAGE_FILE_BASE_RELOCATION_TABLE 23 constexpr size_t kIndexOfBaseRelocationTable = 5; 24 25 constexpr uint32_t kImageScnMemExecute = 0x20000000; // IMAGE_SCN_MEM_EXECUTE 26 constexpr uint32_t kImageScnMemRead = 0x40000000; // IMAGE_SCN_MEM_READ 27 28 // IMAGE_DOS_HEADER 29 struct ImageDOSHeader { 30 uint16_t e_magic; // 0x00 31 uint16_t e_cblp; 32 uint16_t e_cp; 33 uint16_t e_crlc; 34 uint16_t e_cparhdr; 35 uint16_t e_minalloc; 36 uint16_t e_maxalloc; 37 uint16_t e_ss; 38 uint16_t e_sp; // 0x10 39 uint16_t e_csum; 40 uint16_t e_ip; 41 uint16_t e_cs; 42 uint16_t e_lfarlc; 43 uint16_t e_ovno; 44 uint16_t e_res[4]; 45 uint16_t e_oemid; // 0x24 46 uint16_t e_oeminfo; 47 uint16_t e_res2[10]; 48 uint32_t e_lfanew; // 0x3C 49 }; 50 static_assert(sizeof(ImageDOSHeader) == 0x40, 51 "DOS header size should be 0x40 bytes"); 52 53 // IMAGE_SECTION_HEADER 54 struct ImageSectionHeader { 55 char name[8]; 56 uint32_t virtual_size; 57 uint32_t virtual_address; 58 uint32_t size_of_raw_data; 59 uint32_t file_offset_of_raw_data; 60 uint32_t pointer_to_relocations; // Always zero in an image. 61 uint32_t pointer_to_line_numbers; // Always zero in an image. 62 uint16_t number_of_relocations; // Always zero in an image. 63 uint16_t number_of_line_numbers; // Always zero in an image. 64 uint32_t characteristics; 65 }; 66 static_assert(sizeof(ImageSectionHeader) == 0x28, 67 "Section header size should be 0x28 bytes"); 68 69 // IMAGE_DATA_DIRECTORY 70 struct ImageDataDirectory { 71 uint32_t virtual_address; 72 uint32_t size; 73 }; 74 static_assert(sizeof(ImageDataDirectory) == 0x08, 75 "Data directory size should be 0x08 bytes"); 76 77 // IMAGE_FILE_HEADER 78 struct ImageFileHeader { 79 uint16_t machine; 80 uint16_t number_of_sections; 81 uint32_t time_date_stamp; 82 uint32_t pointer_to_symbol_table; 83 uint32_t number_of_symbols; 84 uint16_t size_of_optional_header; 85 uint16_t characteristics; 86 }; 87 static_assert(sizeof(ImageFileHeader) == 0x14, 88 "File header size should be 0x14 bytes"); 89 90 // IMAGE_OPTIONAL_HEADER 91 struct ImageOptionalHeader { 92 uint16_t magic; // 0x00: 0x10B 93 uint8_t major_linker_version; 94 uint8_t minor_linker_version; 95 uint32_t size_of_code; 96 uint32_t size_of_initialized_data; 97 uint32_t size_of_uninitialized_data; 98 uint32_t address_of_entry_point; // 0x10 99 uint32_t base_of_code; 100 uint32_t base_of_data; 101 102 uint32_t image_base; 103 uint32_t section_alignment; // 0x20 104 uint32_t file_alignment; 105 uint16_t major_operating_system_version; 106 uint16_t minor_operating_system_version; 107 uint16_t major_image_version; 108 uint16_t minor_image_version; 109 uint16_t major_subsystem_version; // 0x30 110 uint16_t minor_subsystem_version; 111 uint32_t win32_version_value; 112 uint32_t size_of_image; 113 uint32_t size_of_headers; 114 uint32_t check_sum; // 0x40 115 uint16_t subsystem; 116 uint16_t dll_characteristics; 117 uint32_t size_of_stack_reserve; 118 uint32_t size_of_stack_commit; 119 uint32_t size_of_heap_reserve; // 0x50 120 uint32_t size_of_heap_commit; 121 uint32_t loader_flags; 122 uint32_t number_of_rva_and_sizes; 123 124 // The number of elements is actually |number_of_rva_and_sizes|, so accesses 125 // to |data_directory| should be checked against the bound. 126 ImageDataDirectory data_directory[kImageNumberOfDirectoryEntries]; // 0x60 127 /* 0xE0 */ 128 }; 129 static_assert(sizeof(ImageOptionalHeader) == 0xE0, 130 "Optional header (32) size should be 0xE0 bytes"); 131 132 // IMAGE_OPTIONAL_HEADER64 133 struct ImageOptionalHeader64 { 134 uint16_t magic; // 0x00: 0x20B 135 uint8_t major_linker_version; 136 uint8_t minor_linker_version; 137 uint32_t size_of_code; 138 uint32_t size_of_initialized_data; 139 uint32_t size_of_uninitialized_data; 140 uint32_t address_of_entry_point; // 0x10 141 uint32_t base_of_code; 142 143 uint64_t image_base; 144 uint32_t section_alignment; // 0x20 145 uint32_t file_alignment; 146 uint16_t major_operating_system_version; 147 uint16_t minor_operating_system_version; 148 uint16_t major_image_version; 149 uint16_t minor_image_version; 150 uint16_t major_subsystem_version; // 0x30 151 uint16_t minor_subsystem_version; 152 uint32_t win32_version_value; 153 uint32_t size_of_image; 154 uint32_t size_of_headers; 155 uint32_t check_sum; // 0x40 156 uint16_t subsystem; 157 uint16_t dll_characteristics; 158 uint64_t size_of_stack_reserve; 159 uint64_t size_of_stack_commit; // 0x50 160 uint64_t size_of_heap_reserve; 161 uint64_t size_of_heap_commit; // 0x60 162 uint32_t loader_flags; 163 uint32_t number_of_rva_and_sizes; 164 ImageDataDirectory data_directory[kImageNumberOfDirectoryEntries]; // 0x70 165 /* 0xF0 */ 166 }; 167 static_assert(sizeof(ImageOptionalHeader64) == 0xF0, 168 "Optional header (64) size should be 0xF0 bytes"); 169 170 struct RelocHeader { 171 uint32_t rva_hi; 172 uint32_t size; 173 }; 174 static_assert(sizeof(RelocHeader) == 8, "RelocHeader size should be 8 bytes"); 175 176 #pragma pack(pop) 177 178 } // namespace pe 179 180 // Constants and offsets gleaned from WINNT.h and various articles on the 181 // format of Windows PE executables. 182 183 constexpr char const* kTextSectionName = ".text"; 184 185 // Bitfield with characteristics usually associated with code sections. 186 const uint32_t kCodeCharacteristics = 187 pe::kImageScnMemExecute | pe::kImageScnMemRead; 188 189 } // namespace zucchini 190 191 #endif // COMPONENTS_ZUCCHINI_TYPE_WIN_PE_H_ 192