give embedded modules a helping hand by backing up and restoring their global variables when they are loaded and unloaded
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@56092 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
a6cbe5d651
commit
1bec2f5bfa
|
@ -34,11 +34,13 @@ $(LOADABLE_MODS:%=%.so): ASTCFLAGS+=-fPIC
|
||||||
$(LOADABLE_MODS:%=%.so): LIBS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LIB))
|
$(LOADABLE_MODS:%=%.so): LIBS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LIB))
|
||||||
$(LOADABLE_MODS:%=%.so): ASTLDFLAGS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LDFLAGS))
|
$(LOADABLE_MODS:%=%.so): ASTLDFLAGS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LDFLAGS))
|
||||||
|
|
||||||
|
$(EMBEDDED_MODS:%=%.o): ASTCFLAGS+=-DEMBEDDED_MODULE=$*
|
||||||
|
|
||||||
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(C_MODS))): %.so: %.o
|
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(C_MODS))): %.so: %.o
|
||||||
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(CC_MODS))): %.so: %.oo
|
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(CC_MODS))): %.so: %.oo
|
||||||
|
|
||||||
modules.link: $(addsuffix .o,$(filter $(EMBEDDED_MODS),$(C_MODS)))
|
modules.link: $(addsuffix .eo,$(filter $(EMBEDDED_MODS),$(C_MODS)))
|
||||||
modules.link: $(addsuffix .oo,$(filter $(EMBEDDED_MODS),$(CC_MODS)))
|
modules.link: $(addsuffix .eoo,$(filter $(EMBEDDED_MODS),$(CC_MODS)))
|
||||||
|
|
||||||
.PHONY: clean uninstall _all
|
.PHONY: clean uninstall _all
|
||||||
|
|
||||||
|
@ -64,11 +66,11 @@ endif
|
||||||
|
|
||||||
modules.link:
|
modules.link:
|
||||||
@rm -f $@
|
@rm -f $@
|
||||||
@for file in $(patsubst %,$(SUBDIR)/%,$(filter %.o,$^)); do echo "INPUT (../$${file})" >> $@; done
|
@for file in $(patsubst %,$(SUBDIR)/%,$(filter %.eo %.eoo,$^)); do echo "INPUT (../$${file})" >> $@; done
|
||||||
@for file in $(patsubst %,$(SUBDIR)/%,$(filter-out %.o,$^)); do echo "INPUT (../$${file})" >> $@; done
|
@for file in $(patsubst %,$(SUBDIR)/%,$(filter-out %.eo %.eoo,$^)); do echo "INPUT (../$${file})" >> $@; done
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
rm -f *.so *.o *.oo
|
rm -f *.so *.o *.oo *.eo *.eoo
|
||||||
rm -f .*.o.d .*.oo.d
|
rm -f .*.o.d .*.oo.d
|
||||||
rm -f modules.link
|
rm -f modules.link
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,22 @@ else
|
||||||
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
%.o: %.i
|
||||||
|
$(ECHO_PREFIX) echo " [CC] $< -> $@"
|
||||||
|
ifeq ($(AST_DEVMODE),yes)
|
||||||
|
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS) -MMD -MT $@ -MF .$(subst /,_,$@).d -MP
|
||||||
|
else
|
||||||
|
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
%.i: %.c
|
||||||
|
$(ECHO_PREFIX) echo " [CC] $< -> $@"
|
||||||
|
ifeq ($(AST_DEVMODE),yes)
|
||||||
|
$(CMD_PREFIX) $(CC) -o $@ -E $< $(PTHREAD_CFLAGS) $(ASTCFLAGS) -MMD -MT $@ -MF .$(subst /,_,$@).d -MP
|
||||||
|
else
|
||||||
|
$(CMD_PREFIX) $(CC) -o $@ -E $< $(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
%.o: %.s
|
%.o: %.s
|
||||||
$(ECHO_PREFIX) echo " [AS] $< -> $@"
|
$(ECHO_PREFIX) echo " [AS] $< -> $@"
|
||||||
ifeq ($(AST_DEVMODE),yes)
|
ifeq ($(AST_DEVMODE),yes)
|
||||||
|
@ -76,6 +92,18 @@ endif
|
||||||
$(ECHO_PREFIX) echo " [LDXX] $^ -> $@"
|
$(ECHO_PREFIX) echo " [LDXX] $^ -> $@"
|
||||||
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $^ $(PTHREAD_LIBS) $(LIBS)
|
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $^ $(PTHREAD_LIBS) $(LIBS)
|
||||||
|
|
||||||
|
%.eo: %.o
|
||||||
|
$(ECHO_PREFIX) echo " [EMBED] $< -> $@"
|
||||||
|
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/make_linker_eo_script $* > .$@.ld
|
||||||
|
$(CMD_PREFIX) $(LD) -r -T .$@.ld -o $@ $<
|
||||||
|
$(CMD_PREFIX) rm -f .$@.ld
|
||||||
|
|
||||||
|
%.eoo: %.o
|
||||||
|
$(ECHO_PREFIX) echo " [EMBED] $< -> $@"
|
||||||
|
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/make_linker_eo_script $* > .$@.ld
|
||||||
|
$(CMD_PREFIX) $(LD) -r -T .$@.ld -o $@ $<
|
||||||
|
$(CMD_PREFIX) rm -f .$@.ld
|
||||||
|
|
||||||
%: %.o
|
%: %.o
|
||||||
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
|
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
|
||||||
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $^ $(PTHREAD_LIBS) $(LIBS)
|
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $^ $(PTHREAD_LIBS) $(LIBS)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
SECTIONS {
|
||||||
|
.text : { *(.text) }
|
||||||
|
.data : { __${1}_data_start = . ; *(.data) __${1}_data_end = . ;}
|
||||||
|
.rodata : { *(.rodata*) }
|
||||||
|
.bss : { __${1}_bss_start = . ; *(.bss) __${1}_bss_end = . ;}
|
||||||
|
.debug_abbrev : { *(.debug_abbrev) }
|
||||||
|
.debug_info : { *(.debug_info) }
|
||||||
|
.debug_line : { *(.debug_line) }
|
||||||
|
.debug_macinfo : { *(.debug_macinfo) }
|
||||||
|
.dtors : { *(.dtors) }
|
||||||
|
.ctors : { *(.ctors) }
|
||||||
|
.data.rel.local : { *(.data.rel.local) }
|
||||||
|
.data.rel.ro.local : { *(.data.rel.ro.local) }
|
||||||
|
.debug_frame : { *(.debug_frame) }
|
||||||
|
.eh_frame : { *(.eh_frame) }
|
||||||
|
.debug_loc : { *(.debug_loc) }
|
||||||
|
.debug_pubname : { *(.debug_pubname) }
|
||||||
|
.debug_aranges : { *(.debug_aranges) }
|
||||||
|
.debug_ranges : { *(.debug_ranges) }
|
||||||
|
.debug_str : { *(.debug_str) }
|
||||||
|
.comment : { *(.comment) }
|
||||||
|
.note.GNU-stack : { *(.note.GNU-stack) }
|
||||||
|
}
|
||||||
|
EOF
|
|
@ -192,6 +192,8 @@ struct ast_module_info {
|
||||||
enum ast_module_load_result (*load)(void); /* register stuff etc. Optional. */
|
enum ast_module_load_result (*load)(void); /* register stuff etc. Optional. */
|
||||||
int (*reload)(void); /* config etc. Optional. */
|
int (*reload)(void); /* config etc. Optional. */
|
||||||
int (*unload)(void); /* unload. called with the module locked */
|
int (*unload)(void); /* unload. called with the module locked */
|
||||||
|
int (*backup_globals)(void); /* for embedded modules, backup global data */
|
||||||
|
void (*restore_globals)(void); /* for embedded modules, restore global data */
|
||||||
const char *name; /* name of the module for loader reference and CLI commands */
|
const char *name; /* name of the module for loader reference and CLI commands */
|
||||||
const char *description; /* user friendly description of the module. */
|
const char *description; /* user friendly description of the module. */
|
||||||
|
|
||||||
|
@ -253,6 +255,75 @@ void ast_module_unref(struct ast_module *);
|
||||||
and populated at the end of the module's source file... */
|
and populated at the end of the module's source file... */
|
||||||
const static __attribute__((unused)) struct ast_module_info *ast_module_info;
|
const static __attribute__((unused)) struct ast_module_info *ast_module_info;
|
||||||
|
|
||||||
|
#if defined(EMBEDDED_MODULE)
|
||||||
|
|
||||||
|
#define make_var_sub(mod, type) __ ## mod ## _ ## type
|
||||||
|
#define make_var(mod, type) make_var_sub(mod, type)
|
||||||
|
|
||||||
|
extern void make_var(EMBEDDED_MODULE, bss_start);
|
||||||
|
extern void make_var(EMBEDDED_MODULE, bss_end);
|
||||||
|
extern void make_var(EMBEDDED_MODULE, data_start);
|
||||||
|
extern void make_var(EMBEDDED_MODULE, data_end);
|
||||||
|
|
||||||
|
static void * __attribute__((section(".embed_module"))) __global_backup;
|
||||||
|
|
||||||
|
static int __backup_globals(void)
|
||||||
|
{
|
||||||
|
size_t data_size = & make_var(EMBEDDED_MODULE, data_end) - & make_var(EMBEDDED_MODULE, data_start);
|
||||||
|
|
||||||
|
if (__global_backup)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(__global_backup = ast_malloc(data_size)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(__global_backup, & make_var(EMBEDDED_MODULE, data_start), data_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __restore_globals(void)
|
||||||
|
{
|
||||||
|
size_t data_size = & make_var(EMBEDDED_MODULE, data_end) - & make_var(EMBEDDED_MODULE, data_start);
|
||||||
|
size_t bss_size = & make_var(EMBEDDED_MODULE, bss_end) - & make_var(EMBEDDED_MODULE, bss_start);
|
||||||
|
|
||||||
|
if (bss_size)
|
||||||
|
memset(& make_var(EMBEDDED_MODULE, bss_start), 0, bss_size);
|
||||||
|
|
||||||
|
if (!data_size || !__global_backup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(& make_var(EMBEDDED_MODULE, data_start), __global_backup, data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...) \
|
||||||
|
static struct ast_module_info __mod_info = { \
|
||||||
|
.backup_globals = __backup_globals, \
|
||||||
|
.restore_globals = __restore_globals, \
|
||||||
|
.name = AST_MODULE, \
|
||||||
|
.flags = flags_to_set, \
|
||||||
|
.description = desc, \
|
||||||
|
.key = keystr, \
|
||||||
|
fields \
|
||||||
|
}; \
|
||||||
|
static void __attribute__ ((constructor)) __reg_module(void) \
|
||||||
|
{ \
|
||||||
|
ast_module_register(&__mod_info); \
|
||||||
|
} \
|
||||||
|
static void __attribute__ ((destructor)) __unreg_module(void) \
|
||||||
|
{ \
|
||||||
|
ast_module_unregister(&__mod_info); \
|
||||||
|
} \
|
||||||
|
const static struct ast_module_info *ast_module_info = &__mod_info
|
||||||
|
|
||||||
|
#undef make_var
|
||||||
|
#undef make_var_sub
|
||||||
|
|
||||||
|
#else /* !defined(EMBEDDED_MODULE) */
|
||||||
|
|
||||||
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...) \
|
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...) \
|
||||||
static struct ast_module_info __mod_info = { \
|
static struct ast_module_info __mod_info = { \
|
||||||
.name = AST_MODULE, \
|
.name = AST_MODULE, \
|
||||||
|
@ -271,6 +342,8 @@ const static __attribute__((unused)) struct ast_module_info *ast_module_info;
|
||||||
} \
|
} \
|
||||||
const static struct ast_module_info *ast_module_info = &__mod_info
|
const static struct ast_module_info *ast_module_info = &__mod_info
|
||||||
|
|
||||||
|
#endif /* !defined(EMBEDDED_MODULE) */
|
||||||
|
|
||||||
#define AST_MODULE_INFO_STANDARD(keystr, desc) \
|
#define AST_MODULE_INFO_STANDARD(keystr, desc) \
|
||||||
AST_MODULE_INFO(keystr, AST_MODFLAG_DEFAULT, desc, \
|
AST_MODULE_INFO(keystr, AST_MODFLAG_DEFAULT, desc, \
|
||||||
.load = load_module, \
|
.load = load_module, \
|
||||||
|
|
|
@ -483,6 +483,9 @@ int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode f
|
||||||
if (!error)
|
if (!error)
|
||||||
ast_update_use_count();
|
ast_update_use_count();
|
||||||
|
|
||||||
|
if (!error && !mod->lib)
|
||||||
|
mod->info->restore_globals();
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,6 +630,11 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
|
||||||
return AST_MODULE_LOAD_DECLINE;
|
return AST_MODULE_LOAD_DECLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mod->lib && mod->info->backup_globals()) {
|
||||||
|
ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
|
||||||
|
return AST_MODULE_LOAD_DECLINE;
|
||||||
|
}
|
||||||
|
|
||||||
ast_clear_flag(mod, FLAG_DECLINED);
|
ast_clear_flag(mod, FLAG_DECLINED);
|
||||||
|
|
||||||
if (mod->info->load)
|
if (mod->info->load)
|
||||||
|
|
Loading…
Reference in New Issue