Subversion Repositories shark

Rev

Rev 1051 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1051 tullio 1
////////////////////////////////////////////////////////////////////////
2
//      dynalink.c
3
//
4
//  DynaLink for S.H.A.R.K
5
//  Dynamic ELF object linker.
6
//  
7
//  Original code written by Luca Abeni.
8
//  Adapted by Lex Nahumury 19-7-2006.
9
//  
10
//  This is free software; see GPL.txt
11
//////////////////////////////////////////////////////////////////////// 
12
 
13
#include "kernel/kern.h"
14
#include <kernel/func.h>
15
#include <stdlib.h>
16
#include <stdio.h>
17
#include <string.h>
18
#include <math.h>
19
 
20
#include <ll/i386/hw-data.h>
21
#include <ll/i386/mem.h>
22
#include <ll/i386/hw-instr.h>
23
#include <ll/i386/cons.h>
24
#include <ll/i386/error.h>
25
#include <ll/i386/mem.h>
1689 fabio 26
#include <arch/ctype.h>
1051 tullio 27
#include <ll/i386/x-bios.h>
28
 
29
#include "format.h"
30
#include "dynalink.h"
31
#include "elf.h"
32
 
33
#include <drivers/shark_linuxc26.h>
34
#include <drivers/shark_pci26.h>
35
#include <drivers/shark_input26.h>
36
#include <drivers/shark_keyb26.h>
37
 
38
// some shark pci forward declaration stuff (pci20to26.c)
39
extern int pci20to26_find_class(unsigned int class_code, int index, BYTE *bus, BYTE *dev);
40
extern int pci20to26_read_config_byte(unsigned int bus, unsigned int dev, int where, BYTE *val);
41
extern int pci20to26_read_config_word(unsigned int bus, unsigned int dev, int where, WORD *val);
42
extern int pci20to26_read_config_dword(unsigned int bus, unsigned int dev, int where, DWORD *val);
43
extern int pci20to26_write_config_byte(unsigned int bus, unsigned int dev, int where, BYTE val);
44
extern int pci20to26_write_config_word(unsigned int bus, unsigned int dev, int where, WORD val);
45
extern int pci20to26_write_config_dword(unsigned int bus, unsigned int dev, int where, DWORD val);
46
 
47
 
48
#define __DYNA_DEBUG__
49
#define NORMAL_PROCESS  0
50
#define EMPTY_SLOT {0, (DWORD)0xFFFFFFFF}
51
#define SUBSTITUTE 1
52
#define ADD 0
53
 
54
 
55
static struct file_ops  kf;
56
static DWORD start;
57
static DWORD end;
58
static DWORD pointer;
59
 
60
 
61
//A module can also export symbols by adding them to the kernel symbol table
62
int add_call(char *name, DWORD address, int mode);
63
 
64
// forward declarations of some custom 'syscalls'...
65
extern void call_shutdown_task(void *arg);
66
extern DWORD get_tick();
67
 
68
static struct symbol syscall_table[] = {
69
        // console & string
70
        { "cprintf", (DWORD)cprintf },
71
        { "sprintf", (DWORD)sprintf },
72
        { "printk", (DWORD)printk },
73
        { "printf_xy", (DWORD)printf_xy },
74
        { "puts_xy", (DWORD)puts_xy },
75
        { "place", (DWORD)place },
76
        { "_clear", (DWORD)_clear },   
77
        { "clear", (DWORD)clear },     
78
        { "strcpy", (DWORD)strcpy },   
79
        // keyboard
80
        { "keyb_getch", (DWORD)keyb_getch },
81
        { "keyb_getcode", (DWORD)keyb_getcode },
82
        // math
83
        { "sin", (DWORD)sin },
84
        { "cos", (DWORD)cos },
85
        { "pow", (DWORD)pow },
86
        { "abs", (DWORD)abs }, 
87
        // memory
88
        { "malloc",  (DWORD)malloc },
89
        { "kern_alloc_aligned",  (DWORD)kern_alloc_aligned },
90
        { "free",  (DWORD)free },
91
        // I/O
92
        { "inp",  (DWORD)inp },
93
        { "inpw",  (DWORD)inpw },
94
        { "inpd",  (DWORD)inpd },
95
        // pci
96
        { "pci20to26_read_config_byte",  (DWORD)pci20to26_read_config_byte },
97
        { "pci20to26_read_config_word",  (DWORD)pci20to26_read_config_word },
98
        { "pci20to26_read_config_dword",  (DWORD)pci20to26_read_config_dword },
99
        { "pci20to26_write_config_byte",  (DWORD)pci20to26_write_config_byte },
100
        { "pci20to26_write_config_word",  (DWORD)pci20to26_write_config_word },
101
        { "pci20to26_write_config_dword",  (DWORD)pci20to26_write_config_dword },
102
        // task managment
103
        { "task_testcancel",  (DWORD)task_testcancel },
104
        { "task_message",  (DWORD)task_message },
105
        { "task_createn",  (DWORD)task_createn },
106
        { "task_activate",  (DWORD)task_activate },
107
        { "handler_set",  (DWORD)handler_set },
108
        { "task_nopreempt",  (DWORD)task_nopreempt },
109
        { "task_preempt",  (DWORD)task_preempt },      
110
        { "group_activate",  (DWORD)group_activate },
111
        // Time & termination
112
        { "sys_gettime",  (DWORD)sys_gettime },
113
        { "get_tick",  (DWORD)get_tick },
114
        { "perror",  (DWORD)perror },
115
        { "exit",  (DWORD)exit },
116
        { "call_shutdown_task",  (DWORD)call_shutdown_task },
117
        { "sys_shutdown_message",  (DWORD)sys_shutdown_message },      
118
        { "add_call", (DWORD)add_call }, //module can add symbol to the kernel symbol table     
119
        EMPTY_SLOT,
120
        EMPTY_SLOT,
121
        EMPTY_SLOT,
122
        EMPTY_SLOT,
123
        EMPTY_SLOT,
124
        EMPTY_SLOT,
125
        EMPTY_SLOT,
126
        EMPTY_SLOT,
127
        EMPTY_SLOT,
128
        EMPTY_SLOT,
129
        EMPTY_SLOT,
130
        EMPTY_SLOT,
131
        EMPTY_SLOT,
132
        EMPTY_SLOT,
133
        EMPTY_SLOT,
134
        EMPTY_SLOT,
135
        EMPTY_SLOT,
136
        EMPTY_SLOT,
137
        EMPTY_SLOT,
138
        EMPTY_SLOT,  
139
        {0, 0}
140
};
141
 
142
void *get_syscall_table(void)
143
{
144
  return syscall_table;
145
};
146
 
147
int add_call(char *name, DWORD address, int mode)
148
{
149
  int i;
150
  int done;
151
  int res;
152
 
153
  i = 0;
154
  done = 0;
155
  while ((!done) && (syscall_table[i].address != 0)) {
156
    if (!strcmp(syscall_table[i].name, name)) {
157
      done = 1;
158
    } else {
159
      i++;
160
    }
161
  }
162
 
163
  if (done == 1) {
164
    if (mode == SUBSTITUTE) {
165
      res = syscall_table[i].address;
166
      syscall_table[i].name = name;
167
      syscall_table[i].address = address;
168
    } else {
169
      return -1;
170
    }
171
  } else {
172
    if (mode == SUBSTITUTE) {
173
      return -1;
174
    } else {
175
      i = 0;
176
      while (syscall_table[i].name != 0) {
177
        i++;
178
      }
179
 
180
      if (syscall_table[i].address != 0xFFFFFFFF) {
181
        return -1;
182
      }
183
      res = 1;
184
      syscall_table[i].name = name;
185
      syscall_table[i].address = address;    
186
    }
187
  }
188
 
189
  return res;
190
};
191
 
192
 
193
 
194
static DWORD load_process(struct file_ops *kf,                         
195
                                                DWORD *ex_exec_space,
196
                                                DWORD *image_base,
197
                                                DWORD *ex_size)
198
{      
199
  #ifdef __EXEC_DEBUG__
200
  DWORD offset;
201
  #endif
202
 
203
  DWORD size;
204
  DWORD exec_space=0;
205
  int bss_sect, i;
206
  DWORD dyn_entry;
207
  struct section_info   *sections;
208
  struct symbol_info    *symbols = NULL;
209
  struct table_info             tables;
210
 
211
  // Initialize the table info
212
  tables.section_names_size = 0;
213
  tables.local_bss_size = 0;
214
  tables.private_info = 0;
215
 
216
  // read ELF headers
217
  dyn_entry = ELF_read_headers(kf, &tables);  
218
 
219
  sections = (struct section_info*)malloc(sizeof(struct section_info) * tables.num_sections);
220
  if(sections == 0)
221
  {
222
    printk("Can't allocate the sections info!\n");    
223
    return -1;
224
  }
225
 
226
  // read ELF section headers
227
  bss_sect = ELF_read_section_headers(kf, &tables, sections);
228
 
229
 
230
  // Load symbols (if it's objects, calculate the local bss size)
231
  if(tables.num_symbols != 0)
232
  {
233
    symbols = (struct symbol_info*)malloc(tables.num_symbols * sizeof (struct symbol_info));
234
    if (symbols == 0)
235
        {
236
      error("Error allocating symbols table\n");
237
      ELF_free_tables(kf, &tables, symbols, sections);
238
      return -1;
239
    }
240
 
241
        // read ELF symbols
242
    ELF_read_symbols(kf, &tables, symbols);
243
  }
244
 
245
  if(tables.flags & NEED_LOAD_RELOCATABLE)
246
  {    
247
        #ifdef __EXEC_DEBUG__
248
        printk("[EXEC]Must load_relocatable()!\n");
249
        #endif
250
    exec_space = ELF_load_relocatable(kf, &tables, tables.num_sections, sections, &size);
251
  }
252
  if(exec_space == 0)
253
  {
254
    printk("Error decoding the Executable data\n");
255
    ELF_free_tables(kf, &tables, symbols, sections);
256
    return -1;
257
  }
258
 
259
 
260
  if(tables.flags & (NEED_SECTION_RELOCATION|NEED_IMAGE_RELOCATION))
261
  {
262
    int res;
263
    void *kernel_symbols;
264
    int reloc_sections;
265
 
266
    if (tables.flags & NEED_SECTION_RELOCATION)
267
        {
268
      if ((bss_sect < 0) || (bss_sect > tables.num_sections))
269
          {
270
        error("Error: strange file --- no BSS section\n");
271
        /* TODO: Return code... */
272
        ELF_free_tables(kf, &tables, symbols, sections);
273
                free((DWORD*)exec_space);
274
        return -1;
275
      }
276
    }
277
        #ifdef __EXEC_DEBUG__
278
    printk("[EXEC] Start of local BSS: 0x%lx\n", tables.private_info);
279
        #endif
280
 
281
    kernel_symbols = get_syscall_table();
282
 
283
    if(tables.flags & NEED_SECTION_RELOCATION)
284
        {
285
      reloc_sections = tables.num_sections;
286
    } else
287
        {
288
      reloc_sections = 1;
289
    }
290
 
291
        #ifdef __EXEC_DEBUG__
292
        printk("[EXEC] reloc_sections = %d\n", reloc_sections);
293
        #endif
294
 
295
        // Relocate sections...
296
    for (i=0; i<reloc_sections; i++)
297
        {
298
      res = ELF_relocate_section(kf,
299
                                                                exec_space,
300
                                                                &tables,
301
                                                                tables.num_sections,
302
                                                                sections,
303
                                                                i,
304
                                                                symbols,
305
                                                                kernel_symbols);
306
      if(res < 0)
307
          {
308
        error("Error: relocation failed!!!\n");
309
        /* TODO: Return code... */
310
        ELF_free_tables(kf, &tables, symbols, sections);
311
                free((DWORD*)exec_space);
312
        return -1;
313
      }
314
    }  
315
  }
316
 
317
  /* The size of the execution space */
318
  *ex_size = size;
319
 
320
  if(tables.flags & NO_ENTRY)
321
  {
322
    int init_sect;
323
    /* No entry point... We assume that we need dynamic linking */       
324
        #ifdef __EXEC_DEBUG__
325
    printk("[EXEC] Searching for the initialization function...\n");
326
        #endif
327
    if(symbols == 0)
328
        {
329
      error("Error: no symbols!!!\n");
330
      /* TODO: Return code... */
331
      ELF_free_tables(kf, &tables, symbols, sections);
332
          free((DWORD*)exec_space);
333
      return -1;
334
    }  
335
 
336
        // Find the main entry point. Function name ends with kf->entry_name...
337
        //dyn_entry = (DWORD)ELF_import_symbol(kf, tables.num_symbols, symbols, DYN_ENTRY_NAME, &init_sect);
338
        dyn_entry = (DWORD)ELF_import_symbol(kf, tables.num_symbols, symbols, kf->entry_name, &init_sect);
339
 
340
    if(init_sect != -1)
341
        {
342
          #ifdef __EXEC_DEBUG__
343
      printk("Found: (%d =  0x%x) 0x%lx\n", init_sect,
344
                                                                                        init_sect, dyn_entry);
345
      printk("Section Base: 0x%lx   Exec Space: 0x%lx\n",
346
                                                                                sections[init_sect].base, exec_space);
347
          #endif
348
      dyn_entry += sections[init_sect].base + exec_space;
349
      *image_base = exec_space;
350
      *ex_exec_space = 0;
351
      ELF_free_tables(kf, &tables, symbols, sections);
352
      return dyn_entry;
353
    }
354
        else
355
        {
356
      printk("WARNING: Initialization function not found!\n");
357
      return -1;
358
    }
359
  }
360
 return -1; // error
361
};
362
 
363
 
364
 
365
// Read an ELF object in memory, and return it's main entry function's address..
366
static DWORD get_exec_address(  struct file_ops *kf )
367
{      
368
        DWORD exec_space;
369
        DWORD image_base;
370
        DWORD ex_size;
371
        DWORD dyn_entry;
372
 
373
        dyn_entry = load_process(       kf,                                            
374
                                                                &exec_space,
375
                                                                &image_base,
376
                                                                &ex_size);
377
 
378
        if(dyn_entry== -1)    return 0;
379
 return dyn_entry;
380
};
381
 
382
/*
383
static char *module_command_line(DWORD mods_addr, int i)
384
{
385
  struct mods_struct *curr_mod;
386
  curr_mod = (struct mods_struct *)mods_addr;
387
  return curr_mod[i].string;
388
};
389
 
390
static void module_address(DWORD mods_addr, int i, DWORD *start, DWORD *end)
391
{
392
  struct mods_struct *curr_mod;
393
  curr_mod = (struct mods_struct *)mods_addr;
394
  *start = (DWORD)curr_mod[i].mod_start;
395
  *end = (DWORD)curr_mod[i].mod_end;
396
};
397
*/
398
 
399
static int modfs_read( void *buff, int size)
400
{
401
  int len = size;
402
  if(pointer + len > end)
403
  {
404
    len = end - pointer;
405
  }
406
  memcpy(buff, (void *)pointer, len);
407
  pointer += len;
408
  return len;
409
};
410
 
411
 
412
static int modfs_seek( int pos, int wence)
413
{
414
  int res;
415
 
416
  if(wence == 0)
417
  {
418
    res = pos;
419
  }
420
  else if(wence == 1)
421
  {
422
    res = pointer + pos - start;
423
  }
424
  else if(wence == 2)
425
  {
426
    if(end - start < pos) res = 0;
427
        else res = end - start - pos;
428
  }
429
  else  res = pointer - start;
430
 
431
  if(start + res > end) res = end - start;
432
 
433
  pointer = start + res;
434
 
435
  return res;
436
};
437
 
438
// This will process all modules and fill out a dynalink_module_list.
439
// We only support valid ELF objects.
440
// Everything else is treated as DATA.
441
int dynalink_modules(struct multiboot_info* mb,
442
                                        struct dynalink_module_list* dml,
443
                                        char* search_string)
444
{
445
        int i;
446
        DWORD dyn_entry;
447
 
448
        int mods_addr   = mb->mods_addr;
449
        int mods_count  = mb->mods_count;      
450
 
451
        // Initialize the Modules Pseudo-FS...  
452
        kf.file_seek = modfs_seek;
453
        kf.file_read = modfs_read;
454
        kf.entry_name = search_string;
455
        kf.seek_set = 0;
456
        kf.seek_cur = 1;
457
 
458
        // check all modules..
459
        for(i = 0; i < mods_count; i++)
460
        {
461
                #ifdef __DYNA_DEBUG__
462
                printk("[MOD] Process Module #%d:", i);
463
                #endif
464
 
465
                kf.file_offset = 0;
466
 
467
                // Pseudo-FS open               
468
                struct mods_struct* curr_mod = (struct mods_struct*)mods_addr;
469
                start = (DWORD)curr_mod[i].mod_start;
470
                end = (DWORD)curr_mod[i].mod_end;              
471
                pointer = start;
472
 
473
                if( Elf_check(&kf) )
474
                {      
475
                        // Try to Link the ELF module and get it's main_entry address
476
                        dyn_entry = get_exec_address( &kf );                   
477
                        if(dyn_entry)
478
                        {
479
                                int j = dml->num_apps;
480
                                dml->app[j].dyn_entry   = dyn_entry;
481
                                dml->app[j].start               = start;
482
                                dml->app[j].end                 = end;
483
                                dml->app[j].size                = end - start;
484
                                dml->app[j].name                = curr_mod[i].string;
485
                                #ifdef __DYNA_DEBUG__   
486
                                printk(" ELF object :%s [%d bytes]\n",
487
                                                dml->app[j].name, dml->app[j].size);
488
                                #endif
489
                                ++dml->num_apps;
490
                        }
491
                        else // add it as 'Data' module
492
                        {
493
                                int j = dml->num_dats;                 
494
                                dml->dat[j].start       = start;
495
                                dml->dat[j].end         = end;
496
                                dml->dat[j].size        = end - start;
497
                                dml->dat[j].name        = curr_mod[i].string;
498
                                #ifdef __DYNA_DEBUG__   
499
                                printk(" Data object :%s [%d bytes]\n",
500
                                                dml->dat[j].name, dml->dat[j].size);
501
                                #endif                          
502
                                ++dml->num_dats;
503
                        }
504
                }
505
                else // it is a 'Data' module
506
                {
507
                        int j = dml->num_dats;         
508
                        dml->dat[j].start       = start;
509
                        dml->dat[j].end         = end;
510
                        dml->dat[j].size        = end - start;
511
                        dml->dat[j].name        = curr_mod[i].string;
512
                        #ifdef __DYNA_DEBUG__   
513
                        printk(" Data object :%s [%d bytes]\n",
514
                                        dml->dat[j].name, dml->dat[j].size);
515
                        #endif                                  
516
                        ++dml->num_dats;
517
                }
518
 
519
                //TODO: ? mem_release_module(mods_addr, i, mods_count);
520
        }
521
return 0;
522
};
523
 
524
 
525
 
526
/*
527
// TODO: haven't finished this yet for SHARK [Lex]
528
void mem_release_module(DWORD mstart, int m, int mnum)
529
{
530
  DWORD ms, nms, me, ms1, dummy;
531
  int i;
532
 
533
  module_address(mstart, m, &ms, &me);
534
  nms = 0;
535
  for (i = 0; i < mnum; i++)
536
  {
537
    module_address(mstart, i, &ms1, &dummy);
538
    if(nms == 0)
539
        {
540
      if(ms1 >= me) nms = ms1;
541
    }
542
        else
543
        {
544
      if((ms1 >= me) && (ms1 < nms))  nms = ms1;  
545
    }
546
  }
547
 
548
  if (nms == 0)  nms = me;
549
 
550
#ifdef __MEM_DEBUG__
551
  printk("releasing %lx - %lx\n", ms, nms);
552
#endif
553
 
554
  //pmm_add_region(&high_mem_pool, ms, nms - ms);
555
 
556
 
557
};
558
*/
559