subr_pe.c revision 123821
1/*
2 * Copyright (c) 2003
3 *	Bill Paul <wpaul@windriver.com>.  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 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_pe.c 123821 2003-12-24 21:21:18Z wpaul $");
35
36/*
37 * This file contains routines for relocating and dynamically linking
38 * executable object code files in the Windows(r) PE (Portable Executable)
39 * format. In Windows, anything with a .EXE, .DLL or .SYS extention is
40 * considered an executable, and all such files have some structures in
41 * common. The PE format was apparently based largely on COFF but has
42 * mutated significantly over time. We are mainly concerned with .SYS files,
43 * so this module implements only enough routines to be able to parse the
44 * headers and sections of a .SYS object file and perform the necessary
45 * relocations and jump table patching to allow us to call into it
46 * (and to have it call back to us). Note that while this module
47 * can handle fixups for imported symbols, it knows nothing about
48 * exporting them.
49 */
50
51#include <sys/param.h>
52#include <sys/types.h>
53#include <sys/errno.h>
54#ifdef _KERNEL
55#include <sys/systm.h>
56#else
57#include <stdio.h>
58#include <stdlib.h>
59#include <unistd.h>
60#include <string.h>
61#endif
62
63#include <compat/ndis/pe_var.h>
64
65static u_int32_t pe_functbl_match(image_patch_table *, char *);
66
67/*
68 * Check for an MS-DOS executable header. All Windows binaries
69 * have a small MS-DOS executable prepended to them to print out
70 * the "This program requires Windows" message. Even .SYS files
71 * have this header, in spite of the fact that you're can't actually
72 * run them directly.
73 */
74
75int
76pe_get_dos_header(imgbase, hdr)
77	vm_offset_t		imgbase;
78	image_dos_header	*hdr;
79{
80	uint16_t		signature;
81
82	if (imgbase == 0 || hdr == NULL)
83		return (EINVAL);
84
85	signature = *(uint16_t *)imgbase;
86	if (signature != IMAGE_DOS_SIGNATURE)
87		return (ENOEXEC);
88
89	bcopy ((char *)imgbase, (char *)hdr, sizeof(image_dos_header));
90
91	return(0);
92}
93
94/*
95 * Verify that this image has a Windows NT PE signature.
96 */
97
98int
99pe_is_nt_image(imgbase)
100	vm_offset_t		imgbase;
101{
102	uint32_t		signature;
103	image_dos_header	*dos_hdr;
104
105	if (imgbase == 0)
106		return (EINVAL);
107
108	signature = *(uint16_t *)imgbase;
109	if (signature == IMAGE_DOS_SIGNATURE) {
110		dos_hdr = (image_dos_header *)imgbase;
111		signature = *(uint32_t *)(imgbase + dos_hdr->idh_lfanew);
112		if (signature == IMAGE_NT_SIGNATURE)
113			return(0);
114	}
115
116	return(ENOEXEC);
117}
118
119/*
120 * Return a copy of the optional header. This contains the
121 * executable entry point and the directory listing which we
122 * need to find the relocations and imports later.
123 */
124
125int
126pe_get_optional_header(imgbase, hdr)
127	vm_offset_t		imgbase;
128	image_optional_header	*hdr;
129{
130	image_dos_header	*dos_hdr;
131	image_nt_header		*nt_hdr;
132
133	if (imgbase == 0 || hdr == NULL)
134		return(EINVAL);
135
136	if (pe_is_nt_image(imgbase))
137		return (EINVAL);
138
139	dos_hdr = (image_dos_header *)(imgbase);
140	nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
141
142	bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr,
143	    sizeof(image_optional_header));
144
145	return(0);
146}
147
148/*
149 * Return a copy of the file header. Contains the number of
150 * sections in this image.
151 */
152
153int
154pe_get_file_header(imgbase, hdr)
155	vm_offset_t		imgbase;
156	image_file_header	*hdr;
157{
158	image_dos_header	*dos_hdr;
159	image_nt_header		*nt_hdr;
160
161	if (imgbase == 0 || hdr == NULL)
162		return(EINVAL);
163
164	if (pe_is_nt_image(imgbase))
165		return (EINVAL);
166
167	dos_hdr = (image_dos_header *)imgbase;
168	nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
169
170	bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr,
171	    sizeof(image_file_header));
172
173	return(0);
174}
175
176/*
177 * Return the header of the first section in this image (usually
178 * .text).
179 */
180
181int
182pe_get_section_header(imgbase, hdr)
183	vm_offset_t		imgbase;
184	image_section_header	*hdr;
185{
186	image_dos_header	*dos_hdr;
187	image_nt_header		*nt_hdr;
188	image_section_header	*sect_hdr;
189
190	if (imgbase == 0 || hdr == NULL)
191		return(EINVAL);
192
193	if (pe_is_nt_image(imgbase))
194		return (EINVAL);
195
196	dos_hdr = (image_dos_header *)imgbase;
197	nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
198	sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
199	    sizeof(image_nt_header));
200
201	bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header));
202
203	return(0);
204}
205
206/*
207 * Return the number of sections in this executable, or 0 on error.
208 */
209
210int
211pe_numsections(imgbase)
212	vm_offset_t		imgbase;
213{
214	image_file_header	file_hdr;
215
216	if (pe_get_file_header(imgbase, &file_hdr))
217		return(0);
218
219	return (file_hdr.ifh_numsections);
220}
221
222/*
223 * Return the base address that this image was linked for.
224 * This helps us calculate relocation addresses later.
225 */
226
227vm_offset_t
228pe_imagebase(imgbase)
229	vm_offset_t		imgbase;
230{
231	image_optional_header	optional_hdr;
232
233	if (pe_get_optional_header(imgbase, &optional_hdr))
234		return(0);
235
236	return (optional_hdr.ioh_imagebase);
237}
238
239/*
240 * Return the offset of a given directory structure within the
241 * image. Directories reside within sections.
242 */
243
244vm_offset_t
245pe_directory_offset(imgbase, diridx)
246	vm_offset_t		imgbase;
247	uint32_t		diridx;
248{
249	image_optional_header	opt_hdr;
250	vm_offset_t		dir;
251
252	if (pe_get_optional_header(imgbase, &opt_hdr))
253		return(0);
254
255	if (diridx >= opt_hdr.ioh_rva_size_cnt)
256		return(0);
257
258	dir = opt_hdr.ioh_datadir[diridx].idd_vaddr;
259
260	return(pe_translate_addr(imgbase, dir));
261}
262
263vm_offset_t
264pe_translate_addr(imgbase, rva)
265	vm_offset_t		imgbase;
266	uint32_t		rva;
267{
268	image_optional_header	opt_hdr;
269	image_section_header	*sect_hdr;
270	image_dos_header	*dos_hdr;
271	image_nt_header		*nt_hdr;
272	int			i = 0, sections, fixedlen;
273
274	if (pe_get_optional_header(imgbase, &opt_hdr))
275		return(0);
276
277	sections = pe_numsections(imgbase);
278
279	dos_hdr = (image_dos_header *)imgbase;
280	nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
281	sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
282	    sizeof(image_nt_header));
283
284	/*
285	 * The test here is to see if the RVA falls somewhere
286	 * inside the section, based on the section's start RVA
287	 * and its length. However it seems sometimes the
288	 * virtual length isn't enough to cover the entire
289	 * area of the section. We fudge by taking into account
290	 * the section alignment and rounding the section length
291	 * up to a page boundary.
292	 */
293	while (i++ < sections) {
294		fixedlen = sect_hdr->ish_misc.ish_vsize;
295		fixedlen += ((opt_hdr.ioh_sectalign - 1) -
296		    sect_hdr->ish_misc.ish_vsize) &
297		    (opt_hdr.ioh_sectalign - 1);
298		if (sect_hdr->ish_vaddr <= (u_int32_t)rva &&
299		    (sect_hdr->ish_vaddr + fixedlen) >
300		    (u_int32_t)rva)
301			break;
302		sect_hdr++;
303	}
304
305	if (i > sections)
306		return(0);
307
308	return((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr +
309	    sect_hdr->ish_rawdataaddr));
310}
311
312/*
313 * Get the section header for a particular section. Note that
314 * section names can be anything, but there are some standard
315 * ones (.text, .data, .rdata, .reloc).
316 */
317
318int
319pe_get_section(imgbase, hdr, name)
320	vm_offset_t		imgbase;
321	image_section_header	*hdr;
322	const char		*name;
323{
324	image_dos_header	*dos_hdr;
325	image_nt_header		*nt_hdr;
326	image_section_header	*sect_hdr;
327
328	int			i, sections;
329
330	if (imgbase == 0 || hdr == NULL)
331		return(EINVAL);
332
333	if (pe_is_nt_image(imgbase))
334		return (EINVAL);
335
336	sections = pe_numsections(imgbase);
337
338	dos_hdr = (image_dos_header *)imgbase;
339	nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
340	sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
341	    sizeof(image_nt_header));
342
343	for (i = 0; i < sections; i++) {
344		if (!strcmp ((char *)&sect_hdr->ish_name, name)) {
345			bcopy((char *)sect_hdr, (char *)hdr,
346			    sizeof(image_section_header));
347			return(0);
348		} else
349			sect_hdr++;
350	}
351
352	return (ENOEXEC);
353}
354
355/*
356 * Apply the base relocations to this image. The relocation table
357 * resides within the .reloc section. Relocations are specified in
358 * blocks which refer to a particular page. We apply the relocations
359 * one page block at a time.
360 */
361
362int
363pe_relocate(imgbase)
364	vm_offset_t		imgbase;
365{
366	image_section_header	sect;
367	image_base_reloc	*relhdr;
368	uint16_t		rel, *sloc;
369	uint32_t		base, delta, *lloc;
370	int			i, count;
371	vm_offset_t		txt;
372
373	base = pe_imagebase(imgbase);
374	pe_get_section(imgbase, &sect, ".text");
375	txt = pe_translate_addr(imgbase, sect.ish_vaddr);
376	delta = (uint32_t)(txt) - base - sect.ish_vaddr;
377
378	pe_get_section(imgbase, &sect, ".reloc");
379
380	relhdr = (image_base_reloc *)(imgbase + sect.ish_rawdataaddr);
381
382	do {
383		count = (relhdr->ibr_blocksize -
384		    (sizeof(uint32_t) * 2)) / sizeof(uint16_t);
385		for (i = 0; i < count; i++) {
386			rel = relhdr->ibr_rel[i];
387			switch (IMR_RELTYPE(rel)) {
388			case IMAGE_REL_BASED_ABSOLUTE:
389				break;
390			case IMAGE_REL_BASED_HIGHLOW:
391				lloc = (uint32_t *)pe_translate_addr(imgbase,
392				    relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
393				*lloc = pe_translate_addr(imgbase,
394				    (*lloc - base));
395				break;
396			case IMAGE_REL_BASED_HIGH:
397				sloc = (uint16_t *)pe_translate_addr(imgbase,
398				    relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
399				*sloc += (delta & 0xFFFF0000) >> 16;
400				break;
401			case IMAGE_REL_BASED_LOW:
402				sloc = (uint16_t *)pe_translate_addr(imgbase,
403				    relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
404				*sloc += (delta & 0xFFFF);
405				break;
406			default:
407				printf ("[%d]reloc type: %d\n",i,
408				    IMR_RELTYPE(rel));
409				break;
410			}
411		}
412		relhdr = (image_base_reloc *)((vm_offset_t)relhdr +
413		    relhdr->ibr_blocksize);
414	} while (relhdr->ibr_blocksize);
415
416	return(0);
417}
418
419/*
420 * Return the import descriptor for a particular module. An image
421 * may be linked against several modules, typically HAL.dll, ntoskrnl.exe
422 * and NDIS.SYS. For each module, there is a list of imported function
423 * names and their addresses.
424 */
425
426int
427pe_get_import_descriptor(imgbase, desc, module)
428	vm_offset_t		imgbase;
429	image_import_descriptor	*desc;
430	char			*module;
431{
432	vm_offset_t		offset;
433	image_import_descriptor	*imp_desc;
434	char			*modname;
435
436	if (imgbase == 0 || module == NULL || desc == NULL)
437		return(EINVAL);
438
439	offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_IMPORT);
440	if (offset == 0)
441		return (ENOENT);
442
443	imp_desc = (void *)offset;
444
445	while (imp_desc->iid_nameaddr) {
446		modname = (char *)pe_translate_addr(imgbase,
447		    imp_desc->iid_nameaddr);
448		if (!strncmp(module, modname, strlen(module))) {
449			bcopy((char *)imp_desc, (char *)desc,
450			    sizeof(image_import_descriptor));
451			return(0);
452		}
453		imp_desc++;
454	}
455
456	return (ENOENT);
457}
458
459/*
460 * Find the function that matches a particular name. This doesn't
461 * need to be particularly speedy since it's only run when loading
462 * a module for the first time.
463 */
464
465static vm_offset_t
466pe_functbl_match(functbl, name)
467	image_patch_table	*functbl;
468	char			*name;
469{
470	image_patch_table	*p;
471
472	if (functbl == NULL || name == NULL)
473		return(0);
474
475	p = functbl;
476
477	while (p->ipt_name != NULL) {
478		if (!strcmp(p->ipt_name, name))
479			return((uint32_t)p->ipt_func);
480		p++;
481	}
482	printf ("no match for %s\n", name);
483	return((vm_offset_t)p->ipt_func);
484}
485
486/*
487 * Patch the imported function addresses for a given module.
488 * The caller must specify the module name and provide a table
489 * of function pointers that will be patched into the jump table.
490 * Note that there are actually two copies of the jump table: one
491 * copy is left alone. In a .SYS file, the jump tables are usually
492 * merged into the INIT segment.
493 *
494 * Note: Windows uses the _stdcall calling convention. This means
495 * that the callback functions provided in the function table must
496 * be declared using __attribute__((__stdcall__)), otherwise the
497 * Windows code will likely screw up the %esp register and cause
498 * us to jump to an invalid address when it returns.
499 */
500
501int
502pe_patch_imports(imgbase, module, functbl)
503	vm_offset_t		imgbase;
504	char			*module;
505	image_patch_table	*functbl;
506{
507	image_import_descriptor	imp_desc;
508	char			*fname;
509	vm_offset_t		*nptr, *fptr;
510	vm_offset_t		func;
511
512	if (imgbase == 0 || module == NULL || functbl == NULL)
513		return(EINVAL);
514
515	if (pe_get_import_descriptor(imgbase, &imp_desc, module))
516		return(ENOEXEC);
517
518	nptr = (vm_offset_t *)pe_translate_addr(imgbase,
519	    imp_desc.iid_import_name_table_addr);
520	fptr = (vm_offset_t *)pe_translate_addr(imgbase,
521	    imp_desc.iid_import_address_table_addr);
522
523	while (nptr != NULL && pe_translate_addr(imgbase, *nptr) != NULL) {
524		fname = (char *)pe_translate_addr(imgbase, (*nptr) + 2);
525		func = pe_functbl_match(functbl, fname);
526		if (func)
527			*fptr = func;
528#ifdef notdef
529		if (*fptr == 0)
530			return(ENOENT);
531#endif
532		nptr++;
533		fptr++;
534	}
535
536	return(0);
537}
538