void load_module (char * file) { FILE* handle; char * error; HOOKED * hook; handle = dlopen (file, RTLD_LAZY); if (!handle) { fprintf (stderr, "Couldn't load %s: %s\n", file, dlerror ()); exit(1); } dlerror(); hook = (HOOKED *) dlsym (handle, "hook"); hook->size = ((int (*)()) dlsym(handle,"hook_size"))(); if ((error = dlerror ())) { fprintf (stderr, "Couldn't initialize the hook function.\n\t%s\n", error); exit(1); } load_hook (hook); }
/* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, grub_addr_t *base, grub_size_t *size) { grub_addr_t load_base = (grub_addr_t) -1ULL; grub_size_t load_size = 0; grub_err_t err; auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook); int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook) { grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook; grub_addr_t load_addr; int do_load = 1; load_addr = phdr->p_paddr; if (load_hook && load_hook (phdr, &load_addr, &do_load)) return 1; if (! do_load) return 0; if (load_addr < load_base) load_base = load_addr; grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", (unsigned long long) load_addr, (unsigned long long) phdr->p_memsz); if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) { grub_error_push (); return grub_error (GRUB_ERR_BAD_OS, "invalid offset in program header"); } if (phdr->p_filesz) { grub_ssize_t read; read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); if (read != (grub_ssize_t) phdr->p_filesz) { /* XXX How can we free memory from `load_hook'? */ grub_error_push (); return grub_error (GRUB_ERR_BAD_OS, "couldn't read segment from file: " "wanted 0x%lx bytes; read 0x%lx bytes", phdr->p_filesz, read); } } if (phdr->p_filesz < phdr->p_memsz) grub_memset ((void *) (long) (load_addr + phdr->p_filesz), 0, phdr->p_memsz - phdr->p_filesz); load_size += phdr->p_memsz; return 0; }