]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libpe/libpe_coff.c
Optionally bind ktls threads to NUMA domains
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libpe / libpe_coff.c
1 /*-
2  * Copyright (c) 2015 Kai Wang
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/param.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <unistd.h>
34
35 #include "_libpe.h"
36
37 ELFTC_VCSID("$Id: libpe_coff.c 3326 2016-01-16 17:46:17Z kaiwang27 $");
38
39 int
40 libpe_parse_coff_header(PE *pe, char *hdr)
41 {
42         char tmp[128];
43         PE_CoffHdr *ch;
44         PE_OptHdr *oh;
45         PE_DataDir *dd;
46         unsigned p, r, s;
47         int i;
48
49         if ((ch = malloc(sizeof(PE_CoffHdr))) == NULL) {
50                 errno = ENOMEM;
51                 return (-1);
52         }
53
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);
61
62         pe->pe_ch = ch;
63
64         /*
65          * The Optional header is omitted for object files.
66          */
67         if (ch->ch_optsize == 0)
68                 return (libpe_parse_section_headers(pe));
69
70         if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
71                 errno = ENOMEM;
72                 return (-1);
73         }
74         pe->pe_oh = oh;
75
76 #define READ_OPT(n)                                                     \
77         do {                                                            \
78                 /*                                                      \
79                  * Since the Optional Header size is variable, we must  \
80                  * check if the requested read size will overrun the    \
81                  * remaining header bytes.                              \
82                  */                                                     \
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;\
88                                 return (0);                             \
89                         }                                               \
90                         return (libpe_parse_section_headers(pe));       \
91                 }                                                       \
92                 if (read(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) {       \
93                         pe->pe_flags |= LIBPE_F_BAD_OPT_HEADER; \
94                         return (0);                                     \
95                 }                                                       \
96                 p += (n);                                               \
97         } while (0)
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)
102
103         /*
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+)
106          */
107
108         p = 0;
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);
122         } else
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);
143         } else {
144                 READ_OPT64(oh->oh_stacksizer);
145                 READ_OPT64(oh->oh_stacksizec);
146                 READ_OPT64(oh->oh_heapsizer);
147                 READ_OPT64(oh->oh_heapsizec);
148         }
149         READ_OPT32(oh->oh_ldrflags);
150         READ_OPT32(oh->oh_ndatadir);
151
152         /*
153          * Read in the Data Directories.
154          */
155
156         if (oh->oh_ndatadir > 0) {
157                 if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
158                         errno = ENOMEM;
159                         return (-1);
160                 }
161                 pe->pe_dd = dd;
162
163                 dd->dd_total = oh->oh_ndatadir < PE_DD_MAX ? oh->oh_ndatadir :
164                         PE_DD_MAX;
165
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);
169                 }
170         }
171
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;
179                                 return (0);
180                         }
181                 }
182         }
183
184         return (libpe_parse_section_headers(pe));
185 }
186
187 off_t
188 libpe_write_pe_header(PE *pe, off_t off)
189 {
190         char tmp[4];
191
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,
196                     SEEK_SET);
197                 return (off);
198         }
199
200         /*
201          * PE Header should to be aligned on 8-byte boundary according to
202          * the PE/COFF specification.
203          */
204         if ((off = libpe_align(pe, off, 8)) < 0)
205                 return (-1);
206
207         le32enc(tmp, PE_SIGNATURE);
208         if (write(pe->pe_fd, tmp, sizeof(tmp)) != (ssize_t) sizeof(tmp)) {
209                 errno = EIO;
210                 return (-1);
211         }
212
213         off += 4;
214
215         pe->pe_flags &= ~LIBPE_F_BAD_PE_HEADER;
216
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;
220
221         return (off);
222 }
223
224 off_t
225 libpe_write_coff_header(PE *pe, off_t off)
226 {
227         char tmp[128], *hdr;
228         PE_CoffHdr *ch;
229         PE_DataDir *dd;
230         PE_OptHdr *oh;
231         PE_Scn *ps;
232         PE_SecHdr *sh;
233         unsigned p;
234         uint32_t reloc_rva, reloc_sz;
235         int i, reloc;
236
237         reloc = 0;
238         reloc_rva = reloc_sz = 0;
239
240         if (pe->pe_cmd == PE_C_RDWR) {
241                 assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
242
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),
246                             SEEK_CUR) < 0) {
247                                 errno = EIO;
248                                 return (-1);
249                         }
250                         off += sizeof(PE_CoffHdr);
251                         assert(pe->pe_ch != NULL);
252                         ch = pe->pe_ch;
253                         goto coff_done;
254                 }
255
256                 /* lseek(2) to the offset of the COFF header. */
257                 if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
258                         errno = EIO;
259                         return (-1);
260                 }
261         }
262
263         if (pe->pe_ch == NULL) {
264                 if ((ch = calloc(1, sizeof(PE_CoffHdr))) == NULL) {
265                         errno = ENOMEM;
266                         return (-1);
267                 }
268                 pe->pe_ch = ch;
269
270                 /*
271                  * Default value for ch_machine if not provided by the
272                  * application.
273                  */
274                 if (pe->pe_obj == PE_O_PE32P)
275                         ch->ch_machine = IMAGE_FILE_MACHINE_AMD64;
276                 else
277                         ch->ch_machine = IMAGE_FILE_MACHINE_I386;
278
279         } else
280                 ch = pe->pe_ch;
281
282         if (!ch->ch_timestamp)
283                 ch->ch_timestamp = time(NULL);
284
285         if (pe->pe_obj == PE_O_PE32) {
286                 if (!ch->ch_optsize)
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) {
291                 if (!ch->ch_optsize)
292                         ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
293                 ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
294                     IMAGE_FILE_LARGE_ADDRESS_AWARE;
295         } else
296                 ch->ch_optsize = 0;
297
298         /*
299          * COFF line number is deprecated by the PE/COFF
300          * specification. COFF symbol table is deprecated
301          * for executables.
302          */
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;
306
307         ch->ch_nsec = pe->pe_nscn;
308
309         STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
310                 sh = &ps->ps_sh;
311
312                 if (ps->ps_ndx == 0xFFFFFFFFU) {
313                         ch->ch_symptr = sh->sh_rawptr;
314                         ch->ch_nsym = pe->pe_nsym;
315                 }
316
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")) ==
320                             0) {
321                                 reloc = 1;
322                                 reloc_rva = sh->sh_addr;
323                                 reloc_sz = sh->sh_virtsize;
324                         }
325                 }
326         }
327
328         if (!reloc)
329                 ch->ch_char |= IMAGE_FILE_RELOCS_STRIPPED;
330
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;
336                 else
337                         ch->ch_optsize = 0;
338         }
339
340         /*
341          * Write the COFF header.
342          */
343         hdr = tmp;
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)) {
353                 errno = EIO;
354                 return (-1);
355         }
356
357 coff_done:
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;
362
363         if (ch->ch_optsize == 0)
364                 return (off);
365
366         /*
367          * Write the Optional header.
368          */
369
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,
374                             SEEK_CUR) < 0) {
375                                 errno = EIO;
376                                 return (-1);
377                         }
378                         off += ch->ch_optsize;
379                         return (off);
380                 }
381
382         }
383
384         if (pe->pe_oh == NULL) {
385                 if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
386                         errno = ENOMEM;
387                         return (-1);
388                 }
389                 pe->pe_oh = oh;
390         } else
391                 oh = pe->pe_oh;
392
393         if (pe->pe_obj == PE_O_PE32)
394                 oh->oh_magic = PE_FORMAT_32;
395         else
396                 oh->oh_magic = PE_FORMAT_32P;
397
398         /*
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)
402          */
403         if (!oh->oh_ldvermajor && !oh->oh_ldverminor) {
404                 oh->oh_ldvermajor = 2;
405                 oh->oh_ldverminor = 22;
406         }
407
408         /*
409          * The library always tries to write out all 16 data directories
410          * but the actual data dir written will depend on ch_optsize.
411          */
412         oh->oh_ndatadir = PE_DD_MAX;
413
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);
421
422 #define WRITE_OPT(n)                                                    \
423         do {                                                            \
424                 /*                                                      \
425                  * Since the Optional Header size is variable, we must  \
426                  * check if the requested write size will overrun the   \
427                  * remaining header bytes.                              \
428                  */                                                     \
429                 if (p + (n) > ch->ch_optsize) {                         \
430                         /* Pad the "extra" bytes */                     \
431                         if (libpe_pad(pe, ch->ch_optsize - p) < 0) {    \
432                                 errno = EIO;                            \
433                                 return (-1);                            \
434                         }                                               \
435                         goto opt_done;                                  \
436                 }                                                       \
437                 if (write(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) {      \
438                         errno = EIO;                                    \
439                         return (-1);                                    \
440                 }                                                       \
441                 p += (n);                                               \
442         } while (0)
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)
447
448         p = 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);
462         } else
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);
483         } else {
484                 WRITE_OPT64(oh->oh_stacksizer);
485                 WRITE_OPT64(oh->oh_stacksizec);
486                 WRITE_OPT64(oh->oh_heapsizer);
487                 WRITE_OPT64(oh->oh_heapsizec);
488         }
489         WRITE_OPT32(oh->oh_ldrflags);
490         WRITE_OPT32(oh->oh_ndatadir);
491
492         /*
493          * Write the Data Directories.
494          */
495
496         if (oh->oh_ndatadir > 0) {
497                 if (pe->pe_dd == NULL) {
498                         if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
499                                 errno = ENOMEM;
500                                 return (-1);
501                         }
502                         pe->pe_dd = dd;
503                         dd->dd_total = PE_DD_MAX;
504                 } else
505                         dd = pe->pe_dd;
506
507                 assert(oh->oh_ndatadir <= PE_DD_MAX);
508
509                 if (reloc) {
510                         dd->dd_e[PE_DD_BASERELOC].de_addr = reloc_rva;
511                         dd->dd_e[PE_DD_BASERELOC].de_size = reloc_sz;
512                 }
513
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);
517                 }
518         }
519
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) {
523                         errno = EIO;
524                         return (-1);
525                 }
526         }
527
528 opt_done:
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;
533
534         return (off);
535 }