2 * Copyright (c) 2015 Kai Wang
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/param.h>
37 ELFTC_VCSID("$Id: libpe_coff.c 3326 2016-01-16 17:46:17Z kaiwang27 $");
40 libpe_parse_coff_header(PE *pe, char *hdr)
49 if ((ch = malloc(sizeof(PE_CoffHdr))) == NULL) {
54 PE_READ16(hdr, ch->ch_machine);
55 PE_READ16(hdr, ch->ch_nsec);
56 PE_READ32(hdr, ch->ch_timestamp);
57 PE_READ32(hdr, ch->ch_symptr);
58 PE_READ32(hdr, ch->ch_nsym);
59 PE_READ16(hdr, ch->ch_optsize);
60 PE_READ16(hdr, ch->ch_char);
65 * The Optional header is omitted for object files.
67 if (ch->ch_optsize == 0)
68 return (libpe_parse_section_headers(pe));
70 if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
79 * Since the Optional Header size is variable, we must \
80 * check if the requested read size will overrun the \
81 * remaining header bytes. \
83 if (p + (n) > ch->ch_optsize) { \
84 /* Consume the "extra" bytes */ \
85 r = ch->ch_optsize - p; \
86 if (read(pe->pe_fd, tmp, r) != (ssize_t) r) { \
87 pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;\
90 return (libpe_parse_section_headers(pe)); \
92 if (read(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \
93 pe->pe_flags |= LIBPE_F_BAD_OPT_HEADER; \
98 #define READ_OPT8(v) do { READ_OPT(1); (v) = *tmp; } while(0)
99 #define READ_OPT16(v) do { READ_OPT(2); (v) = le16dec(tmp); } while(0)
100 #define READ_OPT32(v) do { READ_OPT(4); (v) = le32dec(tmp); } while(0)
101 #define READ_OPT64(v) do { READ_OPT(8); (v) = le64dec(tmp); } while(0)
104 * Read in the Optional header. Size of some fields are depending
105 * on the PE format specified by the oh_magic field. (PE32 or PE32+)
109 READ_OPT16(oh->oh_magic);
110 if (oh->oh_magic == PE_FORMAT_32P)
111 pe->pe_obj = PE_O_PE32P;
112 READ_OPT8(oh->oh_ldvermajor);
113 READ_OPT8(oh->oh_ldverminor);
114 READ_OPT32(oh->oh_textsize);
115 READ_OPT32(oh->oh_datasize);
116 READ_OPT32(oh->oh_bsssize);
117 READ_OPT32(oh->oh_entry);
118 READ_OPT32(oh->oh_textbase);
119 if (oh->oh_magic != PE_FORMAT_32P) {
120 READ_OPT32(oh->oh_database);
121 READ_OPT32(oh->oh_imgbase);
123 READ_OPT64(oh->oh_imgbase);
124 READ_OPT32(oh->oh_secalign);
125 READ_OPT32(oh->oh_filealign);
126 READ_OPT16(oh->oh_osvermajor);
127 READ_OPT16(oh->oh_osverminor);
128 READ_OPT16(oh->oh_imgvermajor);
129 READ_OPT16(oh->oh_imgverminor);
130 READ_OPT16(oh->oh_subvermajor);
131 READ_OPT16(oh->oh_subverminor);
132 READ_OPT32(oh->oh_win32ver);
133 READ_OPT32(oh->oh_imgsize);
134 READ_OPT32(oh->oh_hdrsize);
135 READ_OPT32(oh->oh_checksum);
136 READ_OPT16(oh->oh_subsystem);
137 READ_OPT16(oh->oh_dllchar);
138 if (oh->oh_magic != PE_FORMAT_32P) {
139 READ_OPT32(oh->oh_stacksizer);
140 READ_OPT32(oh->oh_stacksizec);
141 READ_OPT32(oh->oh_heapsizer);
142 READ_OPT32(oh->oh_heapsizec);
144 READ_OPT64(oh->oh_stacksizer);
145 READ_OPT64(oh->oh_stacksizec);
146 READ_OPT64(oh->oh_heapsizer);
147 READ_OPT64(oh->oh_heapsizec);
149 READ_OPT32(oh->oh_ldrflags);
150 READ_OPT32(oh->oh_ndatadir);
153 * Read in the Data Directories.
156 if (oh->oh_ndatadir > 0) {
157 if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
163 dd->dd_total = oh->oh_ndatadir < PE_DD_MAX ? oh->oh_ndatadir :
166 for (i = 0; (uint32_t) i < dd->dd_total; i++) {
167 READ_OPT32(dd->dd_e[i].de_addr);
168 READ_OPT32(dd->dd_e[i].de_size);
172 /* Consume the remaining bytes in the Optional header, if any. */
173 if (ch->ch_optsize > p) {
174 r = ch->ch_optsize - p;
175 for (; r > 0; r -= s) {
176 s = r > sizeof(tmp) ? sizeof(tmp) : r;
177 if (read(pe->pe_fd, tmp, s) != (ssize_t) s) {
178 pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;
184 return (libpe_parse_section_headers(pe));
188 libpe_write_pe_header(PE *pe, off_t off)
192 if (pe->pe_cmd == PE_C_RDWR &&
193 (pe->pe_flags & LIBPE_F_BAD_PE_HEADER) == 0) {
194 assert(pe->pe_dh != NULL);
195 off = lseek(pe->pe_fd, (off_t) pe->pe_dh->dh_lfanew + 4,
201 * PE Header should to be aligned on 8-byte boundary according to
202 * the PE/COFF specification.
204 if ((off = libpe_align(pe, off, 8)) < 0)
207 le32enc(tmp, PE_SIGNATURE);
208 if (write(pe->pe_fd, tmp, sizeof(tmp)) != (ssize_t) sizeof(tmp)) {
215 pe->pe_flags &= ~LIBPE_F_BAD_PE_HEADER;
217 /* Trigger rewrite for the following headers. */
218 pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
219 pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
225 libpe_write_coff_header(PE *pe, off_t off)
234 uint32_t reloc_rva, reloc_sz;
238 reloc_rva = reloc_sz = 0;
240 if (pe->pe_cmd == PE_C_RDWR) {
241 assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
243 if ((pe->pe_flags & LIBPE_F_DIRTY_COFF_HEADER) == 0 &&
244 (pe->pe_flags & LIBPE_F_BAD_COFF_HEADER) == 0) {
245 if (lseek(pe->pe_fd, (off_t) sizeof(PE_CoffHdr),
250 off += sizeof(PE_CoffHdr);
251 assert(pe->pe_ch != NULL);
256 /* lseek(2) to the offset of the COFF header. */
257 if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
263 if (pe->pe_ch == NULL) {
264 if ((ch = calloc(1, sizeof(PE_CoffHdr))) == NULL) {
271 * Default value for ch_machine if not provided by the
274 if (pe->pe_obj == PE_O_PE32P)
275 ch->ch_machine = IMAGE_FILE_MACHINE_AMD64;
277 ch->ch_machine = IMAGE_FILE_MACHINE_I386;
282 if (!ch->ch_timestamp)
283 ch->ch_timestamp = time(NULL);
285 if (pe->pe_obj == PE_O_PE32) {
287 ch->ch_optsize = PE_COFF_OPT_SIZE_32;
288 ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
289 IMAGE_FILE_32BIT_MACHINE;
290 } else if (pe->pe_obj == PE_O_PE32P) {
292 ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
293 ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
294 IMAGE_FILE_LARGE_ADDRESS_AWARE;
299 * COFF line number is deprecated by the PE/COFF
300 * specification. COFF symbol table is deprecated
303 ch->ch_char |= IMAGE_FILE_LINE_NUMS_STRIPPED;
304 if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P)
305 ch->ch_char |= IMAGE_FILE_LOCAL_SYMS_STRIPPED;
307 ch->ch_nsec = pe->pe_nscn;
309 STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
312 if (ps->ps_ndx == 0xFFFFFFFFU) {
313 ch->ch_symptr = sh->sh_rawptr;
314 ch->ch_nsym = pe->pe_nsym;
317 if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) {
318 if (ps->ps_ndx == (0xFFFF0000 | PE_DD_BASERELOC) ||
319 strncmp(sh->sh_name, ".reloc", strlen(".reloc")) ==
322 reloc_rva = sh->sh_addr;
323 reloc_sz = sh->sh_virtsize;
329 ch->ch_char |= IMAGE_FILE_RELOCS_STRIPPED;
331 if (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) {
332 if (pe->pe_obj == PE_O_PE32)
333 ch->ch_optsize = PE_COFF_OPT_SIZE_32;
334 else if (pe->pe_obj == PE_O_PE32P)
335 ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
341 * Write the COFF header.
344 PE_WRITE16(hdr, ch->ch_machine);
345 PE_WRITE16(hdr, ch->ch_nsec);
346 PE_WRITE32(hdr, ch->ch_timestamp);
347 PE_WRITE32(hdr, ch->ch_symptr);
348 PE_WRITE32(hdr, ch->ch_nsym);
349 PE_WRITE16(hdr, ch->ch_optsize);
350 PE_WRITE16(hdr, ch->ch_char);
351 if (write(pe->pe_fd, tmp, sizeof(PE_CoffHdr)) !=
352 (ssize_t) sizeof(PE_CoffHdr)) {
358 off += sizeof(PE_CoffHdr);
359 pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER;
360 pe->pe_flags &= ~LIBPE_F_BAD_COFF_HEADER;
361 pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
363 if (ch->ch_optsize == 0)
367 * Write the Optional header.
370 if (pe->pe_cmd == PE_C_RDWR) {
371 if ((pe->pe_flags & LIBPE_F_DIRTY_OPT_HEADER) == 0 &&
372 (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) == 0) {
373 if (lseek(pe->pe_fd, (off_t) ch->ch_optsize,
378 off += ch->ch_optsize;
384 if (pe->pe_oh == NULL) {
385 if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
393 if (pe->pe_obj == PE_O_PE32)
394 oh->oh_magic = PE_FORMAT_32;
396 oh->oh_magic = PE_FORMAT_32P;
399 * LinkerVersion should not be less than 2.5, which will cause
400 * Windows to complain the executable is invalid in some case.
401 * By default we set LinkerVersion to 2.22 (binutils 2.22)
403 if (!oh->oh_ldvermajor && !oh->oh_ldverminor) {
404 oh->oh_ldvermajor = 2;
405 oh->oh_ldverminor = 22;
409 * The library always tries to write out all 16 data directories
410 * but the actual data dir written will depend on ch_optsize.
412 oh->oh_ndatadir = PE_DD_MAX;
414 if (!oh->oh_filealign)
415 oh->oh_filealign = 0x200;
416 if (!oh->oh_secalign)
417 oh->oh_secalign = 0x1000;
418 oh->oh_hdrsize = roundup(off + ch->ch_optsize + pe->pe_nscn *
419 sizeof(PE_SecHdr), oh->oh_filealign);
420 oh->oh_imgsize = roundup(pe->pe_rvamax, oh->oh_secalign);
422 #define WRITE_OPT(n) \
425 * Since the Optional Header size is variable, we must \
426 * check if the requested write size will overrun the \
427 * remaining header bytes. \
429 if (p + (n) > ch->ch_optsize) { \
430 /* Pad the "extra" bytes */ \
431 if (libpe_pad(pe, ch->ch_optsize - p) < 0) { \
437 if (write(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \
443 #define WRITE_OPT8(v) do { *tmp = (v); WRITE_OPT(1); } while(0)
444 #define WRITE_OPT16(v) do { le16enc(tmp, (v)); WRITE_OPT(2); } while(0)
445 #define WRITE_OPT32(v) do { le32enc(tmp, (v)); WRITE_OPT(4); } while(0)
446 #define WRITE_OPT64(v) do { le64enc(tmp, (v)); WRITE_OPT(8); } while(0)
449 WRITE_OPT16(oh->oh_magic);
450 if (oh->oh_magic == PE_FORMAT_32P)
451 pe->pe_obj = PE_O_PE32P;
452 WRITE_OPT8(oh->oh_ldvermajor);
453 WRITE_OPT8(oh->oh_ldverminor);
454 WRITE_OPT32(oh->oh_textsize);
455 WRITE_OPT32(oh->oh_datasize);
456 WRITE_OPT32(oh->oh_bsssize);
457 WRITE_OPT32(oh->oh_entry);
458 WRITE_OPT32(oh->oh_textbase);
459 if (oh->oh_magic != PE_FORMAT_32P) {
460 WRITE_OPT32(oh->oh_database);
461 WRITE_OPT32(oh->oh_imgbase);
463 WRITE_OPT64(oh->oh_imgbase);
464 WRITE_OPT32(oh->oh_secalign);
465 WRITE_OPT32(oh->oh_filealign);
466 WRITE_OPT16(oh->oh_osvermajor);
467 WRITE_OPT16(oh->oh_osverminor);
468 WRITE_OPT16(oh->oh_imgvermajor);
469 WRITE_OPT16(oh->oh_imgverminor);
470 WRITE_OPT16(oh->oh_subvermajor);
471 WRITE_OPT16(oh->oh_subverminor);
472 WRITE_OPT32(oh->oh_win32ver);
473 WRITE_OPT32(oh->oh_imgsize);
474 WRITE_OPT32(oh->oh_hdrsize);
475 WRITE_OPT32(oh->oh_checksum);
476 WRITE_OPT16(oh->oh_subsystem);
477 WRITE_OPT16(oh->oh_dllchar);
478 if (oh->oh_magic != PE_FORMAT_32P) {
479 WRITE_OPT32(oh->oh_stacksizer);
480 WRITE_OPT32(oh->oh_stacksizec);
481 WRITE_OPT32(oh->oh_heapsizer);
482 WRITE_OPT32(oh->oh_heapsizec);
484 WRITE_OPT64(oh->oh_stacksizer);
485 WRITE_OPT64(oh->oh_stacksizec);
486 WRITE_OPT64(oh->oh_heapsizer);
487 WRITE_OPT64(oh->oh_heapsizec);
489 WRITE_OPT32(oh->oh_ldrflags);
490 WRITE_OPT32(oh->oh_ndatadir);
493 * Write the Data Directories.
496 if (oh->oh_ndatadir > 0) {
497 if (pe->pe_dd == NULL) {
498 if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
503 dd->dd_total = PE_DD_MAX;
507 assert(oh->oh_ndatadir <= PE_DD_MAX);
510 dd->dd_e[PE_DD_BASERELOC].de_addr = reloc_rva;
511 dd->dd_e[PE_DD_BASERELOC].de_size = reloc_sz;
514 for (i = 0; (uint32_t) i < dd->dd_total; i++) {
515 WRITE_OPT32(dd->dd_e[i].de_addr);
516 WRITE_OPT32(dd->dd_e[i].de_size);
520 /* Pad the remaining bytes in the Optional header, if any. */
521 if (ch->ch_optsize > p) {
522 if (libpe_pad(pe, ch->ch_optsize - p) < 0) {
529 off += ch->ch_optsize;
530 pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
531 pe->pe_flags &= ~LIBPE_F_BAD_OPT_HEADER;
532 pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;