2
* Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
18
#include "usr_linker.h"
22
#include <linux/types.h>
23
#include <asm/errno.h>
25
//#define DEBUGLINKER 2
27
#include "ntoskernel.h"
37
static struct pe_exports pe_exports[40];
38
static int num_pe_exports;
40
#define RVA2VA(image, rva, type) (type)(ULONG_PTR)((void *)image + rva)
41
#define CHECK_SZ(a,b) { if (sizeof(a) != b) { \
42
ERROR("%s is bad, got %zd, expected %d", \
43
#a , sizeof(a), (b)); return -EINVAL; } }
45
#if defined(DEBUGLINKER) && DEBUGLINKER > 0
46
#define DBGLINKER(fmt, ...) printk(KERN_INFO "%s (%s:%d): " fmt "\n", \
47
DRIVER_NAME, __func__, \
48
__LINE__ , ## __VA_ARGS__);
49
static const char *image_directory_name[] = {
66
#define DBGLINKER(fmt, ...) do { } while (0)
70
extern struct wrap_export ntoskernel_exports[], ntoskernel_io_exports[],
71
ndis_exports[], crt_exports[], hal_exports[], rtl_exports[];
73
extern struct wrap_export usb_exports[];
76
static int get_export(char *name, generic_func *func)
80
struct wrap_export *exports[] = {
82
ntoskernel_io_exports,
92
for (j = 0; j < ARRAY_SIZE(exports); j++)
93
for (i = 0; exports[j][i].name != NULL; i++)
94
if (strcmp(exports[j][i].name, name) == 0) {
95
*func = exports[j][i].func;
99
for (i = 0; i < num_pe_exports; i++)
100
if (strcmp(pe_exports[i].name, name) == 0) {
101
*func = pe_exports[i].addr;
107
#endif // TEST_LOADER
109
static void *get_dll_init(char *name)
112
for (i = 0; i < num_pe_exports; i++)
113
if ((strcmp(pe_exports[i].dll, name) == 0) &&
114
(strcmp(pe_exports[i].name, "DllInitialize") == 0))
115
return (void *)pe_exports[i].addr;
120
* Find and validate the coff header
123
static int check_nt_hdr(IMAGE_NT_HEADERS *nt_hdr)
127
PIMAGE_OPTIONAL_HEADER opt_hdr;
129
/* Validate the "PE\0\0" signature */
130
if (nt_hdr->Signature != IMAGE_NT_SIGNATURE) {
131
ERROR("is this driver file? bad signature %08x",
136
opt_hdr = &nt_hdr->OptionalHeader;
137
/* Make sure Image is PE32 or PE32+ */
139
if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
140
ERROR("kernel is 64-bit, but Windows driver is not 64-bit;"
141
"bad magic: %04X", opt_hdr->Magic);
145
if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
146
ERROR("kernel is 32-bit, but Windows driver is not 32-bit;"
147
"bad magic: %04X", opt_hdr->Magic);
152
/* Validate the image for the current architecture. */
154
if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
155
ERROR("kernel is 64-bit, but Windows driver is not 64-bit;"
156
" (PE signature is %04X)", nt_hdr->FileHeader.Machine);
160
if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
161
ERROR("kernel is 32-bit, but Windows driver is not 32-bit;"
162
" (PE signature is %04X)", nt_hdr->FileHeader.Machine);
167
/* Must have attributes */
169
attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE;
171
attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE;
173
if ((nt_hdr->FileHeader.Characteristics & attr) != attr)
176
/* Must be relocatable */
177
attr = IMAGE_FILE_RELOCS_STRIPPED;
178
if ((nt_hdr->FileHeader.Characteristics & attr))
181
/* Make sure we have at least one section */
182
if (nt_hdr->FileHeader.NumberOfSections == 0)
185
if (opt_hdr->SectionAlignment < opt_hdr->FileAlignment) {
186
ERROR("alignment mismatch: secion: 0x%x, file: 0x%x",
187
opt_hdr->SectionAlignment, opt_hdr->FileAlignment);
191
DBGLINKER("number of datadictionary entries %d",
192
opt_hdr->NumberOfRvaAndSizes);
193
for (i = 0; i < opt_hdr->NumberOfRvaAndSizes; i++) {
194
DBGLINKER("datadirectory %s RVA:%X Size:%d",
195
(i<=IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)?
196
image_directory_name[i] : "unknown",
197
opt_hdr->DataDirectory[i].VirtualAddress,
198
opt_hdr->DataDirectory[i].Size);
201
if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
202
return IMAGE_FILE_EXECUTABLE_IMAGE;
203
if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_DLL))
204
return IMAGE_FILE_DLL;
208
static int import(void *image, IMAGE_IMPORT_DESCRIPTOR *dirent, char *dll)
210
ULONG_PTR *lookup_tbl, *address_tbl;
211
char *symname = NULL;
216
lookup_tbl = RVA2VA(image, dirent->u.OriginalFirstThunk, ULONG_PTR *);
217
address_tbl = RVA2VA(image, dirent->FirstThunk, ULONG_PTR *);
219
for (i = 0; lookup_tbl[i]; i++) {
220
if (IMAGE_SNAP_BY_ORDINAL(lookup_tbl[i])) {
221
ERROR("ordinal import not supported: %Lu",
222
(uint64_t)lookup_tbl[i]);
226
symname = RVA2VA(image,
228
~IMAGE_ORDINAL_FLAG) + 2), char *);
231
ret = get_export(symname, &adr);
233
ERROR("unknown symbol: %s:'%s'", dll, symname);
235
DBGLINKER("found symbol: %s:%s: addr: %p, rva = %Lu",
236
dll, symname, adr, (uint64_t)address_tbl[i]);
237
address_tbl[i] = (ULONG_PTR)adr;
243
static int read_exports(struct pe_image *pe)
245
IMAGE_EXPORT_DIRECTORY *export_dir_table;
246
uint32_t *export_addr_table;
248
uint32_t *name_table;
249
PIMAGE_OPTIONAL_HEADER opt_hdr;
250
IMAGE_DATA_DIRECTORY *export_data_dir;
252
opt_hdr = &pe->nt_hdr->OptionalHeader;
254
&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
256
if (export_data_dir->Size == 0) {
257
DBGLINKER("no exports");
262
RVA2VA(pe->image, export_data_dir->VirtualAddress,
263
IMAGE_EXPORT_DIRECTORY *);
265
name_table = (unsigned int *)(pe->image +
266
export_dir_table->AddressOfNames);
267
export_addr_table = (uint32_t *)
268
(pe->image + export_dir_table->AddressOfFunctions);
270
for (i = 0; i < export_dir_table->NumberOfNames; i++) {
272
if (export_data_dir->VirtualAddress <= *export_addr_table ||
273
*export_addr_table >= (export_data_dir->VirtualAddress +
274
export_data_dir->Size))
275
DBGLINKER("forwarder rva");
277
DBGLINKER("export symbol: %s, at %p",
278
(char *)(pe->image + *name_table),
279
pe->image + *export_addr_table);
281
pe_exports[num_pe_exports].dll = pe->name;
282
pe_exports[num_pe_exports].name = pe->image + *name_table;
283
pe_exports[num_pe_exports].addr =
284
pe->image + *export_addr_table;
293
static int fixup_imports(void *image, IMAGE_NT_HEADERS *nt_hdr)
298
IMAGE_IMPORT_DESCRIPTOR *dirent;
299
IMAGE_DATA_DIRECTORY *import_data_dir;
300
PIMAGE_OPTIONAL_HEADER opt_hdr;
302
opt_hdr = &nt_hdr->OptionalHeader;
304
&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
305
dirent = RVA2VA(image, import_data_dir->VirtualAddress,
306
IMAGE_IMPORT_DESCRIPTOR *);
308
for (i = 0; dirent[i].Name; i++) {
309
name = RVA2VA(image, dirent[i].Name, char*);
311
DBGLINKER("imports from dll: %s", name);
312
ret += import(image, &dirent[i], name);
317
static int fixup_reloc(void *image, IMAGE_NT_HEADERS *nt_hdr)
321
IMAGE_BASE_RELOCATION *fixup_block;
322
IMAGE_DATA_DIRECTORY *base_reloc_data_dir;
323
PIMAGE_OPTIONAL_HEADER opt_hdr;
325
opt_hdr = &nt_hdr->OptionalHeader;
326
base = opt_hdr->ImageBase;
327
base_reloc_data_dir =
328
&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
329
if (base_reloc_data_dir->Size == 0)
332
fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress,
333
IMAGE_BASE_RELOCATION *);
334
DBGLINKER("fixup_block=%p, image=%p", fixup_block, image);
335
DBGLINKER("fixup_block info: %x %d",
336
fixup_block->VirtualAddress, fixup_block->SizeOfBlock);
338
while (fixup_block->SizeOfBlock) {
342
size = (fixup_block->SizeOfBlock -
343
sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
344
DBGLINKER("found %Lu relocations in this block",
347
for (i = 0; i < size; i++) {
348
fixup = fixup_block->TypeOffset[i];
349
offset = fixup & 0xfff;
350
switch ((fixup >> 12) & 0x0f) {
351
case IMAGE_REL_BASED_ABSOLUTE:
354
case IMAGE_REL_BASED_HIGHLOW: {
358
fixup_block->VirtualAddress +
360
addr = RVA2VA(image, (*loc - base), uint32_t);
361
DBGLINKER("relocation: *%p (Val:%X)= %X",
367
case IMAGE_REL_BASED_DIR64: {
371
fixup_block->VirtualAddress +
373
addr = RVA2VA(image, (*loc - base), uint64_t);
374
DBGLINKER("relocation: *%p (Val:%llX)= %llx",
381
ERROR("unknown fixup: %08X",
382
(fixup >> 12) & 0x0f);
387
DBGLINKER("finished relocating block");
389
fixup_block = (IMAGE_BASE_RELOCATION *)
390
((void *)fixup_block + fixup_block->SizeOfBlock);
392
DBGLINKER("done relocating all");
397
/* Expand the image in memroy if necessary. The image on disk does not
398
* necessarily maps the image of the driver in memory, so we have to
399
* re-write it in order to fullfill the sections alignements. The
400
* advantage to do that is that rva_to_va becomes a simple
402
static int fix_pe_image(struct pe_image *pe)
405
IMAGE_SECTION_HEADER *sect_hdr;
409
if (pe->size == pe->opt_hdr->SizeOfImage) {
414
image_size = pe->opt_hdr->SizeOfImage;
416
#ifdef PAGE_KERNEL_EXECUTABLE
417
image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
418
PAGE_KERNEL_EXECUTABLE);
419
#elif defined PAGE_KERNEL_EXEC
420
image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
423
#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
427
/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
428
* not available to modules! */
430
image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
431
__pgprot(__PAGE_KERNEL & ~_PAGE_NX));
433
image = vmalloc(image_size);
435
image = vmalloc(image_size);
439
ERROR("failed to allocate enough space for new image:"
440
" %d bytes", image_size);
444
/* Copy all the headers, ie everything before the first section. */
446
sections = pe->nt_hdr->FileHeader.NumberOfSections;
447
sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr);
449
DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData);
451
memcpy(image, pe->image, sect_hdr->PointerToRawData);
453
/* Copy all the sections */
454
for (i = 0; i < sections; i++) {
455
DBGLINKER("Copy section %s from %x to %x",
456
sect_hdr->Name, sect_hdr->PointerToRawData,
457
sect_hdr->VirtualAddress);
458
if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData >
460
ERROR("Invalid section %s in driver", sect_hdr->Name);
465
memcpy(image+sect_hdr->VirtualAddress,
466
pe->image + sect_hdr->PointerToRawData,
467
sect_hdr->SizeOfRawData);
473
pe->size = image_size;
475
/* Update our internal pointers */
476
pe->nt_hdr = (IMAGE_NT_HEADERS *)
477
(pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew);
478
pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
480
DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p",
481
pe->nt_hdr, pe->opt_hdr, pe->image);
486
#if defined(CONFIG_X86_64)
487
static void fix_user_shared_data_addr(char *driver, unsigned long length)
489
unsigned long i, n, max_addr, *addr;
491
n = length - sizeof(unsigned long);
492
max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);
493
for (i = 0; i < n; i++) {
494
addr = (unsigned long *)(driver + i);
495
if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {
496
*addr -= KI_USER_SHARED_DATA;
497
*addr += (unsigned long)&kuser_shared_data;
498
kuser_shared_data.reserved1 = 1;
504
int link_pe_images(struct pe_image *pe_image, unsigned short n)
510
/* Sanity checkings */
511
CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER);
512
CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER);
513
CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
514
CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER +
515
IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
516
CHECK_SZ(IMAGE_DOS_HEADER, 0x40);
517
CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40);
518
CHECK_SZ(IMAGE_BASE_RELOCATION, 8);
519
CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20);
522
for (i = 0; i < n; i++) {
523
IMAGE_DOS_HEADER *dos_hdr;
527
if (pe->size < sizeof(IMAGE_DOS_HEADER)) {
528
TRACE1("image too small: %d", pe->size);
533
(IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew);
534
pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
536
pe->type = check_nt_hdr(pe->nt_hdr);
542
if (fix_pe_image(pe)) {
543
TRACE1("bad PE image");
547
if (read_exports(pe)) {
548
TRACE1("read exports failed");
553
for (i = 0; i < n; i++) {
556
if (fixup_reloc(pe->image, pe->nt_hdr)) {
557
TRACE1("fixup reloc failed");
560
if (fixup_imports(pe->image, pe->nt_hdr)) {
561
TRACE1("fixup imports failed");
564
#if defined(CONFIG_X86_64)
565
INFO("fixing KI_USER_SHARED_DATA address in the driver");
566
fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size);
568
flush_icache_range(pe->image, pe->size);
572
pe->opt_hdr->AddressOfEntryPoint, void *);
573
TRACE1("entry is at %p, rva at %08X", pe->entry,
574
pe->opt_hdr->AddressOfEntryPoint);
577
for (i = 0; i < n; i++) {
580
if (pe->type == IMAGE_FILE_DLL) {
581
struct unicode_string ustring;
582
char *buf = "0/0t0m0p00";
583
int (*dll_entry)(struct unicode_string *ustring)
586
memset(&ustring, 0, sizeof(ustring));
587
ustring.buf = (wchar_t *)buf;
588
dll_entry = (void *)get_dll_init(pe->name);
590
TRACE1("calling dll_init at %p", dll_entry);
591
if (!dll_entry || dll_entry(&ustring))
592
ERROR("DLL initialize failed for %s",
595
else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE)
596
ERROR("illegal image type: %d", pe->type);