Re: Modular fb-devs - unresolved symbols.

Keith Owens (kaos@ocs.com.au)
Sat, 11 Dec 1999 22:17:25 +1100


On 10 Dec 1999 21:50:52 -0600,
Peter Samuelson <peter@wire.cadcamlab.org> wrote:
>It would be really nice if there were some easy way for EXPORT_SYMBOL()
>to tell the linker "do not repeat *do* *not* GC this".
>
>The only way I can think of is with a macro __export similar to __init
>which puts exported symbols in a separate elf section. (So much for
>locality.) Then the linker script uses KEEP() on that section.

That is equivalent to "include every piece of code that uses
EXPORT_SYMBOL". In that case, you may as well forget about .a files
and go back to individual .o files. The point of .a files is to only
link code into the kernel if it is really needed. Most of the time it
works but one case is not covered at the moment - when the only
reference to some builtin code is from a module.

Ideally we need a mechanism to detect when at least one compiled module
has a reference to a kernel builtin then make sure that the builtin is
linked into [b]zImage. Unfortunately the only automatic way I can see
to do this will require that all modules are built before zImage. And
worse, rebuilding any module will require that zImage be relinked and
reinstalled if the module changes its references. Take the complexity
of "make dep" plus the checks for changes to compiler flags and square
it - no thanks.

A manual alternative is define a macro to force a symbol to be linked
into the kernel. Then any builtin code that "knows" it is used by a
module will declare at least one symbol to be __force_link(). This
works, see the patch below against 2.3.31.

This option is a manual process, each builtin source that does
EXPORT_SYMBOL also has to decide if any of the exported symbols are
actually used. This is a little messy, it was one of the things that
.a files were meant to remove. But if only a few files have this
problem then this patch lets us keep .a files, assuming we still want
them.

Index: 31.4/include/linux/init.h
--- 31.4/include/linux/init.h Sun, 07 Nov 1999 17:24:01 +1100 keith (linux-2.3/D/b/31_init.h 1.4 644)
+++ 31.4(w)/include/linux/init.h Sat, 11 Dec 1999 19:59:59 +1100 keith (linux-2.3/D/b/31_init.h 1.4 644)
@@ -82,6 +82,13 @@
#define module_init(x) __initcall(x);
#define module_exit(x) /* nothing */

+/* Force an object to be linked into the kernel, even if it is not referenced. */
+
+#define __force_link(x) \
+ static int \
+ __attribute__ ((__section__ (".force_link"), unused)) \
+ __force_link_##x = 0
+
#else

#define __init
Index: 31.4/Makefile
--- 31.4/Makefile Thu, 09 Dec 1999 15:51:29 +1100 keith (linux-2.3/M/b/40_Makefile 1.7.1.19.1.5 644)
+++ 31.4(w)/Makefile Sat, 11 Dec 1999 21:54:54 +1100 keith (linux-2.3/M/b/40_Makefile 1.7.1.19.1.5 644)
@@ -242,8 +242,15 @@
boot: vmlinux
@$(MAKE) -C arch/$(ARCH)/boot

+#
+# Scan archives, find any symbols marked "__force_link_", generate linker
+# options to include the corresponding symbol. <kaos@ocs.com.au>
+#
vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
+ $(shell nm -A $(filter %.a, $(FILESYSTEMS) $(NETWORKS) $(DRIVERS)) | \
+ grep __force_link_ | \
+ sed -e "s/^.*__force_link_/-u /") \
--start-group \
$(CORE_FILES) \
$(FILESYSTEMS) \
Index: 31.4/arch/sh/vmlinux.lds.S
--- 31.4/arch/sh/vmlinux.lds.S Sat, 23 Oct 1999 15:35:04 +1000 keith (linux-2.3/b/c/24_vmlinux.ld 1.3 644)
+++ 31.4(w)/arch/sh/vmlinux.lds.S Sat, 11 Dec 1999 20:19:10 +1100 keith (linux-2.3/b/c/24_vmlinux.ld 1.3 644)
@@ -62,6 +62,8 @@
. = ALIGN(4096);
___init_end = .;

+ /DISCARD/ : { *(.force_link) }
+
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }

Index: 31.4/arch/m68k/vmlinux-sun3.lds
--- 31.4/arch/m68k/vmlinux-sun3.lds Tue, 05 Oct 1999 14:20:01 +1000 keith (linux-2.3/f/c/21_vmlinux-su 1.1 644)
+++ 31.4(w)/arch/m68k/vmlinux-sun3.lds Sat, 11 Dec 1999 22:03:55 +1100 keith (linux-2.3/f/c/21_vmlinux-su 1.1 644)
@@ -14,6 +14,7 @@
*(.gnu.warning)
} = 0x4e75
.kstrtab : { *(.kstrtab) }
+ /DISCARD/ : { *(.force_link) } /* No storage needed for __force_link() */


_etext = .; /* End of text section */
Index: 31.4/arch/i386/vmlinux.lds
--- 31.4/arch/i386/vmlinux.lds Sat, 23 Oct 1999 15:35:04 +1000 keith (linux-2.3/j/c/26_vmlinux.ld 1.1 644)
+++ 31.4(w)/arch/i386/vmlinux.lds Sat, 11 Dec 1999 22:03:37 +1100 keith (linux-2.3/j/c/26_vmlinux.ld 1.1 644)
@@ -16,6 +16,7 @@
.text.lock : { *(.text.lock) } /* out-of-line lock text */
.rodata : { *(.rodata) }
.kstrtab : { *(.kstrtab) }
+ /DISCARD/ : { *(.force_link) } /* No storage needed for __force_link() */

. = ALIGN(16); /* Exception table */
__start___ex_table = .;
@@ -51,7 +52,6 @@
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
-
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }

Index: 31.4/arch/sparc64/vmlinux.lds
--- 31.4/arch/sparc64/vmlinux.lds Tue, 10 Aug 1999 19:51:45 +1000 keith (linux-2.3/j/35_vmlinux.ld 1.2 644)
+++ 31.4(w)/arch/sparc64/vmlinux.lds Sat, 11 Dec 1999 22:03:47 +1100 keith (linux-2.3/j/35_vmlinux.ld 1.2 644)
@@ -35,6 +35,7 @@
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
__kstrtab : { *(.kstrtab) }
+ /DISCARD/ : { *(.force_link) } /* No storage needed for __force_link() */
. = ALIGN(8192);
__init_begin = .;
.text.init : { *(.text.init) }
Index: 31.4/arch/m68k/vmlinux.lds
--- 31.4/arch/m68k/vmlinux.lds Tue, 05 Oct 1999 14:20:01 +1000 keith (linux-2.3/k/30_vmlinux.ld 1.3 644)
+++ 31.4(w)/arch/m68k/vmlinux.lds Sat, 11 Dec 1999 22:03:51 +1100 keith (linux-2.3/k/30_vmlinux.ld 1.3 644)
@@ -14,6 +14,7 @@
} = 0x4e75
.rodata : { *(.rodata) }
.kstrtab : { *(.kstrtab) }
+ /DISCARD/ : { *(.force_link) } /* No storage needed for __force_link() */

. = ALIGN(16); /* Exception table */
__start___ex_table = .;
Index: 31.4/arch/alpha/vmlinux.lds
--- 31.4/arch/alpha/vmlinux.lds Sat, 04 Sep 1999 13:10:55 +1000 keith (linux-2.3/w/26_vmlinux.ld 1.3 644)
+++ 31.4(w)/arch/alpha/vmlinux.lds Sat, 11 Dec 1999 22:05:01 +1100 keith (linux-2.3/w/26_vmlinux.ld 1.3 644)
@@ -20,6 +20,7 @@
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
.kstrtab : { *(.kstrtab) }
+ /DISCARD/ : { *(.force_link) } /* No storage needed for __force_link() */

/* Startup code */
. = ALIGN(8192);

With the above patch, forcing any object to be linked into the kernel
even when there are no references to it is a one line change to each
problem object.

Index: 31.4/drivers/video/fbcmap.c
--- 31.4/drivers/video/fbcmap.c Thu, 03 Jun 1999 11:07:51 +1000 keith (linux-2.3/C/31_fbcmap.c 1.2 644)
+++ 31.4(w)/drivers/video/fbcmap.c Sat, 11 Dec 1999 22:01:02 +1100 keith (linux-2.3/C/31_fbcmap.c 1.2 644)
@@ -307,3 +307,4 @@
EXPORT_SYMBOL(fb_set_cmap);
EXPORT_SYMBOL(fb_default_cmap);
EXPORT_SYMBOL(fb_invert_cmaps);
+__force_link(fb_invert_cmaps); /* Must link this object into the kernel */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/