[syslinux] [PATCH 3/5] lib/sys/module: Add support for weak symbols

Matt Fleming matt at console-pimps.org
Mon Jul 16 13:32:25 PDT 2012


From: Matt Fleming <matt.fleming at intel.com>

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 at intel.com>
---
 com32/lib/sys/module/common.c     |   10 +++++++++-
 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 19742e6..002b733 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 dbb5afe..b220e1a 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
-- 
1.7.4.4




More information about the Syslinux mailing list