mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +00:00 
			
		
		
		
	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:
		| @@ -34,11 +34,13 @@ $(LOADABLE_MODS:%=%.so): ASTCFLAGS+=-fPIC | ||||
| $(LOADABLE_MODS:%=%.so): LIBS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LIB)) | ||||
| $(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),$(CC_MODS))): %.so: %.oo | ||||
|  | ||||
| modules.link: $(addsuffix .o,$(filter $(EMBEDDED_MODS),$(C_MODS))) | ||||
| modules.link: $(addsuffix .oo,$(filter $(EMBEDDED_MODS),$(CC_MODS))) | ||||
| modules.link: $(addsuffix .eo,$(filter $(EMBEDDED_MODS),$(C_MODS))) | ||||
| modules.link: $(addsuffix .eoo,$(filter $(EMBEDDED_MODS),$(CC_MODS))) | ||||
|  | ||||
| .PHONY: clean uninstall _all | ||||
|  | ||||
| @@ -64,11 +66,11 @@ endif | ||||
|  | ||||
| modules.link: | ||||
| 	@rm -f $@ | ||||
| 	@for file in $(patsubst %,$(SUBDIR)/%,$(filter %.o,$^)); do echo "INPUT (../$${file})" >> $@; done | ||||
| 	@for file in $(patsubst %,$(SUBDIR)/%,$(filter-out %.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 %.eo %.eoo,$^)); do echo "INPUT (../$${file})" >> $@; done | ||||
|  | ||||
| clean:: | ||||
| 	rm -f *.so *.o *.oo | ||||
| 	rm -f *.so *.o *.oo *.eo *.eoo | ||||
| 	rm -f .*.o.d .*.oo.d | ||||
| 	rm -f modules.link | ||||
|  | ||||
|   | ||||
| @@ -44,6 +44,22 @@ else | ||||
| 	$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS) | ||||
| 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 | ||||
| 	$(ECHO_PREFIX) echo "   [AS] $< -> $@" | ||||
| ifeq ($(AST_DEVMODE),yes) | ||||
| @@ -76,6 +92,18 @@ endif | ||||
| 	$(ECHO_PREFIX) echo "   [LDXX] $^ -> $@" | ||||
| 	$(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 | ||||
| 	$(ECHO_PREFIX) echo "   [LD] $^ -> $@" | ||||
| 	$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $^ $(PTHREAD_LIBS) $(LIBS) | ||||
|   | ||||
							
								
								
									
										27
									
								
								build_tools/make_linker_eo_script
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										27
									
								
								build_tools/make_linker_eo_script
									
									
									
									
									
										Executable file
									
								
							| @@ -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. */ | ||||
| 	int (*reload)(void);			/* config etc. Optional. */ | ||||
| 	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 *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... */ | ||||
| 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...)	\ | ||||
| 	static struct ast_module_info __mod_info = {		\ | ||||
| 		.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 | ||||
|  | ||||
| #endif /* !defined(EMBEDDED_MODULE) */ | ||||
|  | ||||
| #define AST_MODULE_INFO_STANDARD(keystr, desc)		\ | ||||
| 	AST_MODULE_INFO(keystr, AST_MODFLAG_DEFAULT, desc,	\ | ||||
| 			.load = load_module,			\ | ||||
|   | ||||
| @@ -483,6 +483,9 @@ int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode f | ||||
| 	if (!error) | ||||
| 		ast_update_use_count(); | ||||
|  | ||||
| 	if (!error && !mod->lib) | ||||
| 		mod->info->restore_globals(); | ||||
|  | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| @@ -627,6 +630,11 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi | ||||
| 		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); | ||||
|  | ||||
| 	if (mod->info->load) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user