/shark/trunk/ports/dynalink/dynalink.h |
---|
0,0 → 1,61 |
//////////////////////////////////////////////////////////////////////// |
// dynalink.h |
// |
// DynaLink for S.H.A.R.K |
// Dynamic ELF object linker. |
// |
// Original code written by Luca Abeni. |
// Adapted by Lex Nahumury 19-7-2006. |
// |
// This is free software; see GPL.txt |
//////////////////////////////////////////////////////////////////////// |
#ifndef _DYNALINK_H_ |
#define _DYNALINK_H_ |
#define MAX_DYNA_MOD 64 |
struct mods_struct |
{ |
void *mod_start; |
void *mod_end; |
char *string; |
DWORD reserved; |
}; |
struct app_module_info |
{ |
unsigned int start; // the memory used goes from bytes 'mod_start' |
unsigned int end; // to 'mod_end-1' inclusive |
unsigned int size; // size in bytes |
unsigned int dyn_entry; // main_module_entry() start address |
char* name; // file name |
}; |
struct dat_module_info |
{ |
unsigned int start; // the memory used goes from bytes 'mod_start' |
unsigned int end; // to 'mod_end-1' inclusive. |
unsigned int size; // in bytes |
char *name; // file name |
}; |
struct dynalink_module_list |
{ |
int num_apps; // number of loaded ELF objects |
int num_dats; // number of loaded Data object |
struct app_module_info app[MAX_DYNA_MOD]; // aplications in mem |
struct dat_module_info dat[MAX_DYNA_MOD]; // data file in mem |
}; |
int dynalink_modules( struct multiboot_info* mb, |
struct dynalink_module_list* dml, |
char* search_string); |
#endif //_DYNALINK_H_ |
/shark/trunk/ports/dynalink/elf.c |
---|
0,0 → 1,708 |
//////////////////////////////////////////////////////////////////////// |
// elf.c |
// |
// DynaLink for S.H.A.R.K |
// Dynamic ELF object linker. |
// |
// Original code written by Luca Abeni. |
// Adapted by Lex Nahumury 19-7-2006. |
// |
// This is free software; see GPL.txt |
//////////////////////////////////////////////////////////////////////// |
#include "kernel/kern.h" |
#include <kernel/func.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <math.h> |
#include <ll/i386/hw-data.h> |
#include <ll/i386/mem.h> |
#include <ll/i386/hw-instr.h> |
#include <ll/i386/cons.h> |
#include <ll/i386/error.h> |
#include <ll/i386/mem.h> |
#include <ll/ctype.h> |
#include <ll/i386/x-bios.h> |
#include "format.h" |
#include "elf.h" |
//#define __ELF_DEBUG__ |
char elf_signature[] = "\177ELF"; |
DWORD ELF_read_headers( struct file_ops *kf, |
struct table_info *tables) |
{ |
//printk("ELF_read_headers\n"); |
int res; |
DWORD entry; |
struct elf_header header; |
struct elf_section_header h; |
kf->file_seek(kf->file_offset + 0, kf->seek_set); |
kf->file_read(&header, sizeof(struct elf_header)); |
if (memcmp(header.e_ident, elf_signature, 4)) { |
printk("Not an ELF file\n"); |
printk("Wrong signature: 0x%lx)!!!\n", |
*(DWORD *)header.e_ident); |
return 0; |
} |
//printk("ELF signature OK\n"); |
tables->flags = 0; |
if (header.e_ident[4] != ELFCLASS32) { |
printk("Wrong ELF class\n"); |
printk("Class: 0x%x!!!\n", header.e_ident[4]); |
return 0; |
} |
//printk("ELF Class OK\n"); |
if (header.e_ident[5] != ELFDATA2LSB) { |
printk("Wrong data ordering (not LSB)\n"); |
printk("Ordering: 0x%x!!!\n", header.e_ident[5]); |
return 0; |
} |
//printk("ELF data ordering OK\n"); |
#ifdef __ELF_DEBUG__ |
if(header.e_machine != EM_386) |
{ |
printk("Warning: machine = 0x%x!!!\n", header.e_machine); |
} |
#endif |
//printk("ELF Type: 0x%x\n", header.e_type); |
if(header.e_shoff != 0) |
{ |
#ifdef __ELF_DEBUG__ |
printk("Section headers @ %ld\n", header.e_shoff); |
printk("Number of sections: %d\n", header.e_shnum); |
printk("Section header size: %d (0x%x)\n", |
header.e_shentsize, header.e_shentsize); |
#endif |
tables->section_header = header.e_shoff; |
tables->section_header_size = header.e_shentsize; |
tables->num_sections = header.e_shnum; |
} |
#ifdef __ELF_DEBUG__ |
if (header.e_phoff != 0) { |
printk("Program header table @ %ld\n", header.e_phoff); |
printk("Number of segments: %d\n", header.e_phnum); |
printk("Segment header size: %d (0x%x)\n", |
header.e_phentsize, header.e_phentsize); |
} |
#ifdef __ELF_DEBUG__ |
/* Flags... */ |
/* RELOCATION */ |
if (header.f_flags & F_RELFLG) { |
printk("No relocation info!\n"); |
} |
if (header.f_flags & F_EXEC) { |
printk("Executable file (no unresolved symbols)\n"); |
} |
if (header.f_flags & F_LNNO) { |
printk("No line numbers!\n"); |
} |
if (header.f_flags & F_LSYMS) { |
printk("No local symbols!\n"); |
} |
if (header.f_flags & F_AR32WR) { |
printk("32-bit little endian!\n"); |
} else { |
printk("File type?\n"); |
} |
#endif |
printk("Section Name String Table is section number %d\n", |
header.e_shstrndx); |
#endif |
if (header.e_shstrndx > tables->num_sections) |
{ |
printk("Error: SNST number > section number...\n"); |
return 0; |
} |
res = kf->file_seek( kf->file_offset + tables->section_header + |
header.e_shstrndx * tables->section_header_size, |
kf->seek_set); |
if (res < 0) { |
printk("Cannot seek"); |
return 0; |
} |
//printk("ELF file seek OK\n"); |
res = kf->file_read( &h, sizeof(struct elf_section_header)); |
if (res < 0) { |
printk("Cannot read"); |
return 0; |
} |
//printk("ELF file read OK\n"); |
tables->section_names = 0; |
if(h.sh_size != 0) |
{ |
//printk("ELF Loading Section Names...\n"); |
tables->section_names = (void *)malloc(h.sh_size); |
if (tables->section_names == NULL) |
{ |
printk("Failed to allocate space for section names...\n"); |
return 0; |
} |
res = kf->file_seek( kf->file_offset + h.sh_offset, kf->seek_set); |
if (res < 0) { |
printk("Cannot seek"); |
return 0; |
} |
res = kf->file_read( tables->section_names, h.sh_size); |
if (res < 0) { |
printk("Cannot read"); |
return 0; |
} |
tables->section_names_size = h.sh_size; |
} |
else |
{ |
printk("0 size?\n"); |
tables->section_names_size = 0; |
} |
entry = header.e_entry; |
if (entry == 0) { |
tables->flags |= NO_ENTRY; |
tables->flags |= NEED_LOAD_RELOCATABLE; |
tables->flags |= NEED_SECTION_RELOCATION; |
} |
//printk("ELF Read headers Done!\n"); |
return entry; |
}; |
int ELF_read_section_headers(struct file_ops *kf, |
struct table_info *tables, |
struct section_info *scndata) |
{ |
int bss = -1; |
int i, j; |
struct elf_section_header h; |
int header_size; |
int stringtable = -1; |
struct elf_rel_info r; |
header_size = tables->section_header_size; |
if(header_size > sizeof(struct elf_section_header)) |
{ |
printk("Section header size (%d) > sizeof(struct section_header) (%d)\n", |
header_size, (int)(sizeof(struct elf_section_header)) ); |
header_size = sizeof(struct elf_section_header); |
} |
for (i = 0; i < tables->num_sections; i++) |
{ |
kf->file_seek( kf->file_offset + tables->section_header + |
i * tables->section_header_size, kf->seek_set); |
kf->file_read( &h, sizeof(struct elf_section_header)); |
#ifdef __ELF_DEBUG__ |
printk("Section %d: ", i); |
printk("Flags 0x%x: \n", h.sh_flags); |
#endif |
/* |
Set this stuff to 0... |
If size == 0 the section must not be loaded |
*/ |
scndata[i].num_reloc = 0; |
scndata[i].base = 0; |
scndata[i].size = 0; |
scndata[i].fileptr = 0; |
scndata[i].filesize = 0; |
/* If this is a NULL section, skip it!!! */ |
if (h.sh_type != SHT_NULL) { |
if (tables->section_names != 0) { |
#ifdef __ELF_DEBUG__ |
printk("[%s]", tables->section_names + h.sh_name); |
#endif |
if (strcmp(tables->section_names + h.sh_name, ".bss") == 0) { |
bss = i; |
} |
} |
#ifdef __ELF_DEBUG__ |
printk(" <0x%lx:0x%lx> (0x%lx)\n", |
h.sh_addr, |
h.sh_addr + h.sh_size, |
h.sh_offset); |
#endif |
if (h.sh_type == SHT_REL) { |
#ifdef __ELF_DEBUG__ |
printk("\t\tSection %d: relocation info!!!\n", i); |
printk("\t\tSymbol table: section number %lu\n", h.sh_link); |
printk("\t\tSection to modify: %lu\n", h.sh_info); |
printk("\t\tNumber of relocation entries: %lu\n", |
h.sh_size / h.sh_entsize); |
#endif |
if (scndata[h.sh_info].num_reloc != 0) { |
printk("Double relocation for section\n"); |
printk("%lu?\n", h.sh_info); |
return 0; |
} |
/* So, ...let's load it!!! */ |
scndata[h.sh_info].num_reloc = h.sh_size / h.sh_entsize; |
//scndata[h.sh_info].reloc = (void *)kf->mem_alloc((h.sh_size / h.sh_entsize) * sizeof(struct reloc_info)); |
scndata[h.sh_info].reloc = (void *)malloc((h.sh_size / h.sh_entsize) * sizeof(struct reloc_info)); |
if (scndata[h.sh_info].reloc == NULL) { |
printk("Failed to allocate space for relocation info...\n"); |
return 0; |
} |
//printk("ELF Allocate space for relocation info OK!\n"); |
for (j = 0; j < h.sh_size / h.sh_entsize; j++) { |
kf->file_seek( kf->file_offset + h.sh_offset + j * h.sh_entsize, |
kf->seek_set); |
kf->file_read( &r, sizeof(struct elf_rel_info)); |
scndata[h.sh_info].reloc[j].offset = r.r_offset; |
scndata[h.sh_info].reloc[j].symbol = r.r_info >> 8; |
/* HACKME!!! Unify the relocation types... */ |
scndata[h.sh_info].reloc[j].type = (BYTE)r.r_info; |
if ((BYTE)r.r_info == R_386_32){ |
scndata[h.sh_info].reloc[j].type = REL_TYPE_ELF_ABSOLUTE; |
} else if ((BYTE)r.r_info == R_386_PC32) { |
scndata[h.sh_info].reloc[j].type = REL_TYPE_RELATIVE; |
} |
} |
} else if (h.sh_type == SHT_RELA) { |
printk("Error: unsupported relocation section!!!\n"); |
return 0; |
} else if ((h.sh_type == SHT_SYMTAB) || (h.sh_type == SHT_DYNSYM)) { |
#ifdef __ELF_DEBUG__ |
printk("\t\tSection %d: symbol table!!!\n", i); |
printk("\t\tString table: section number %lu\n", h.sh_link); |
printk("\t\tLast local Symbol + 1: %lu\n", h.sh_info); |
#endif |
tables->symbol = h.sh_offset; |
tables->num_symbols = h.sh_size / h.sh_entsize; |
tables->symbol_size = h.sh_size; |
if (stringtable != -1) { |
printk("Error: double string table!!!\n"); |
return 0; |
} |
stringtable = h.sh_link; |
if (stringtable < i) { |
printk("Strange... "); |
printk("String table (%d) < Symbol Table\n", stringtable); |
return 0; |
} |
} else if (i == stringtable) { |
#ifdef __ELF_DEBUG__ |
printk("\t\t Section %d: string table!!!\n", i); |
#endif |
tables->string = h.sh_offset; |
tables->string_size = h.sh_size; |
stringtable = -1; |
} else { |
scndata[i].base = h.sh_addr; |
scndata[i].size = h.sh_size; |
scndata[i].fileptr = h.sh_offset; |
if (h.sh_type != SHT_NOBITS) { |
#ifdef __ELF_DEBUG__ |
printk("BSS?\n"); |
#endif |
scndata[i].filesize = h.sh_size; |
} |
} |
} else { |
#ifdef __ELF_DEBUG__ |
printk("NULL Section\n"); |
#endif |
} |
#if 0 |
if (h.s_flags & SECT_TEXT) { |
printk("Executable section\n"); |
} |
if (h.s_flags & SECT_INIT_DATA) { |
printk("Data section\n"); |
} |
if (h.s_flags & SECT_UNINIT_DATA) { |
printk("BSS section\n"); |
scndata[i].filesize = 0; |
} |
#endif |
} |
tables->image_base = scndata[0].base; |
return bss; |
}; |
int ELF_read_symbols(struct file_ops *kf, |
struct table_info *tables, |
struct symbol_info *syms) |
{ |
//printk("ELF read_symbols\n"); |
int i; |
int entsize; |
struct elf_symbol_info symbol; |
char *s; |
s = (void *)malloc(tables->string_size); |
if(s == NULL) |
{ |
printk("Failed to allocate space for string table...\n"); |
return 0; |
} |
tables->string_buffer = (DWORD)s; |
kf->file_seek( kf->file_offset + tables->string, kf->seek_set); |
kf->file_read( s, tables->string_size); |
entsize = tables->symbol_size / tables->num_symbols; |
for (i = 0; i < tables->num_symbols; i++) |
{ |
kf->file_seek( kf->file_offset + tables->symbol + i * entsize, |
kf->seek_set); |
kf->file_read( &symbol, sizeof(struct elf_symbol_info)); |
syms[i].name = s + symbol.st_name; |
syms[i].section = symbol.st_shndx; |
syms[i].offset = symbol.st_value; |
if (syms[i].section == SHN_UNDEF) { |
/* extern symbol */ |
if (symbol.st_name != 0) |
syms[i].section = EXTERN_SYMBOL; |
else /* Mark the empty entry, external symbol with no name is not used :-) */ |
syms[i].section = NULL_SYMBOL; |
} |
if (syms[i].section == SHN_COMMON) { |
/* extern symbol */ |
syms[i].section = COMMON_SYMBOL; |
syms[i].offset = symbol.st_size; |
/* calculate the local_bss_size */ |
tables->local_bss_size += syms[i].offset; |
} |
} |
return 1; |
}; |
int Elf_check(struct file_ops *kf) |
{ |
char signature[4]; |
kf->file_offset = kf->file_seek( 0, kf->seek_cur); |
kf->file_read(signature, 4); |
kf->file_seek( kf->file_offset + 0, kf->seek_set); |
if(memcmp(signature, elf_signature, 4)) |
{ |
return 0; |
} |
return 1; |
}; |
int ELF_relocate_section(struct file_ops *kf, |
DWORD base, |
struct table_info *tables, |
int n, |
struct section_info *s, |
int sect, |
struct symbol_info *syms, |
struct symbol *import) |
{ |
int i, idx; |
DWORD address, destination; |
int j, done; |
DWORD local_bss = tables->local_bss; |
struct reloc_info *rel = s[sect].reloc; |
/* Setup the common space-uninitialized symbols at the first section relocation |
* Pre-calculate the local BSS size (in read_symbols) |
* then allocate for each symbol (in load_relocatable) |
*/ |
if(sect == 0) |
{ |
for(i=0; i<tables->num_symbols; i++) |
{ |
if(syms[i].section == COMMON_SYMBOL) |
{ |
j = syms[i].offset; |
syms[i].offset = local_bss; |
local_bss += j; |
} |
else if(syms[i].section == EXTERN_SYMBOL) |
{ |
#ifdef __ELF_DEBUG__ |
printk("Searching for symbol %s\n", syms[i].name); |
#endif |
/* Pre-set the external symbol at the same time */ |
for(j=0, done=0; import[j].name != 0; j++) |
{ |
if(strcmp(import[j].name, syms[i].name) == 0) |
{ |
syms[i].offset = import[j].address; |
done = 1; |
break; |
} |
} |
if(done == 0) |
{ |
printk("Symbol %s not found\n", syms[i].name); |
return -1; |
} |
} |
} |
} |
//printk("[COMMON] s[sect].num_reloc = %d\n", s[sect].num_reloc); |
for(i=0; i < s[sect].num_reloc; i++) |
{ |
#ifdef __COFF_DEBUG__ |
printk("Relocate 0x%lx (index 0x%x): mode %d ", |
rel[i].offset, rel[i].symbol, rel[i].type); |
#endif |
idx = rel[i].symbol; |
#ifdef __COFF_DEBUG__ |
printk("%s --> 0x%lx (section %d)\n", syms[idx].name, |
syms[idx].offset, syms[idx].section); |
#endif |
switch (rel[i].type) |
{ |
case REL_TYPE_ELF_ABSOLUTE: |
destination = s[sect].base + rel[i].offset + base; |
// Initial address |
address = *((DWORD*)destination); |
break; |
case REL_TYPE_RELATIVE: |
destination = s[sect].base + rel[i].offset + base; |
address = 0; |
break; |
default: |
// (Non-)external symbols: only REL32 is supported |
printk("Unsupported relocation!\n"); |
printk("Relocation Type: %d\n", rel[i].type); |
return -1; |
} |
if(syms[idx].section == COMMON_SYMBOL || syms[idx].section == EXTERN_SYMBOL) |
{ |
if(rel[i].type == REL_TYPE_ELF_ABSOLUTE) |
address += syms[idx].offset; |
else if(rel[i].type == REL_TYPE_RELATIVE) |
address = syms[idx].offset - destination - 4; |
} |
else if(syms[idx].section >= n) |
{ |
// Check if the section exists ... |
printk("Unsupported relocation section\n"); |
printk("Section %d > %d\n", syms[idx].section, n); |
printk("Value 0x%lx\n", syms[idx].offset); |
return -1; |
} |
else |
{ |
if(rel[i].type == REL_TYPE_ELF_ABSOLUTE) |
{ |
address += base + s[syms[idx].section].base + syms[idx].offset; |
} |
else if(rel[i].type == REL_TYPE_RELATIVE) |
{ |
address = (s[syms[idx].section].base + syms[idx].offset) - (s[sect].base + rel[i].offset) - 4; |
#ifdef __COFF_DEBUG__ |
printk("Reloc: 0x%lx + 0x%lx - 0x%lx = 0x%lx ", |
syms[idx].offset, |
s[syms[idx].section].base, |
rel[i].offset , address); |
#endif |
} |
} |
#ifdef __COFF_DEBUG__ |
printk("0x%lx <--- 0x%lx\n", destination, address); |
#endif |
*((DWORD*)destination) = address; |
} |
return 1; |
}; |
/* Import symbol with suffix `name' |
* NOTE: Any symbol with prefix `_' won't be found and be regarded as internal and hidden |
*/ |
DWORD ELF_import_symbol(struct file_ops *kf, |
int n, |
struct symbol_info *syms, |
char *name, |
int *sect) |
{ |
//printk("[COMMON] import_symbol...\n"); |
int i; |
int len = strlen(name); |
for(i = 0; i < n ; i++) |
{ |
#ifdef __COFF_DEBUG__ |
printk("Checking symbol %d [%d] --- Sect %d\n", i, n, syms[i].section); |
#endif |
if ((syms[i].section != EXTERN_SYMBOL) && (syms[i].section != COMMON_SYMBOL) && (syms[i].section != NULL_SYMBOL)) |
{ |
#ifdef __COFF_DEBUG__ |
printk("Compare %s, %s\n", syms[i].name, name); |
#endif |
if(syms[i].name[0] != '_') |
{ |
int sym_len = strlen(syms[i].name); |
if(sym_len >= len && strcmp(syms[i].name+sym_len-len, name) == 0) |
{ |
#ifdef __COFF_DEBUG__ |
printk("Found: %s --- 0x%x : 0x%lx\n", |
syms[i].name, syms[i].section, syms[i].offset); |
#endif |
break; |
} |
#ifdef __COFF_DEBUG__ |
else |
{ |
printk("Cmp failed --- Going to %d\n", i); |
} |
#endif |
} |
} |
#ifdef __COFF_DEBUG__ |
else |
{ |
printk("Skipped symbol --- Going to %d\n", i); |
} |
#endif |
} |
if(i < n) |
{ /* Symbol found */ |
*sect = syms[i].section; |
return syms[i].offset; |
} |
else |
{ |
*sect = -1; |
printk("Symbol not found!!!\n"); |
return 0; |
} |
}; |
DWORD ELF_load_relocatable( struct file_ops *kf, |
struct table_info *tables, |
int n, |
struct section_info *s, |
DWORD *size) |
{ |
int i; |
DWORD needed_mem = 0; |
DWORD local_offset = 0; |
BYTE *mem_space, *where_to_place; |
// Allocate for the local bss at the mean time |
for(i=0; i<n; i++) |
{ |
needed_mem += s[i].size; |
} |
needed_mem += tables->local_bss_size; |
mem_space = (BYTE *)malloc(needed_mem); |
if(mem_space == NULL) |
{ |
printk("Unable to allocate memory for the program image\n"); |
return 0; |
} |
memset(mem_space, 0, needed_mem); |
#ifdef __ELF_DEBUG__ |
printk("Loading relocatable @%p; size 0x%lx\n", mem_space, needed_mem); |
#endif |
if(tables->local_bss_size != 0) |
tables->local_bss = (DWORD)mem_space + needed_mem - tables->local_bss_size; |
else |
tables->local_bss = 0; |
for(i=0; i<n; i++) |
{ |
#ifdef __ELF_DEBUG__ |
printk("Section %d\t", i); |
#endif |
if(s[i].size != 0) |
{ |
#ifdef __ELF_DEBUG__ |
printk("Loading @ 0x%lx (0x%lx + 0x%lx)...\n", |
(DWORD)mem_space + (DWORD)local_offset, |
(DWORD)mem_space, local_offset); |
#endif |
where_to_place = mem_space + local_offset; |
s[i].base = local_offset; |
local_offset += s[i].size; |
kf->file_seek( kf->file_offset + s[i].fileptr, kf->seek_set); |
if(s[i].filesize > 0) |
{ |
kf->file_read( where_to_place, s[i].filesize); |
} |
} |
else |
{ |
#ifdef __ELF_DEBUG__ |
printk("Not to be loaded\n"); |
#endif |
} |
} |
*size = needed_mem; |
return (DWORD)mem_space; |
}; |
void ELF_free_tables(struct file_ops *kf, |
struct table_info *tables, |
struct symbol_info *syms, |
struct section_info *scndata) |
{ |
int i; |
for(i = 0; i < tables->num_sections; i++) |
if (scndata[i].num_reloc != 0) |
free( scndata[i].reloc); |
free(scndata); |
if (syms != NULL) free(syms); |
if (tables->string_size != 0) free((DWORD*)tables->string_buffer); |
if (tables->section_names_size != 0) free(tables->section_names); |
}; |
/shark/trunk/ports/dynalink/dynalink.c |
---|
0,0 → 1,559 |
//////////////////////////////////////////////////////////////////////// |
// dynalink.c |
// |
// DynaLink for S.H.A.R.K |
// Dynamic ELF object linker. |
// |
// Original code written by Luca Abeni. |
// Adapted by Lex Nahumury 19-7-2006. |
// |
// This is free software; see GPL.txt |
//////////////////////////////////////////////////////////////////////// |
#include "kernel/kern.h" |
#include <kernel/func.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <math.h> |
#include <ll/i386/hw-data.h> |
#include <ll/i386/mem.h> |
#include <ll/i386/hw-instr.h> |
#include <ll/i386/cons.h> |
#include <ll/i386/error.h> |
#include <ll/i386/mem.h> |
#include <ll/ctype.h> |
#include <ll/i386/x-bios.h> |
#include "format.h" |
#include "dynalink.h" |
#include "elf.h" |
#include <drivers/shark_linuxc26.h> |
#include <drivers/shark_pci26.h> |
#include <drivers/shark_input26.h> |
#include <drivers/shark_keyb26.h> |
// some shark pci forward declaration stuff (pci20to26.c) |
extern int pci20to26_find_class(unsigned int class_code, int index, BYTE *bus, BYTE *dev); |
extern int pci20to26_read_config_byte(unsigned int bus, unsigned int dev, int where, BYTE *val); |
extern int pci20to26_read_config_word(unsigned int bus, unsigned int dev, int where, WORD *val); |
extern int pci20to26_read_config_dword(unsigned int bus, unsigned int dev, int where, DWORD *val); |
extern int pci20to26_write_config_byte(unsigned int bus, unsigned int dev, int where, BYTE val); |
extern int pci20to26_write_config_word(unsigned int bus, unsigned int dev, int where, WORD val); |
extern int pci20to26_write_config_dword(unsigned int bus, unsigned int dev, int where, DWORD val); |
#define __DYNA_DEBUG__ |
#define NORMAL_PROCESS 0 |
#define EMPTY_SLOT {0, (DWORD)0xFFFFFFFF} |
#define SUBSTITUTE 1 |
#define ADD 0 |
static struct file_ops kf; |
static DWORD start; |
static DWORD end; |
static DWORD pointer; |
//A module can also export symbols by adding them to the kernel symbol table |
int add_call(char *name, DWORD address, int mode); |
// forward declarations of some custom 'syscalls'... |
extern void call_shutdown_task(void *arg); |
extern DWORD get_tick(); |
static struct symbol syscall_table[] = { |
// console & string |
{ "cprintf", (DWORD)cprintf }, |
{ "sprintf", (DWORD)sprintf }, |
{ "printk", (DWORD)printk }, |
{ "printf_xy", (DWORD)printf_xy }, |
{ "puts_xy", (DWORD)puts_xy }, |
{ "place", (DWORD)place }, |
{ "_clear", (DWORD)_clear }, |
{ "clear", (DWORD)clear }, |
{ "strcpy", (DWORD)strcpy }, |
// keyboard |
{ "keyb_getch", (DWORD)keyb_getch }, |
{ "keyb_getcode", (DWORD)keyb_getcode }, |
// math |
{ "sin", (DWORD)sin }, |
{ "cos", (DWORD)cos }, |
{ "pow", (DWORD)pow }, |
{ "abs", (DWORD)abs }, |
// memory |
{ "malloc", (DWORD)malloc }, |
{ "kern_alloc_aligned", (DWORD)kern_alloc_aligned }, |
{ "free", (DWORD)free }, |
// I/O |
{ "inp", (DWORD)inp }, |
{ "inpw", (DWORD)inpw }, |
{ "inpd", (DWORD)inpd }, |
// pci |
{ "pci20to26_read_config_byte", (DWORD)pci20to26_read_config_byte }, |
{ "pci20to26_read_config_word", (DWORD)pci20to26_read_config_word }, |
{ "pci20to26_read_config_dword", (DWORD)pci20to26_read_config_dword }, |
{ "pci20to26_write_config_byte", (DWORD)pci20to26_write_config_byte }, |
{ "pci20to26_write_config_word", (DWORD)pci20to26_write_config_word }, |
{ "pci20to26_write_config_dword", (DWORD)pci20to26_write_config_dword }, |
// task managment |
{ "task_testcancel", (DWORD)task_testcancel }, |
{ "task_message", (DWORD)task_message }, |
{ "task_createn", (DWORD)task_createn }, |
{ "task_activate", (DWORD)task_activate }, |
{ "handler_set", (DWORD)handler_set }, |
{ "task_nopreempt", (DWORD)task_nopreempt }, |
{ "task_preempt", (DWORD)task_preempt }, |
{ "group_activate", (DWORD)group_activate }, |
// Time & termination |
{ "sys_gettime", (DWORD)sys_gettime }, |
{ "get_tick", (DWORD)get_tick }, |
{ "perror", (DWORD)perror }, |
{ "exit", (DWORD)exit }, |
{ "call_shutdown_task", (DWORD)call_shutdown_task }, |
{ "sys_shutdown_message", (DWORD)sys_shutdown_message }, |
{ "add_call", (DWORD)add_call }, //module can add symbol to the kernel symbol table |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
EMPTY_SLOT, |
{0, 0} |
}; |
void *get_syscall_table(void) |
{ |
return syscall_table; |
}; |
int add_call(char *name, DWORD address, int mode) |
{ |
int i; |
int done; |
int res; |
i = 0; |
done = 0; |
while ((!done) && (syscall_table[i].address != 0)) { |
if (!strcmp(syscall_table[i].name, name)) { |
done = 1; |
} else { |
i++; |
} |
} |
if (done == 1) { |
if (mode == SUBSTITUTE) { |
res = syscall_table[i].address; |
syscall_table[i].name = name; |
syscall_table[i].address = address; |
} else { |
return -1; |
} |
} else { |
if (mode == SUBSTITUTE) { |
return -1; |
} else { |
i = 0; |
while (syscall_table[i].name != 0) { |
i++; |
} |
if (syscall_table[i].address != 0xFFFFFFFF) { |
return -1; |
} |
res = 1; |
syscall_table[i].name = name; |
syscall_table[i].address = address; |
} |
} |
return res; |
}; |
static DWORD load_process(struct file_ops *kf, |
DWORD *ex_exec_space, |
DWORD *image_base, |
DWORD *ex_size) |
{ |
#ifdef __EXEC_DEBUG__ |
DWORD offset; |
#endif |
DWORD size; |
DWORD exec_space=0; |
int bss_sect, i; |
DWORD dyn_entry; |
struct section_info *sections; |
struct symbol_info *symbols = NULL; |
struct table_info tables; |
// Initialize the table info |
tables.section_names_size = 0; |
tables.local_bss_size = 0; |
tables.private_info = 0; |
// read ELF headers |
dyn_entry = ELF_read_headers(kf, &tables); |
sections = (struct section_info*)malloc(sizeof(struct section_info) * tables.num_sections); |
if(sections == 0) |
{ |
printk("Can't allocate the sections info!\n"); |
return -1; |
} |
// read ELF section headers |
bss_sect = ELF_read_section_headers(kf, &tables, sections); |
// Load symbols (if it's objects, calculate the local bss size) |
if(tables.num_symbols != 0) |
{ |
symbols = (struct symbol_info*)malloc(tables.num_symbols * sizeof (struct symbol_info)); |
if (symbols == 0) |
{ |
error("Error allocating symbols table\n"); |
ELF_free_tables(kf, &tables, symbols, sections); |
return -1; |
} |
// read ELF symbols |
ELF_read_symbols(kf, &tables, symbols); |
} |
if(tables.flags & NEED_LOAD_RELOCATABLE) |
{ |
#ifdef __EXEC_DEBUG__ |
printk("[EXEC]Must load_relocatable()!\n"); |
#endif |
exec_space = ELF_load_relocatable(kf, &tables, tables.num_sections, sections, &size); |
} |
if(exec_space == 0) |
{ |
printk("Error decoding the Executable data\n"); |
ELF_free_tables(kf, &tables, symbols, sections); |
return -1; |
} |
if(tables.flags & (NEED_SECTION_RELOCATION|NEED_IMAGE_RELOCATION)) |
{ |
int res; |
void *kernel_symbols; |
int reloc_sections; |
if (tables.flags & NEED_SECTION_RELOCATION) |
{ |
if ((bss_sect < 0) || (bss_sect > tables.num_sections)) |
{ |
error("Error: strange file --- no BSS section\n"); |
/* TODO: Return code... */ |
ELF_free_tables(kf, &tables, symbols, sections); |
free((DWORD*)exec_space); |
return -1; |
} |
} |
#ifdef __EXEC_DEBUG__ |
printk("[EXEC] Start of local BSS: 0x%lx\n", tables.private_info); |
#endif |
kernel_symbols = get_syscall_table(); |
if(tables.flags & NEED_SECTION_RELOCATION) |
{ |
reloc_sections = tables.num_sections; |
} else |
{ |
reloc_sections = 1; |
} |
#ifdef __EXEC_DEBUG__ |
printk("[EXEC] reloc_sections = %d\n", reloc_sections); |
#endif |
// Relocate sections... |
for (i=0; i<reloc_sections; i++) |
{ |
res = ELF_relocate_section(kf, |
exec_space, |
&tables, |
tables.num_sections, |
sections, |
i, |
symbols, |
kernel_symbols); |
if(res < 0) |
{ |
error("Error: relocation failed!!!\n"); |
/* TODO: Return code... */ |
ELF_free_tables(kf, &tables, symbols, sections); |
free((DWORD*)exec_space); |
return -1; |
} |
} |
} |
/* The size of the execution space */ |
*ex_size = size; |
if(tables.flags & NO_ENTRY) |
{ |
int init_sect; |
/* No entry point... We assume that we need dynamic linking */ |
#ifdef __EXEC_DEBUG__ |
printk("[EXEC] Searching for the initialization function...\n"); |
#endif |
if(symbols == 0) |
{ |
error("Error: no symbols!!!\n"); |
/* TODO: Return code... */ |
ELF_free_tables(kf, &tables, symbols, sections); |
free((DWORD*)exec_space); |
return -1; |
} |
// Find the main entry point. Function name ends with kf->entry_name... |
//dyn_entry = (DWORD)ELF_import_symbol(kf, tables.num_symbols, symbols, DYN_ENTRY_NAME, &init_sect); |
dyn_entry = (DWORD)ELF_import_symbol(kf, tables.num_symbols, symbols, kf->entry_name, &init_sect); |
if(init_sect != -1) |
{ |
#ifdef __EXEC_DEBUG__ |
printk("Found: (%d = 0x%x) 0x%lx\n", init_sect, |
init_sect, dyn_entry); |
printk("Section Base: 0x%lx Exec Space: 0x%lx\n", |
sections[init_sect].base, exec_space); |
#endif |
dyn_entry += sections[init_sect].base + exec_space; |
*image_base = exec_space; |
*ex_exec_space = 0; |
ELF_free_tables(kf, &tables, symbols, sections); |
return dyn_entry; |
} |
else |
{ |
printk("WARNING: Initialization function not found!\n"); |
return -1; |
} |
} |
return -1; // error |
}; |
// Read an ELF object in memory, and return it's main entry function's address.. |
static DWORD get_exec_address( struct file_ops *kf ) |
{ |
DWORD exec_space; |
DWORD image_base; |
DWORD ex_size; |
DWORD dyn_entry; |
dyn_entry = load_process( kf, |
&exec_space, |
&image_base, |
&ex_size); |
if(dyn_entry== -1) return 0; |
return dyn_entry; |
}; |
/* |
static char *module_command_line(DWORD mods_addr, int i) |
{ |
struct mods_struct *curr_mod; |
curr_mod = (struct mods_struct *)mods_addr; |
return curr_mod[i].string; |
}; |
static void module_address(DWORD mods_addr, int i, DWORD *start, DWORD *end) |
{ |
struct mods_struct *curr_mod; |
curr_mod = (struct mods_struct *)mods_addr; |
*start = (DWORD)curr_mod[i].mod_start; |
*end = (DWORD)curr_mod[i].mod_end; |
}; |
*/ |
static int modfs_read( void *buff, int size) |
{ |
int len = size; |
if(pointer + len > end) |
{ |
len = end - pointer; |
} |
memcpy(buff, (void *)pointer, len); |
pointer += len; |
return len; |
}; |
static int modfs_seek( int pos, int wence) |
{ |
int res; |
if(wence == 0) |
{ |
res = pos; |
} |
else if(wence == 1) |
{ |
res = pointer + pos - start; |
} |
else if(wence == 2) |
{ |
if(end - start < pos) res = 0; |
else res = end - start - pos; |
} |
else res = pointer - start; |
if(start + res > end) res = end - start; |
pointer = start + res; |
return res; |
}; |
// This will process all modules and fill out a dynalink_module_list. |
// We only support valid ELF objects. |
// Everything else is treated as DATA. |
int dynalink_modules(struct multiboot_info* mb, |
struct dynalink_module_list* dml, |
char* search_string) |
{ |
int i; |
DWORD dyn_entry; |
int mods_addr = mb->mods_addr; |
int mods_count = mb->mods_count; |
// Initialize the Modules Pseudo-FS... |
kf.file_seek = modfs_seek; |
kf.file_read = modfs_read; |
kf.entry_name = search_string; |
kf.seek_set = 0; |
kf.seek_cur = 1; |
// check all modules.. |
for(i = 0; i < mods_count; i++) |
{ |
#ifdef __DYNA_DEBUG__ |
printk("[MOD] Process Module #%d:", i); |
#endif |
kf.file_offset = 0; |
// Pseudo-FS open |
struct mods_struct* curr_mod = (struct mods_struct*)mods_addr; |
start = (DWORD)curr_mod[i].mod_start; |
end = (DWORD)curr_mod[i].mod_end; |
pointer = start; |
if( Elf_check(&kf) ) |
{ |
// Try to Link the ELF module and get it's main_entry address |
dyn_entry = get_exec_address( &kf ); |
if(dyn_entry) |
{ |
int j = dml->num_apps; |
dml->app[j].dyn_entry = dyn_entry; |
dml->app[j].start = start; |
dml->app[j].end = end; |
dml->app[j].size = end - start; |
dml->app[j].name = curr_mod[i].string; |
#ifdef __DYNA_DEBUG__ |
printk(" ELF object :%s [%d bytes]\n", |
dml->app[j].name, dml->app[j].size); |
#endif |
++dml->num_apps; |
} |
else // add it as 'Data' module |
{ |
int j = dml->num_dats; |
dml->dat[j].start = start; |
dml->dat[j].end = end; |
dml->dat[j].size = end - start; |
dml->dat[j].name = curr_mod[i].string; |
#ifdef __DYNA_DEBUG__ |
printk(" Data object :%s [%d bytes]\n", |
dml->dat[j].name, dml->dat[j].size); |
#endif |
++dml->num_dats; |
} |
} |
else // it is a 'Data' module |
{ |
int j = dml->num_dats; |
dml->dat[j].start = start; |
dml->dat[j].end = end; |
dml->dat[j].size = end - start; |
dml->dat[j].name = curr_mod[i].string; |
#ifdef __DYNA_DEBUG__ |
printk(" Data object :%s [%d bytes]\n", |
dml->dat[j].name, dml->dat[j].size); |
#endif |
++dml->num_dats; |
} |
//TODO: ? mem_release_module(mods_addr, i, mods_count); |
} |
return 0; |
}; |
/* |
// TODO: haven't finished this yet for SHARK [Lex] |
void mem_release_module(DWORD mstart, int m, int mnum) |
{ |
DWORD ms, nms, me, ms1, dummy; |
int i; |
module_address(mstart, m, &ms, &me); |
nms = 0; |
for (i = 0; i < mnum; i++) |
{ |
module_address(mstart, i, &ms1, &dummy); |
if(nms == 0) |
{ |
if(ms1 >= me) nms = ms1; |
} |
else |
{ |
if((ms1 >= me) && (ms1 < nms)) nms = ms1; |
} |
} |
if (nms == 0) nms = me; |
#ifdef __MEM_DEBUG__ |
printk("releasing %lx - %lx\n", ms, nms); |
#endif |
//pmm_add_region(&high_mem_pool, ms, nms - ms); |
}; |
*/ |
/shark/trunk/ports/dynalink/elf.h |
---|
0,0 → 1,177 |
//////////////////////////////////////////////////////////////////////// |
// elf.h |
// |
// DynaLink for S.H.A.R.K |
// Dynamic ELF object linker. |
// |
// Original code written by Luca Abeni. |
// Adapted by Lex Nahumury 19-7-2006. |
// |
// This is free software; see GPL.txt |
//////////////////////////////////////////////////////////////////////// |
#ifndef __ELF_HDR__ |
#define __ELF_HDR__ |
#define ELFCLASS32 1 |
#define ELFDATA2LSB 1 |
#define ET_EXEC 2 |
#define EM_386 3 |
/* This info is needed when parsing the symbol table */ |
#define STB_LOCAL 0 |
#define STB_GLOBAL 1 |
#define STB_WEAK 2 |
#define STT_NOTYPE 0 |
#define STT_OBJECT 1 |
#define STT_FUNC 2 |
#define STT_SECTION 3 |
#define STT_FILE 4 |
#define ELF_ST_BIND(info) ((info) >> 4) |
#define ELF_ST_TYPE(info) (((unsigned int) info) & 0xf) |
/* sh_type */ |
#define SHT_NULL 0 |
#define SHT_SYMTAB 2 |
#define SHT_RELA 4 |
#define SHT_NOBITS 8 |
#define SHT_REL 9 |
#define SHT_DYNSYM 11 |
#define R_386_32 1 |
#define R_386_PC32 2 |
/* special section indexes */ |
#define SHN_UNDEF 0 |
#define SHN_COMMON 0xFFF2 |
/* e_ident[] indexes */ |
#define EI_MAG0 0 |
#define EI_MAG1 1 |
#define EI_MAG2 2 |
#define EI_MAG3 3 |
#define EI_CLASS 4 |
#define EI_DATA 5 |
#define EI_NIDENT 16 |
/* EI_MAG */ |
#define ELFMAG0 0x7f |
#define ELFMAG1 'E' |
#define ELFMAG2 'L' |
#define ELFMAG3 'F' |
#define PT_LOAD 1 |
#define PF_W 0x02 |
struct elf_header{ |
BYTE e_ident[EI_NIDENT]; |
WORD e_type; |
WORD e_machine; |
DWORD e_version; |
DWORD e_entry; /* Entry point */ |
DWORD e_phoff; |
DWORD e_shoff; |
DWORD e_flags; |
WORD e_ehsize; |
WORD e_phentsize; |
WORD e_phnum; |
WORD e_shentsize; |
WORD e_shnum; |
WORD e_shstrndx; |
}; |
/* FIXME!!! */ |
typedef struct { |
DWORD p_type; |
DWORD p_offset; |
DWORD p_vaddr; |
DWORD p_paddr; |
DWORD p_filesz; |
DWORD p_memsz; |
DWORD p_flags; |
DWORD p_align; |
} Elf32_Phdr; |
struct elf_section_header { |
DWORD sh_name; |
DWORD sh_type; /* Type of section */ |
DWORD sh_flags; /* Miscellaneous section attributes */ |
DWORD sh_addr; /* Section virtual addr at execution */ |
DWORD sh_offset; /* Section file offset */ |
DWORD sh_size; /* Size of section in bytes */ |
DWORD sh_link; /* Index of another section */ |
DWORD sh_info; /* Additional section information */ |
DWORD sh_addralign; /* Section alignment */ |
DWORD sh_entsize; /* Entry size if section holds table */ |
}; |
struct elf_symbol_info { |
DWORD st_name; |
DWORD st_value; |
DWORD st_size; |
BYTE st_info; |
BYTE st_other; |
WORD st_shndx; |
}; |
struct elf_rel_info { |
DWORD r_offset; |
DWORD r_info; |
}; |
struct elf_rela_info { |
DWORD r_offset; |
DWORD r_info; |
DWORD r_addend; |
}; |
int Elf_check(struct file_ops *kf); |
int ELF_read_symbols(struct file_ops *kf, |
struct table_info *tables, |
struct symbol_info *syms); |
int ELF_read_section_headers(struct file_ops *kf, |
struct table_info *tables, |
struct section_info *scndata); |
DWORD ELF_read_headers(struct file_ops *kf, |
struct table_info *tables); |
int ELF_relocate_section(struct file_ops *kf, DWORD base, |
struct table_info *tables, |
int n, |
struct section_info *s, |
int sect, |
struct symbol_info *syms, |
struct symbol *import); |
DWORD ELF_import_symbol(struct file_ops *kf, |
int n, |
struct symbol_info *syms, |
char *name, |
int *sect); |
DWORD ELF_load_relocatable(struct file_ops *kf, |
struct table_info *tables, |
int n, |
struct section_info *s, |
DWORD *size); |
void ELF_free_tables(struct file_ops *kf, |
struct table_info *tables, |
struct symbol_info *syms, |
struct section_info *scndata); |
#endif |
/shark/trunk/ports/dynalink/makefile |
---|
0,0 → 1,29 |
# Dynalink |
ifndef BASE |
BASE=../.. |
endif |
include $(BASE)/config/config.mk |
LIBRARY = dynalink |
OBJS_PATH = $(BASE)/dynalink |
OBJS = dynalink.o elf.o |
OTHERINCL += -I$(BASE)/drivers/linuxc26/include -I./include -I. |
OTHERINCL += -I$(BASE)/drivers/pci/include |
OTHERINCL += -I$(BASE)/drivers/input/include |
C_OPT += -D__KERNEL__ -D__i386__ $(CFG_VIDEO_OPT) |
include $(BASE)/config/lib.mk |
clean:: |
rm -f $(OBJS) |
rm -f deps |
/shark/trunk/ports/dynalink/format.h |
---|
0,0 → 1,90 |
//////////////////////////////////////////////////////////////////////// |
// format.h |
// |
// DynaLink for S.H.A.R.K |
// Dynamic ELF object linker. |
// |
// Original code written by Luca Abeni. |
// Adapted by Lex Nahumury 19-7-2006. |
// |
// This is free software; see GPL.txt |
//////////////////////////////////////////////////////////////////////// |
#ifndef __FORMAT_H__ |
#define __FORMAT_H__ |
#define EXTERN_SYMBOL 0xFF00 |
#define COMMON_SYMBOL 0xFF01 |
#define NULL_SYMBOL 0xFFFF |
#define REL_TYPE_ELF_ABSOLUTE 1 |
#define REL_TYPE_RELATIVE 4 |
#define NEED_IMAGE_RELOCATION 1 |
#define NEED_SECTION_RELOCATION 2 |
#define NEED_LOAD_RELOCATABLE 4 |
#define NO_ENTRY 16 |
#define DLL_WITH_STDCALL 32 |
struct reloc_info { |
DWORD offset; |
int symbol; |
int type; |
}; |
struct symbol_info { |
char *name; |
DWORD offset; |
WORD section; |
}; |
struct table_info { |
DWORD section_header; |
WORD num_sections; |
WORD section_header_size; |
WORD flags; |
DWORD symbol; |
DWORD num_symbols; |
DWORD symbol_size; |
DWORD string; |
DWORD string_size; |
DWORD string_buffer; |
char *section_names; |
DWORD section_names_size; |
DWORD image_base; |
DWORD local_bss; |
DWORD local_bss_size; |
/* In PEI, it's a pei extra info */ |
DWORD private_info; |
}; |
struct section_info { |
DWORD base; |
DWORD size; |
DWORD fileptr; |
DWORD filesize; |
int num_reloc; |
struct reloc_info *reloc; |
}; |
/* Only used for ``import'' symbols... */ |
struct symbol { |
char *name; |
DWORD address; |
}; |
struct file_ops |
{ |
int (*file_read)( void *buffer, int len); |
int (*file_seek)( int position, int wence); |
int seek_set; |
int seek_cur; |
int file_offset; |
char* entry_name; |
}; |
#endif |