Пример #1
0
bool application::application_private::setup_modules()
{
	// dll

	// if module path is defined ...

	// TODO: add install path in

	// must provide default buildtin modules, ascii/utf8/basic_marks
	char * mod_env = ew::core::program::getenv("EEDIT_MODULES_LIST"); // TODO: add documentation comma separated list
	if (!mod_env) {
		app_log << "env[EEDIT_MODULES_LIST] is not defined...\n";
		return true;
	}

	app_log << "env[EEDIT_MODULES_LIST] is set to : '" << mod_env << "'\n";

	std::vector<std::string> mod_vec = split(mod_env, ',');

	// module_type(codec, filter, ???)
	// extern "C" dll::module_name() -> char *
	// extern "C" dll::module_type() -> int
	// based on type the module provides other interface see codec.h  , filter.h


	for (auto & libname : mod_vec) {

		auto lib = std::make_unique<ew::core::dll>(libname.c_str());
		app_log << "try to load file '" << libname << "'\n";
		if (lib->load() == false) {
			app_log << "cannot load file '" << libname << "'\n";
			continue;
		}

		bool error = false;
		// TODO lambda over mandatory symbols array
		// extract
		const char * mandatory_symbols[] = { "module_name", "module_version", "module_type", "module_init", "module_quit", "module_depends" };
		for (auto sym : mandatory_symbols) {
			auto ptr = lib->symbol_by_name(sym);
			if (ptr == nullptr) {
				error = true;
				break;
			}
			app_log << "found symbol '" << sym << "'\n";

		}

		if (error == true) {
			continue;
		}

		app_log << libname << " : all mandatory symbols found\n";


		const char * (*modname_fn_ptr)()    = reinterpret_cast<const char * (*)()>(lib->symbol_by_name("module_name"));
		const char * (*modversion_fn_ptr)() = reinterpret_cast<const char * (*)()>(lib->symbol_by_name("module_version"));
		eedit_module_type_e  (*modtype_fn_ptr)()      = reinterpret_cast<eedit_module_type_e (*)()>(lib->symbol_by_name("module_type"));

		// add to application module map
		std::string modname           = modname_fn_ptr();
		std::string modversion        = modversion_fn_ptr();
		eedit_module_type_e  modtype = modtype_fn_ptr();


		app_log << libname << " : modname    : '" << modname << "'\n";
		app_log << libname << " : modversion : '" << modversion << "'\n";
		app_log << libname << " : modtype    : '" << modtype << "'\n";

		if (modtype == MODULE_TYPE_INVALID) {
			error = true;
			app_log << libname << " : invliad modtype\n";
		}

		if (error == false) {

			if (module_map.find(modname) != module_map.end()) {
				error = true;
			}
		}

		if (error == false) {

			eedit_module_init_status_e  (*modinit_fn_ptr)()      = reinterpret_cast<eedit_module_init_status_e (*)()>(lib->symbol_by_name("module_init"));

			eedit_module_init_status_e modinit_ret = modinit_fn_ptr();
			if (modinit_ret != MODULE_INIT_OK) {
				error = true;
				app_log << libname << " : modinit error\n";
			} else {
				app_log << libname << " : modinit ok\n";
			}
		}

		if (error == false) {

			//  allow multiple version at same time ?
			// "modname:version"

			std::string prefix;

			auto modinfo = std::make_unique<module_info_s>();

			modinfo->lib = std::move(lib);

			switch (modtype) {
			case MODULE_TYPE_CODEC:
				prefix = "codec";
				break;
			case MODULE_TYPE_FILTER:
				prefix = "filter";
				break;
			case MODULE_TYPE_EDITOR_MODE:
				prefix = "mode";
				break;
			default:
				error = true;
			}

			if (error == false) {
				module_map[prefix + ":" + modname] = std::move(modinfo);
			}

		}

	}

	for ( const auto & e : module_map) {
		app_log << e.first << "\n";
	}

	// TODO: config:

	// TODO: add config function function
	// load-codec [name]
	// load-codec text/ascii


	return true;
}
Пример #2
0
void *elf_hook(char const *module_filename, void const *module_address, char const *name, void const *substitution)
{
    static size_t pagesize;

    int descriptor;  //file descriptor of shared module

    Elf_Shdr
    *dynsym = NULL,  // ".dynsym" section header
    *rel_plt = NULL,  // ".rel.plt" section header
    *rel_dyn = NULL;  // ".rel.dyn" section header

    Elf_Sym
    *symbol = NULL;  //symbol table entry for symbol named "name"

    Elf_Rel
    *rel_plt_table = NULL,  //array with ".rel.plt" entries
    *rel_dyn_table = NULL;  //array with ".rel.dyn" entries

    size_t
    i,
    name_index,  //index of symbol named "name" in ".dyn.sym"
    rel_plt_amount,  // amount of ".rel.plt" entries
    rel_dyn_amount,  // amount of ".rel.dyn" entries
    *name_address = NULL;  //address of relocation for symbol named "name"

    void *original = NULL;  //address of the symbol being substituted

    if (NULL == module_address || NULL == name || NULL == substitution)
        return original;

    if (!pagesize)
        pagesize = sysconf(_SC_PAGESIZE);

    descriptor = open(module_filename, O_RDONLY);

    if (descriptor < 0)
        return original;

    if (
        section_by_type(descriptor, SHT_DYNSYM, &dynsym) ||  //get ".dynsym" section
        symbol_by_name(descriptor, dynsym, name, &symbol, &name_index) ||  //actually, we need only the index of symbol named "name" in the ".dynsym" table
        section_by_name(descriptor, REL_PLT, &rel_plt) ||  //get ".rel.plt" (for 32-bit) or ".rela.plt" (for 64-bit) section
        section_by_name(descriptor, REL_DYN, &rel_dyn)  //get ".rel.dyn" (for 32-bit) or ".rela.dyn" (for 64-bit) section
       )
    {  //if something went wrong
        free(dynsym);
        free(rel_plt);
        free(rel_dyn);
        free(symbol);
        close(descriptor);

        return original;
    }
//release the data used
    free(dynsym);
    free(symbol);

    rel_plt_table = (Elf_Rel *)(((size_t)module_address) + rel_plt->sh_addr);  //init the ".rel.plt" array
    rel_plt_amount = rel_plt->sh_size / sizeof(Elf_Rel);  //and get its size

    rel_dyn_table = (Elf_Rel *)(((size_t)module_address) + rel_dyn->sh_addr);  //init the ".rel.dyn" array
    rel_dyn_amount = rel_dyn->sh_size / sizeof(Elf_Rel);  //and get its size
//release the data used
    free(rel_plt);
    free(rel_dyn);
//and descriptor
    close(descriptor);
//now we've got ".rel.plt" (needed for PIC) table and ".rel.dyn" (for non-PIC) table and the symbol's index
    for (i = 0; i < rel_plt_amount; ++i)  //lookup the ".rel.plt" table
        if (ELF_R_SYM(rel_plt_table[i].r_info) == name_index)  //if we found the symbol to substitute in ".rel.plt"
        {
            original = (void *)*(size_t *)(((size_t)module_address) + rel_plt_table[i].r_offset);  //save the original function address
            *(size_t *)(((size_t)module_address) + rel_plt_table[i].r_offset) = (size_t)substitution;  //and replace it with the substitutional

            break;  //the target symbol appears in ".rel.plt" only once
        }

    if (original)
        return original;
//we will get here only with 32-bit non-PIC module
    for (i = 0; i < rel_dyn_amount; ++i)  //lookup the ".rel.dyn" table
        if (ELF_R_SYM(rel_dyn_table[i].r_info) == name_index)  //if we found the symbol to substitute in ".rel.dyn"
        {
            name_address = (size_t *)(((size_t)module_address) + rel_dyn_table[i].r_offset);  //get the relocation address (address of a relative CALL (0xE8) instruction's argument)

            if (!original)
                original = (void *)(*name_address + (size_t)name_address + sizeof(size_t));  //calculate an address of the original function by a relative CALL (0xE8) instruction's argument

            mprotect((void *)(((size_t)name_address) & (((size_t)-1) ^ (pagesize - 1))), pagesize, PROT_READ | PROT_WRITE);  //mark a memory page that contains the relocation as writable

            if (errno)
                return NULL;

            *name_address = (size_t)substitution - (size_t)name_address - sizeof(size_t);  //calculate a new relative CALL (0xE8) instruction's argument for the substitutional function and write it down

            mprotect((void *)(((size_t)name_address) & (((size_t)-1) ^ (pagesize - 1))), pagesize, PROT_READ | PROT_EXEC);  //mark a memory page that contains the relocation back as executable

            if (errno)  //if something went wrong
            {
                *name_address = (size_t)original - (size_t)name_address - sizeof(size_t);  //then restore the original function address

                return NULL;
            }
        }

    return original;
}
Пример #3
0
void ExecFileParser::find_NOPs() {
    try { NOP_symbols.push_back(symbol_by_name("_TRaP_Linux_PaddingBytes_text").start); }
    catch (std::out_of_range e) {}
    sort(NOP_symbols.begin(), NOP_symbols.end());
}