/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Test-code for Kernel-Modules with GRUB - ELF-Relocation by Soeren Bleikertz This is just for demonstration and learning. I won't explain how relocation works. Please read the ELF-specifications! http://sac.cc || http://osdev.de || http://soeren.geekgate.org works more or less. not fully tested! any questions or comments? */ #include #include #include #include #include #include #include #include #include //FATAL ERROR #define FAT_ERROR(s) \ do { \ perror(s); \ exit(-1); \ } while(1); #define ESUCCESS 0 #define EFAILURE -1 #define ELF_MAGIC "\x7f""ELF" #define MAX_SYMS 255 #define ENTRY_FUNC "mod_init" /* TEST-FUNCTION */ /* test.c - I use this small source for relocation-testing. just compile it with gcc -c test.c int lala(int *a) { *a = 2; return 0; } static void mod_init(void) { char *bla = "MOD_INIT!!!!\n"; foo(); bar(bla); } void hoo(void) { int bla; bla = 2; bla *= 2; } EOF */ void foo(void) { printf("\nfoo() said: Hello\n"); } void bar(char *b) { printf("\nbar() said: %s(%p)\n", b, b); } /* ENTRY-STUFF */ typedef struct entry { //Elf32_Shdr *shdr; ulong addr; } entry_t; entry_t main_entry; /* SYMBOL-STUFF */ typedef struct sym_ent { char *name; ulong addr; } sym_t; // symbol table from module sym_t sym_tab_mod[MAX_SYMS]; int sym_count; // global symbol-table sym_t sym_tab[] = { { "foo", (ulong)foo }, { "bar", (ulong)bar } //test }; // get addr for a symbol int sym_lookup(char *sym, ulong *sym_val) { int sym_nr = sizeof(sym_tab)/sizeof(sym_t); int i; for (i=0; i0 int sym_valid_name(Elf32_Sym *symt) { if ((symt->st_name != 0) && ((ELF32_ST_BIND(symt->st_info) == STB_LOCAL) || (ELF32_ST_BIND(symt->st_info) == STB_GLOBAL)) && (symt->st_size > 0) && (ELF32_ST_TYPE(symt->st_info) == STT_FUNC)) return ESUCCESS; return EFAILURE; } // create symbol-table from mod int sym_tab_create(char *data) { Elf32_Ehdr *elfhdr = (Elf32_Ehdr*)data; int nr_entry, i, nr_shdr = elfhdr->e_shnum; Elf32_Shdr *shdr, *off_shdr = (Elf32_Shdr*)(data + elfhdr->e_shoff); Elf32_Sym *symt; char *strtab; ulong text_ofs; sym_count = 0; //search Symbol-Table for (i=0; i < nr_shdr; i++) { if (off_shdr[i].sh_type == SHT_SYMTAB) shdr = &off_shdr[i]; } printf("Debug: symtab: %p\n", shdr->sh_offset); symt = (Elf32_Sym*)(data+shdr->sh_offset); nr_entry = shdr->sh_size/sizeof(Elf32_Sym); //search String-Table for (i=0; i < nr_shdr; i++) { if ((off_shdr[i].sh_type == SHT_STRTAB) && !(off_shdr[i].sh_flags) && (elfhdr->e_shstrndx != i)) shdr = &off_shdr[i]; } printf("Debug: strtab: %p\n", shdr->sh_offset); strtab = (char*)(data+shdr->sh_offset); //search .text for (i=0;ie_ident[EI_MAG0], ELF_MAGIC, 4) || (elfhdr->e_ident[EI_CLASS] != ELFCLASS32) || (elfhdr->e_ident[EI_DATA] != ELFDATA2LSB) || (elfhdr->e_type != ET_REL) || (elfhdr->e_machine != EM_386) || (elfhdr->e_version != 1)) return EFAILURE; return ESUCCESS; } int kmod_load(char *data, char *modname) { if (kmod_check(data) == EFAILURE) { printf("Error: loading of '%s' failed!\n", modname); return EFAILURE; } printf("Debug: Valid ELF\n"); return ESUCCESS; } int kmod_elf_sym(char *data, uint symidx, ulong *sym_val, ulong symtab_sect) { Elf32_Ehdr *elfhdr; Elf32_Shdr *shdr, *sym_sec, *tmp; Elf32_Sym *symtab; char *sym, *strtab; int i; elfhdr = (Elf32_Ehdr*)data; shdr = (Elf32_Shdr*)(data + elfhdr->e_shoff); //search strtab for (i=0; i < elfhdr->e_shnum; i++) { if ((shdr[i].sh_type == SHT_STRTAB) && !(shdr[i].sh_flags) && (elfhdr->e_shstrndx != i)) break; } tmp = &shdr[i]; strtab = (char*)(data+tmp->sh_offset); printf("Debug: StrTab-ofs: %p\n", tmp->sh_offset); sym_sec = (Elf32_Shdr*)&shdr[symtab_sect]; printf("Debug: SymTab-Sect: %lu, SymTab-IDX: %d\n", symtab_sect, symidx); if (symidx > sym_sec->sh_size/sym_sec->sh_entsize) return EFAILURE; if (sym_sec->sh_type != SHT_SYMTAB) { printf("Error: Not a SymTab!\n"); return EFAILURE; } symtab = (Elf32_Sym*)(data + sym_sec->sh_offset); printf("Debug: Symtab-ofs: %p\n", sym_sec->sh_offset); if (!symtab[symidx].st_shndx) { //external symbol printf("Debug: External Symbol\n"); sym = &strtab[symtab[symidx].st_name]; printf("Debug: Symbol: \"%s\"\n", sym); if (sym_lookup(sym, sym_val) == EFAILURE) { printf("Error: Unknown Symbol!\n"); return EFAILURE; } printf("Debug: ext. Symbol-Addr: %p\n", *sym_val); } else { //internal symbol printf("Debug: Internal Symbol\n"); shdr = (Elf32_Shdr*)(data + elfhdr->e_shoff + elfhdr->e_shentsize * symidx); *sym_val = symtab->st_value + (ulong)(data + shdr->sh_offset); printf("Debug: int. Symbol-Addr: %p, Symtab-Value: %d\n", *sym_val, symtab->st_value); } return ESUCCESS; } int kmod_elf_reloc_do(char *data, Elf32_Rel *rel, Elf32_Shdr *shdr) { ulong *rel_addr; Elf32_Shdr *rel_sect; //section for relocation Elf32_Ehdr *elfhdr; ulong sym_val; //ELf-hdr elfhdr = (Elf32_Ehdr*)data; //section for relocation rel_sect = (Elf32_Shdr*)(data + elfhdr->e_shoff + elfhdr->e_shentsize * shdr->sh_info); //relocation addr rel_addr = (ulong*)(data + rel_sect->sh_offset + rel->r_offset); printf("Debug: rel_offset: 0x%x, SYM: 0x%x, TYPE: 0x%x\n", rel->r_offset, ELF32_R_SYM(rel->r_info), ELF32_R_TYPE(rel->r_info)); printf("Debug: sect_for_rel_ofs: %p, SymTab-Sect-IDX: %d\n", rel_sect->sh_offset, shdr->sh_link); // get addr of symbol if (kmod_elf_sym(data, ELF32_R_SYM(rel->r_info), &sym_val, shdr->sh_link) == EFAILURE) return EFAILURE; // omg.. switch (ELF32_R_TYPE(rel->r_info)) { case R_386_32: *rel_addr = sym_val + *rel_addr; printf("Debug: R_386_32: rel_addr: %p(%p)\n", rel_addr, *rel_addr); break; case R_386_PC32: *rel_addr = sym_val + *rel_addr - (ulong)rel_addr; printf("Debug: R_386_PC32: rel_addr: %p(%p)\n", rel_addr, *rel_addr); break; default: printf("Error: wrong Reloc-Type\n"); return EFAILURE; } return ESUCCESS; } int kmod_elf_reloc(char *data) { Elf32_Shdr *shdr; Elf32_Ehdr *ehdr; Elf32_Rel *rel; uint shdr_nr, i=0, shdr_ent_sz, rel_sz=0, j; ulong entry=0; char *bss; ehdr = (Elf32_Ehdr*)data; shdr_nr = ehdr->e_shnum; shdr_ent_sz = ehdr->e_shentsize; shdr = (Elf32_Shdr*)(data+ehdr->e_shoff); // search BBS while((shdr[i].sh_type != SHT_NOBITS) && (i rel_type: %d, rel_ent_nr: %d\n", i, shdr[i].sh_offset, rel_sz, shdr[i].sh_type, shdr[i].sh_size/rel_sz); for(j=0;j Done!\n\n"); printf("[Create SymTab]\n"); sym_tab_create(elf_ptr); printf("> Done!\n\n"); //relocation bzero(&main_entry, sizeof(entry_t)); printf("[Relocation]\n"); if (kmod_elf_reloc(elf_ptr)==EFAILURE) { printf("Error: Relocation failed!\n"); return EFAILURE; } else printf("> Done!\n\n"); printf("[Start]\n"); ble = (void*)main_entry.addr; printf("Debug: entry: %p\n", main_entry.addr); printf("\n"); ble(); printf(" Done!\n"); free(elf_ptr); return 0; }
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß