~ubuntu-branches/ubuntu/lucid/ndiswrapper/lucid

« back to all changes in this revision

Viewing changes to driver/pe_linker.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2005-11-16 23:39:48 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051116233948-00yddqygl6w65vzg
Tags: 1.5-1ubuntu1
Resynchronise with Debian.  (Totally me!)

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include <string.h>
21
21
#include <linux/types.h>
22
22
#include <asm/errno.h>
 
23
#include <asm/pgtable.h>
23
24
 
24
25
#else
25
26
 
38
39
 
39
40
static struct pe_exports pe_exports[40];
40
41
static int num_pe_exports;
 
42
#if defined(CONFIG_X86_64)
 
43
extern struct kuser_shared_data kuser_shared_data;
 
44
#endif
41
45
 
42
46
#define RVA2VA(image, rva, type) (type)(ULONG_PTR)((void *)image + rva)
43
47
#define CHECK_SZ(a,b) { if (sizeof(a) != b) {                           \
44
48
                        ERROR("%s is bad, got %zd, expected %d",        \
45
49
                              #a , sizeof(a), (b)); return -EINVAL; } }
46
50
 
 
51
#if defined(DEBUGLINKER) && DEBUGLINKER > 0
 
52
#define DBGLINKER(fmt, ...) printk(KERN_INFO "%s (%s:%d): " fmt "\n",   \
 
53
                                   DRIVER_NAME, __FUNCTION__,           \
 
54
                                   __LINE__ , ## __VA_ARGS__);
 
55
static const char *image_directory_name[] = {
 
56
        "EXPORT",
 
57
        "IMPORT",
 
58
        "RESOURCE",
 
59
        "EXCEPTION",
 
60
        "SECURITY",
 
61
        "BASERELOC",
 
62
        "DEBUG",
 
63
        "COPYRIGHT",
 
64
        "GLOBALPTR",
 
65
        "TLS",
 
66
        "LOAD_CONFIG",
 
67
        "BOUND_IMPORT",
 
68
        "IAT",
 
69
        "DELAY_IMPORT",
 
70
        "COM_DESCRIPTOR" };
 
71
#else
 
72
#define DBGLINKER(fmt, ...) do { } while (0)
 
73
#endif
 
74
 
47
75
#ifdef TEST_LOADER
48
76
#define WRAP_EXPORT_FUNC char *
49
77
static WRAP_EXPORT_FUNC get_export(char *name)
51
79
        return name;
52
80
}
53
81
#else
54
 
extern struct wrap_export ntoskernel_exports[], ndis_exports[],
55
 
        misc_funcs_exports[], hal_exports[];
 
82
extern struct wrap_export ntoskernel_exports[], ntoskernel_io_exports[],
 
83
       ndis_exports[], misc_funcs_exports[], hal_exports[];
56
84
#ifdef CONFIG_USB
57
85
extern struct wrap_export usb_exports[];
58
86
#endif
65
93
                if (strcmp(ntoskernel_exports[i].name, name) == 0)
66
94
                        return (char *)ntoskernel_exports[i].func;
67
95
 
 
96
        for (i = 0 ; ntoskernel_io_exports[i].name != NULL; i++)
 
97
                if (strcmp(ntoskernel_io_exports[i].name, name) == 0)
 
98
                        return (char *)ntoskernel_io_exports[i].func;
 
99
 
68
100
        for (i = 0 ; ndis_exports[i].name != NULL; i++)
69
101
                if (strcmp(ndis_exports[i].name, name) == 0)
70
102
                        return (char *)ndis_exports[i].func;
101
133
        return NULL;
102
134
}
103
135
 
104
 
#if DEBUG >= 3
105
 
static const char *image_directory_name[] = {
106
 
        "EXPORT",
107
 
        "IMPORT",
108
 
        "RESOURCE",
109
 
        "EXCEPTION",
110
 
        "SECURITY",
111
 
        "BASERELOC",
112
 
        "DEBUG",
113
 
        "COPYRIGHT",
114
 
        "GLOBALPTR",
115
 
        "TLS",
116
 
        "LOAD_CONFIG",
117
 
        "BOUND_IMPORT",
118
 
        "IAT",
119
 
        "DELAY_IMPORT",
120
 
        "COM_DESCRIPTOR" };
121
 
#endif
122
 
 
123
136
/*
124
137
 * Find and validate the coff header
125
138
 *
190
203
                return -EINVAL;
191
204
        }
192
205
 
193
 
        DBGTRACE1("number of datadictionary entries %d",
 
206
        DBGLINKER("number of datadictionary entries %d",
194
207
                  opt_hdr->NumberOfRvaAndSizes);
195
208
        for (i = 0; i < opt_hdr->NumberOfRvaAndSizes; i++) {
196
 
                DBGTRACE3("datadirectory %s RVA:%X Size:%d",
 
209
                DBGLINKER("datadirectory %s RVA:%X Size:%d",
197
210
                          (i<=IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)?
198
211
                          image_directory_name[i] : "unknown",
199
212
                          opt_hdr->DataDirectory[i].VirtualAddress,
232
245
 
233
246
                adr = get_export(symname);
234
247
                if (adr != NULL)
235
 
                        DBGTRACE1("found symbol: %s:%s, rva = %Lu",
 
248
                        DBGLINKER("found symbol: %s:%s, rva = %Lu",
236
249
                                  dll, symname, (uint64_t)address_tbl[i]);
237
250
                if (adr == NULL) {
238
251
                        ERROR("unknown symbol: %s:%s", dll, symname);
239
252
                        ret = -1;
240
253
                }
241
 
                DBGTRACE1("importing rva: %p, %p: %s : %s",
 
254
                DBGLINKER("importing rva: %p, %p: %s : %s",
242
255
                          (void *)(address_tbl[i]), adr, dll, symname);
243
256
                address_tbl[i] = (ULONG_PTR)adr;
244
257
        }
259
272
                &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
260
273
 
261
274
        if (export_data_dir->Size == 0) {
262
 
                DBGTRACE1("no exports");
 
275
                DBGLINKER("no exports");
263
276
                return 0;
264
277
        }
265
278
 
277
290
                if (export_data_dir->VirtualAddress <= *export_addr_table ||
278
291
                    *export_addr_table >= (export_data_dir->VirtualAddress +
279
292
                                           export_data_dir->Size))
280
 
                        DBGTRACE1("forwarder rva");
 
293
                        DBGLINKER("forwarder rva");
281
294
 
282
 
                DBGTRACE1("export symbol: %s, at %p",
 
295
                DBGLINKER("export symbol: %s, at %p",
283
296
                          (char *)(pe->image + *name_table),
284
297
                          pe->image + *export_addr_table);
285
298
 
313
326
        for (i = 0; dirent[i].Name; i++) {
314
327
                name = RVA2VA(image, dirent[i].Name, char*);
315
328
 
316
 
                DBGTRACE1("imports from dll: %s\n", name);
 
329
                DBGLINKER("imports from dll: %s", name);
317
330
                ret += import(image, &dirent[i], name);
318
331
        }
319
332
        return ret;
336
349
 
337
350
        fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress,
338
351
                             IMAGE_BASE_RELOCATION *);
339
 
        DBGTRACE3("fixup_block=%p, image=%p", fixup_block, image);
340
 
        DBGTRACE3("fixup_block info: %x %d", 
 
352
        DBGLINKER("fixup_block=%p, image=%p", fixup_block, image);
 
353
        DBGLINKER("fixup_block info: %x %d", 
341
354
                  fixup_block->VirtualAddress, fixup_block->SizeOfBlock);
342
355
 
343
356
        while (fixup_block->SizeOfBlock) {
346
359
 
347
360
                size = (fixup_block->SizeOfBlock -
348
361
                        sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
349
 
                DBGTRACE3("found %Lu relocations in this block",
 
362
                DBGLINKER("found %Lu relocations in this block",
350
363
                          (uint64_t)size);
351
364
 
352
365
                for (i = 0; i < size; i++) {
363
376
                                               fixup_block->VirtualAddress +
364
377
                                               offset, uint32_t *);
365
378
                                addr = RVA2VA(image, (*loc - base), uint32_t);
366
 
                                DBGTRACE3("relocation: *%p (Val:%X)= %X",
 
379
                                DBGLINKER("relocation: *%p (Val:%X)= %X",
367
380
                                          loc, *loc, addr);
368
381
                                *loc = addr;
369
382
                        }
376
389
                                               fixup_block->VirtualAddress +
377
390
                                               offset, uint64_t *);
378
391
                                addr = RVA2VA(image, (*loc - base), uint64_t);
379
 
                                DBGTRACE3("relocation: *%p (Val:%llX)= %llx",
 
392
                                DBGLINKER("relocation: *%p (Val:%llX)= %llx",
380
393
                                          loc, *loc, addr);
381
394
                                *loc = addr;
382
395
                        }
389
402
                                break;
390
403
                        }
391
404
                }
392
 
                DBGTRACE1("finished relocating block");
 
405
                DBGLINKER("finished relocating block");
393
406
 
394
407
                fixup_block = (IMAGE_BASE_RELOCATION *)
395
408
                        ((void *)fixup_block + fixup_block->SizeOfBlock);
396
409
        };
397
 
        DBGTRACE1("done relocating all");       
 
410
        DBGLINKER("done relocating all");       
398
411
 
399
412
        return 0;
400
413
}
428
441
#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
429
442
#endif
430
443
#else
431
 
        image = vmalloc(image_size);
 
444
#ifdef cpu_has_nx
 
445
        /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
 
446
         * not available to modules! */
 
447
        if (cpu_has_nx)
 
448
                image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
 
449
                                  __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
 
450
        else
 
451
                image = vmalloc(image_size);
 
452
#else
 
453
                image = vmalloc(image_size);
 
454
#endif
432
455
#endif
433
456
        if (image == NULL) {
434
457
                ERROR("failed to allocate enough space for new image:"
441
464
        sections = pe->nt_hdr->FileHeader.NumberOfSections;
442
465
        sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr);
443
466
 
444
 
        DBGTRACE3("copying headers: %u bytes", sect_hdr->PointerToRawData);
 
467
        DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData);
445
468
 
446
469
        memcpy(image, pe->image, sect_hdr->PointerToRawData);
447
470
 
448
471
        /* Copy all the sections */
449
472
        for (i = 0; i < sections; i++) {
450
 
                DBGTRACE3("Copy section %s from %x to %x",
 
473
                DBGLINKER("Copy section %s from %x to %x",
451
474
                          sect_hdr->Name, sect_hdr->PointerToRawData,
452
475
                          sect_hdr->VirtualAddress);
453
476
                if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData >
472
495
                (pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew);
473
496
        pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
474
497
 
475
 
        DBGTRACE3("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p",
 
498
        DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p",
476
499
                  pe->nt_hdr, pe->opt_hdr, pe->image);
477
500
 
478
501
        return 0;
479
502
}
480
503
 
 
504
#if defined(CONFIG_X86_64)
 
505
void fix_user_shared_data_addr(char *driver, unsigned long length)
 
506
{
 
507
        unsigned long i, n, max_addr, *addr;
 
508
 
 
509
        n = length - sizeof(unsigned long);
 
510
        max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);
 
511
        for (i = 0; i < n; i++) {
 
512
                addr = (unsigned long *)(driver + i);
 
513
                if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {
 
514
                        *addr -= KI_USER_SHARED_DATA;
 
515
                        *addr += (unsigned long)&kuser_shared_data;
 
516
                }
 
517
        }
 
518
}
 
519
#endif
 
520
 
481
521
int load_pe_images(struct pe_image *pe_image, int n)
482
522
{
483
523
        int i;
538
578
                        DBGTRACE1("fixup imports failed");
539
579
                        return -EINVAL;
540
580
                }
 
581
#if defined(CONFIG_X86_64)
 
582
                INFO("fixing KI_USER_SHARED_DATA address in the driver");
 
583
                fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size);
 
584
#endif
541
585
                flush_icache_range(pe->image, pe->size);
542
586
 
543
587
                pe->entry =