mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-02 02:10:46 -08:00
* configure.ac [mingw32]: Don't add -Wpointer-sign, and add -Wno-pointer-sign, to keep the noise level down. * nt/mingw-cfg.site (gl_cv_warn_c__Wredundant_decls): Disable -Wredundant-decls, as that produces a lot of noise due to redeclaration of time-related functions by gnulib. * nt/runemacs.c (set_user_model_id): Fix argument type of 'SetCurrentProcessExplicitAppUserModelID'. * src/image.c (x_create_bitmap_from_file) [HAVE_NTGUI]: Don't declare 'dpyinfo', as it is unused. (xpm_load): Fix warnings about pointer signedness. * src/w32proc.c (IsValidLocale, init_winsock): Remove redundant prototypes. (sys_spawnve): Avoid warnings about discarding 'const' qualifier. (sys_select): Provide prototype. (g_b_init_compare_string_w): Move declaration to file scope. * src/w32heap.c (dumped_data_commit): Now static. (FREEABLE_P): Avoid warnings about pointer comparison with integer. (mmap_realloc): Cast to 'char *' for arithmetics on void pointers. * src/w32console.c (ctrl_c_handler, sys_tputs, sys_tgetstr) (evalcost, cmputc, cmcheckmagic, cmcostinit, cmgoto, Wcm_clear): Provide prototypes. * src/w32.c (globals_of_w32, conv_sockaddr_to_lisp): Remove redundant prototypes. (w32_get_internal_run_time, map_w32_filename): Provide prototype. (init_environment, sys_ctime): Avoid warnings about discarding 'const' qualifier. Include utimens.h. (sys_ctime, sys_chdir, sys_creat, sys_fopen, sys_mkdir) (sys_open, sys_rename, sys_rmdir, is_slow_fs, term_winsock) (sys_close, sys_dup2, sys_read, sys_write, sys_localtime): Provide prototypes. (sys_rename_replace): Use %d to avoid compiler warnings. (_wsa_errlist): Make the message text 'const char *', to avoid compilation warnings. (dynlib_reset_last_error): Move prototype to file scope. (w32_get_resource): First argument is now 'const char *'. * src/w32uniscribe.c (syms_of_w32uniscribe): Provide prototype. (otf_features): Second argument is no 'const char *'. * src/w32term.c (free_frame_menubar, x_wm_set_size_hint) (x_set_window_size): Remove redundant prototypes. (XChangeGC, XGetGCValues, w32_draw_underwave) (w32_draw_rectangle, w32_shift_glyphs_for_insert, x_mouse_leave) (x_calc_absolute_position, x_destroy_window): Now static. (menubar_selection_callback): Move prototype to file scope. * src/w32font.c (g_b_init_get_glyph_outline_w): Remove redundant declaration. (w32_to_x_charset): Fix warnings about discarding 'const' qualifier. (w32font_full_name): Fix warnings about implicit conversion of 'float' to 'double'. * src/w32reg.c (w32_get_rdb_resource): Fix warnings about discarding 'const' qualifier. * src/w32menu.c (syms_of_w32menu, globals_of_w32menu) (set_frame_menubar): Remove redundant prototypes. (menubar_selection_callback, w32_menu_display_help): Provide prototypes. (simple_dialog_show): Avoid warnings about discarding 'const' qualifier. * src/w32fns.c (syms_of_w32fns, globals_of_w32fns) (free_frame_menubar, w32_strerror, x_set_menu_bar_lines) (x_set_tool_bar_lines, x_set_internal_border_width): Remove redundant prototypes. (current_popup_menu): Remove redundant declaration. (colormap_t): Member 'name' is now 'const char *'. (add_system_logical_colors_to_map): Fix signed/unsigned warnings. (x_decode_color, x_set_border_pixel) (x_clear_under_internal_border, x_set_name, hook_w32_key) (reset_w32_kbdhook_state, deliver_wm_chars, w32_backtrace): Now static. (w32_load_cursor, w32_key_to_modifier, map_keypad_keys) (w32_msg_worker, w32_last_error): Provide prototypes. (funhook, lookup_vk_code): Avoid warnings about missing parentheses. (x_default_font_parameter, Fw32_notification_notify): Avoid warnings about discarding 'const' qualifier. (Fx_create_frame): Avoid warnings about empty body of 'else'. (x_screen_planes): Ifdef away unused function. (Fx_show_tip): Remove unused variables. (Fw32_battery_status): Avoid warnings about implicit promotion from float to double. (Fw32_notification_notify): Initialize 'timeout'. * src/profiler.c (profiler_cpu_running) [HAVE_ITIMERSPEC]: Only define the TIMER_SETTIME_RUNNING value if it will be used. * src/w32notify.c (send_notifications): Ifdef away an empty if clause. Remove unused variable. (watch_end, watch_completion): Provide prototypes. * src/sound.c (sound_warning) [WINDOWSNT]: Don't define: unused. * src/callproc.c (child_setup, getenv_internal_1) [WINDOWSNT]: Fix warning with pointer signedness. * src/gnutls.c (gnutls_x509_crt_get_signature) (gnutls_alert_send_appropriate) [WINDOWSNT]: Don't define, and don't load them from the GnuTLS library, as they are no longer used. * src/process.c (DATAGRAM_CHAN_P) [!DATAGRAM_SOCKETS]: Don't define, as it's unused. * src/unexw32.c (open_input_file, open_output_file) (close_file_data): Remove redundant prototypes. (_start): provide prototype. (mainCRTStartup): Move prototype to file level. (find_section): Use type-cast to shut up compiler warnings. (offset_to_section, relocate_offset): Now static. (find_section): First argument is now a 'const char *'. (offset_to_section): Ifdef away, as it's unused. * src/w32heap.h (find_section): Adjust prototype. * src/dynlib.c (dynlib_reset_last_error): Provide prototype. * src/dired.c (directory_files_internal_w32_unwind): Avoid warnings about missing prototypes. (is_slow_fs) [WINDOWSNT]: Provide prototype at file level. (directory_files_internal) [WINDOWSNT]: Fix warnings about pointer signedness. * src/fileio.c (Ffile_writable_p, Ffile_regular_p) [WINDOWSNT]: Fix warnings about pointer signedness. * src/filelock.c (WTMP_FILE) [WINDOWSNT]: Don't define, it's unused. * src/sysdep.c (_getpid): Remove redundant prototype. (sys_subshell) [DOS_NT]: Don't define 'status', it's unused. [!MSDOS]: Don't define 'st', it's unused. (init_sys_modes) [DOS_NT]: Don't define 'terminal', it's unused. (str_collate) [WINDOWSNT]: Avoid warnings about pointer signedness. * src/keyboard.c (tty_read_avail_input) [WINDOWSNT]: Don't define n_to_read, as it is not used. (MAX_ENCODED_BYTES) [WINDOWSNT]: Don't define, as it's unused. * src/w32font.h (syms_of_w32font): Remove redundant prototype. * src/xfaces.c (x_display_info) [HAVE_NTGUI]: Remove unused macro. * src/term.c (init_tty) [DOS_NT]: Ifdef away variables that are not used by DOS_NT builds, to avoid compiler warnings. * src/menu.c (current_popup_menu) [HAVE_NTGUI]: Remove redundant declaration. * src/dispnew.c (init_display) [WINDOWSNT]: Use type-cast to shut up compiler warnings. * src/w32term.h (x_set_window_size, x_get_focus_frame) (x_make_frame_visible, x_make_frame_invisible, x_iconify_frame) (x_set_frame_alpha, x_activate_menubar, x_bitmap_icon) (x_free_frame_resources, x_real_positions) (display_x_get_resource): Remove redundant prototypes. * lib-src/ntlib.c (sys_ctime, sys_fopen, sys_chdir, mkostemp) (sys_rename, gettimeofday): Provide prototypes. * lib-src/ntlib.h (getuid, geteuid, mkostemp): Remove redundant declarations. * lib-src/emacsclient.c (w32_getenv): Argument is now 'const char *'. (xstrdup, w32_get_resource, w32_window_app, w32_execvp, ttyname) (close_winsock, initialize_sockets, w32_set_user_model_id) (w32_find_emacs_process, w32_give_focus) [WINDOWSNT]: Add prototypes. (w32_get_resource) [WINDOWSNT]: Fix a warning about signedness difference. (w32_set_user_model_id): Update prototype of SetCurrentProcessExplicitAppUserModelID to avoid compiler warnings. (start_daemon_and_retry_set_socket) [WINDOWSNT]: Use type-cast to shut up compiler warnings. * lib-src/etags.c (MAXPATHLEN) [WINDOWSNT]: Remove unused macro.
331 lines
8 KiB
C
331 lines
8 KiB
C
/* Portable API for dynamic loading.
|
|
|
|
Copyright 2015-2016 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Emacs.
|
|
|
|
GNU Emacs 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 3 of the License, or (at
|
|
your option) any later version.
|
|
|
|
GNU Emacs 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
/* Assume modules are enabled on modern systems... *Yes*, the
|
|
preprocessor macro checks could be more precise. I don't care.
|
|
|
|
If you think the abstraction is too leaky use libltdl (libtool),
|
|
don't reinvent the wheel by fixing this one. */
|
|
|
|
#include <config.h>
|
|
|
|
#include "dynlib.h"
|
|
|
|
#ifdef WINDOWSNT
|
|
|
|
/* MS-Windows systems. */
|
|
|
|
#include <errno.h>
|
|
#include "lisp.h"
|
|
#include "w32common.h" /* for os_subtype */
|
|
#include "w32.h"
|
|
|
|
static BOOL g_b_init_get_module_handle_ex;
|
|
static DWORD dynlib_last_err;
|
|
|
|
/* Some versions of w32api headers only expose the following when
|
|
_WIN32_WINNT is set to higher values that we use. */
|
|
typedef BOOL (WINAPI *GetModuleHandleExA_Proc) (DWORD,LPCSTR,HMODULE*);
|
|
#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
|
# define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
|
|
#endif
|
|
#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
|
|
# define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
|
|
#endif
|
|
|
|
/* This needs to be called at startup to countermand any non-zero
|
|
values recorded by temacs. */
|
|
void dynlib_reset_last_error (void);
|
|
void
|
|
dynlib_reset_last_error (void)
|
|
{
|
|
g_b_init_get_module_handle_ex = 0;
|
|
dynlib_last_err = 0;
|
|
}
|
|
|
|
dynlib_handle_ptr
|
|
dynlib_open (const char *dll_fname)
|
|
{
|
|
HMODULE hdll;
|
|
char dll_fname_local[MAX_UTF8_PATH];
|
|
|
|
if (!dll_fname)
|
|
{
|
|
errno = ENOTSUP;
|
|
return NULL;
|
|
}
|
|
|
|
if (!dll_fname)
|
|
hdll = GetModuleHandle (NULL);
|
|
else
|
|
{
|
|
/* LoadLibrary wants backslashes. */
|
|
strcpy (dll_fname_local, dll_fname);
|
|
unixtodos_filename (dll_fname_local);
|
|
|
|
if (w32_unicode_filenames)
|
|
{
|
|
wchar_t dll_fname_w[MAX_PATH];
|
|
|
|
filename_to_utf16 (dll_fname_local, dll_fname_w);
|
|
hdll = LoadLibraryW (dll_fname_w);
|
|
}
|
|
else
|
|
{
|
|
char dll_fname_a[MAX_PATH];
|
|
|
|
filename_to_ansi (dll_fname_local, dll_fname_a);
|
|
hdll = LoadLibraryA (dll_fname_a);
|
|
}
|
|
}
|
|
|
|
if (!hdll)
|
|
dynlib_last_err = GetLastError ();
|
|
|
|
return (dynlib_handle_ptr) hdll;
|
|
}
|
|
|
|
void *
|
|
dynlib_sym (dynlib_handle_ptr h, const char *sym)
|
|
{
|
|
FARPROC sym_addr = NULL;
|
|
|
|
if (!h || h == INVALID_HANDLE_VALUE || !sym)
|
|
{
|
|
dynlib_last_err = ERROR_INVALID_PARAMETER;
|
|
return NULL;
|
|
}
|
|
|
|
sym_addr = GetProcAddress ((HMODULE) h, sym);
|
|
if (!sym_addr)
|
|
dynlib_last_err = GetLastError ();
|
|
|
|
return (void *)sym_addr;
|
|
}
|
|
|
|
bool
|
|
dynlib_addr (void *addr, const char **fname, const char **symname)
|
|
{
|
|
static char dll_filename[MAX_UTF8_PATH];
|
|
static char addr_str[22];
|
|
static GetModuleHandleExA_Proc s_pfn_Get_Module_HandleExA = NULL;
|
|
char *dll_fn = NULL;
|
|
HMODULE hm_kernel32 = NULL;
|
|
bool result = false;
|
|
HMODULE hm_dll = NULL;
|
|
wchar_t mfn_w[MAX_PATH];
|
|
char mfn_a[MAX_PATH];
|
|
|
|
/* Step 1: Find the handle of the module where ADDR lives. */
|
|
if (os_subtype == OS_9X
|
|
/* Windows NT family version before XP (v5.1). */
|
|
|| ((w32_major_version + (w32_minor_version > 0)) < 6))
|
|
{
|
|
MEMORY_BASIC_INFORMATION mbi;
|
|
|
|
/* According to Matt Pietrek, the module handle is just the base
|
|
address where it's loaded in memory. */
|
|
if (VirtualQuery (addr, &mbi, sizeof(mbi)))
|
|
hm_dll = (HMODULE)mbi.AllocationBase;
|
|
}
|
|
else
|
|
{
|
|
/* Use the documented API when available (XP and later). */
|
|
if (g_b_init_get_module_handle_ex == 0)
|
|
{
|
|
g_b_init_get_module_handle_ex = 1;
|
|
hm_kernel32 = LoadLibrary ("kernel32.dll");
|
|
/* We load the ANSI version of the function because the
|
|
address we pass to it is not an address of a string, but
|
|
an address of a function. So we don't care about the
|
|
Unicode version. */
|
|
s_pfn_Get_Module_HandleExA =
|
|
(GetModuleHandleExA_Proc) GetProcAddress (hm_kernel32,
|
|
"GetModuleHandleExA");
|
|
}
|
|
if (s_pfn_Get_Module_HandleExA)
|
|
{
|
|
DWORD flags = (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
|
/* We don't want to call FreeLibrary at the
|
|
end, because then we'd need to remember
|
|
whether we obtained the handle by this
|
|
method or the above one. */
|
|
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT);
|
|
|
|
if (!s_pfn_Get_Module_HandleExA (flags, addr, &hm_dll))
|
|
{
|
|
dynlib_last_err = GetLastError ();
|
|
hm_dll = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Step 2: Find the absolute file name of the module corresponding
|
|
to the hm_dll handle. */
|
|
if (hm_dll)
|
|
{
|
|
DWORD retval;
|
|
|
|
if (w32_unicode_filenames)
|
|
{
|
|
retval = GetModuleFileNameW (hm_dll, mfn_w, MAX_PATH);
|
|
if (retval > 0 && retval < MAX_PATH
|
|
&& filename_from_utf16 (mfn_w, dll_filename) == 0)
|
|
dll_fn = dll_filename;
|
|
else if (retval == MAX_PATH)
|
|
dynlib_last_err = ERROR_INSUFFICIENT_BUFFER;
|
|
else
|
|
dynlib_last_err = GetLastError ();
|
|
}
|
|
else
|
|
{
|
|
retval = GetModuleFileNameA (hm_dll, mfn_a, MAX_PATH);
|
|
if (retval > 0 && retval < MAX_PATH
|
|
&& filename_from_ansi (mfn_a, dll_filename) == 0)
|
|
dll_fn = dll_filename;
|
|
else if (retval == MAX_PATH)
|
|
dynlib_last_err = ERROR_INSUFFICIENT_BUFFER;
|
|
else
|
|
dynlib_last_err = GetLastError ();
|
|
}
|
|
if (dll_fn)
|
|
{
|
|
dostounix_filename (dll_fn);
|
|
/* We cannot easily produce the function name, since
|
|
typically all of the module functions will be unexported,
|
|
and probably even static, which means the symbols can be
|
|
obtained only if we link against libbfd (and the DLL can
|
|
be stripped anyway). So we just show the address and the
|
|
file name; they can use that with addr2line or GDB to
|
|
recover the symbolic name. */
|
|
sprintf (addr_str, "at 0x%x", (DWORD_PTR)addr);
|
|
*symname = addr_str;
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
*fname = dll_fn;
|
|
return result;
|
|
}
|
|
|
|
const char *
|
|
dynlib_error (void)
|
|
{
|
|
char *error_string = NULL;
|
|
|
|
if (dynlib_last_err)
|
|
{
|
|
error_string = w32_strerror (dynlib_last_err);
|
|
dynlib_last_err = 0;
|
|
}
|
|
|
|
return error_string;
|
|
}
|
|
|
|
int
|
|
dynlib_close (dynlib_handle_ptr h)
|
|
{
|
|
if (!h || h == INVALID_HANDLE_VALUE)
|
|
{
|
|
dynlib_last_err = ERROR_INVALID_PARAMETER;
|
|
return -1;
|
|
}
|
|
/* If the handle is for the main module (the .exe file), it
|
|
shouldn't be passed to FreeLibrary, because GetModuleHandle
|
|
doesn't increment the refcount, but FreeLibrary does decrement
|
|
it. I don't think this should matter for the main module, but
|
|
just in case, we avoid the call here, relying on another call to
|
|
GetModuleHandle to return the same value. */
|
|
if (h == GetModuleHandle (NULL))
|
|
return 0;
|
|
|
|
if (!FreeLibrary ((HMODULE) h))
|
|
{
|
|
dynlib_last_err = GetLastError ();
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#elif defined HAVE_UNISTD_H
|
|
|
|
/* POSIX systems. */
|
|
|
|
#include <dlfcn.h>
|
|
|
|
dynlib_handle_ptr
|
|
dynlib_open (const char *path)
|
|
{
|
|
return dlopen (path, RTLD_LAZY);
|
|
}
|
|
|
|
void *
|
|
dynlib_sym (dynlib_handle_ptr h, const char *sym)
|
|
{
|
|
return dlsym (h, sym);
|
|
}
|
|
|
|
bool
|
|
dynlib_addr (void *ptr, const char **path, const char **sym)
|
|
{
|
|
#ifdef HAVE_DLADDR
|
|
Dl_info info;
|
|
if (dladdr (ptr, &info) && info.dli_fname && info.dli_sname)
|
|
{
|
|
*path = info.dli_fname;
|
|
*sym = info.dli_sname;
|
|
return true;
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
const char *
|
|
dynlib_error (void)
|
|
{
|
|
return dlerror ();
|
|
}
|
|
|
|
/* FIXME: Currently there is no way to unload a module, so this
|
|
function is never used. */
|
|
#if false
|
|
int
|
|
dynlib_close (dynlib_handle_ptr h)
|
|
{
|
|
return dlclose (h) == 0;
|
|
}
|
|
#endif
|
|
|
|
#else
|
|
|
|
#error "No dynamic loading for this system"
|
|
|
|
#endif
|
|
|
|
#if !HAVE_DLFUNC
|
|
# define dlfunc dynlib_sym
|
|
#endif
|
|
|
|
dynlib_function_ptr
|
|
dynlib_func (dynlib_handle_ptr h, const char *sym)
|
|
{
|
|
return (dynlib_function_ptr) dlfunc (h, sym);
|
|
}
|