diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-07-12 17:39:53 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-07-20 10:20:18 +0100 |
commit | 373a42433c4bea38d4d93ee749bd4d7f19bded51 (patch) | |
tree | 3a5c905b995521ce8279058f6216d7a1f157bece | |
parent | b93e6bc9bdafc9fa2dc8709dc97fa5e598c7e94d (diff) | |
download | syslinux-373a42433c4bea38d4d93ee749bd4d7f19bded51.tar.gz syslinux-373a42433c4bea38d4d93ee749bd4d7f19bded51.tar.xz syslinux-373a42433c4bea38d4d93ee749bd4d7f19bded51.zip |
lib/sys/module: Add support for weak symbols
We need a means of allowing Syslinux derivative-specific functions to
remain unresolved when there is no implementation for them. For
example, unload_pxe() is referenced by common code in com32/lib, but
is only implemented for PXELINUX. By marking unload_pxe() as __weak we
can substitute references with the undefined_symbol() function for
SYSLINUX, EXTLINUX and ISOLINUX. Provided that those references are
never executed everything works fine. However, if code calls actually
calls unload_pxe() from SYSLINUX, EXTLINUX or ISOLINUX an error
message is displayed and execution is halted.
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r-- | com32/lib/sys/module/common.c | 10 | ||||
-rw-r--r-- | com32/lib/sys/module/elf_module.c | 15 |
2 files changed, 22 insertions, 3 deletions
diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c index 19742e65..002b733a 100644 --- a/com32/lib/sys/module/common.c +++ b/com32/lib/sys/module/common.c @@ -321,7 +321,7 @@ int check_symbols(struct elf_module *module) crt_name = module->str_table + crt_sym->st_name; strong_count = 0; - weak_count = 0; + weak_count = (ELF32_ST_BIND(crt_sym->st_info) == STB_WEAK); for_each_module(crt_module) { @@ -345,6 +345,14 @@ int check_symbols(struct elf_module *module) if (crt_sym->st_shndx == SHN_UNDEF) { // We have an undefined symbol + // + // We use the weak_count to differentiate + // between Syslinux-derivative-specific + // functions. For example, unload_pxe() is + // only provided by PXELINUX, so we mark it as + // __weak and replace it with a reference to + // undefined_symbol() on SYSLINUX, EXTLINUX, + // and ISOLINUX. See perform_relocations(). if (strong_count == 0 && weak_count == 0) { DBG_PRINT("Symbol %s is undefined\n", crt_name); diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c index dbb5afed..b220e1ad 100644 --- a/com32/lib/sys/module/elf_module.c +++ b/com32/lib/sys/module/elf_module.c @@ -11,6 +11,7 @@ #include <stdio.h> #include <elf.h> #include <dprintf.h> +#include <core.h> #include <linux/list.h> #include <sys/module.h> @@ -238,6 +239,11 @@ static int prepare_dynlinking(struct elf_module *module) { return 0; } +void undefined_symbol(void) +{ + printf("Error: An undefined symbol was referenced\n"); + kaboom(); +} static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { Elf32_Word *dest = module_get_absolute(rel->r_offset, module); @@ -263,11 +269,16 @@ static int perform_relocation(struct elf_module *module, Elf32_Rel *rel) { &sym_module); if (sym_def == NULL) { - // This should never happen DBG_PRINT("Cannot perform relocation for symbol %s\n", module->str_table + sym_ref->st_name); - return -1; + if (ELF32_ST_BIND(sym_ref->st_info) != STB_WEAK) + return -1; + + // This must be a derivative-specific + // function. We're OK as long as we never + // execute the function. + sym_def = global_find_symbol("undefined_symbol", &sym_module); } // Compute the absolute symbol virtual address |