[PATCH] Discardable strings for init and exit sections

From: Maciej W. Rozycki
Date: Fri Oct 12 2007 - 12:50:34 EST


We currently have infrastructure for discardable text and data, but no
such thing for strings. This is especially notable for inline strings
such as ones used by printk() which are left behind resident in the memory
throughout the life of the system even though code referring to them has
been removed.

Following a short discussion at the linux-mips list, here is a proposed
implementation for discardable strings. It adds __initstr and __exitstr
plus most of the usual variations, but most importantly it adds wrapper
macros that may be used for inline strings that make them be put in
separate sections which may then be discarded, while still preserving the
usual merging property of sections containing strings. The macros are
called _i() and _e(), with the other alternatives adding at most two
letters each. This has been inspired by how the GNU gettext handles
localised strings in a way that does not add too much clutter and the
result is still reasonably well readable. Some use examples have been
included in <linux/init.h>.

There is one pitfall here -- GCC does not let one specify section flags
explicitly and provides its own set based on the type of the variable
instead. The guess, which is "aw", is not what we want here, so I had to
circumvent it somehow. The solution is to provide the flags and the
further necessary parameters as a part of the section "name" and then emit
a newline and an assembly comment character so that what GCC produces for
section flags is ignored. A newline is required for a reasonable
implementation, because only the line comment character is almost
universal across targets supported by binutils (except from a couple of
obscure platforms we do not aim to support), while the trailing comment
character varies wildly and may not even be available at all (cf.
blackfin). This is what this strange __strflags macro is for.

Of course for this to work all the linker scripts have to be updated
accordingly.

Signed-off-by: Maciej W. Rozycki <macro@xxxxxxxxxxxxxx>
---
I did some proof-of-concept testing only of this change as for it to be
of use, strings have to be annotated appropriately. I do not expect it to
happen soon or automatically, but I rely on people for whom the size
matters to make the necessary adjustments.

For testing I made the obvious choice ;-) of drivers/net/defxx.c; for
which I have a patch that I will send separately. The driver is nice
enough to have a duplicate string that can be used to verify that merging
still works and then the results of the discarding can be examined through
/proc/kcore. I have built the changes for MIPS, albeit with a slightly
older kernel as the current version does not build for my configuration of
interest, and successfully verified at the run time.

Architecture maintainers, I have made a reasonable attempt to get the
linker script changes right, but for a few of the more complicated setups
I may have not done everything necessary or I may have misplaced the
sections in the output even. Please let me know of any adjustments
necessary.

Comments are welcome, whether positive or negative, but I do hope overall
the feature is reasonable enough to be accepted. This patch applies to
the current Linus tree.

Maciej

patch-2.6.23-20071012-inexitstr-5
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/alpha/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/alpha/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/alpha/kernel/vmlinux.lds.S 2007-09-04 04:55:16.000000000 +0000
+++ linux-2.6.23-20071012/arch/alpha/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -42,6 +42,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }

. = ALIGN(16);
@@ -107,7 +108,7 @@ SECTIONS
_end = .;

/* Sections to be discarded */
- /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) }
+ /DISCARD/ : { *(.exit.text) *(.exit.str1) *(.exit.data) *(.exitcall.exit) }

.mdebug 0 : { *(.mdebug) }
.note 0 : { *(.note) }
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/arm/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/arm/kernel/vmlinux.lds.S 2007-09-04 04:55:16.000000000 +0000
+++ linux-2.6.23-20071012/arch/arm/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -41,6 +41,7 @@ SECTIONS
__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;
+ *(.init.str1)
. = ALIGN(16);
__setup_start = .;
*(.init.setup)
@@ -78,6 +79,7 @@ SECTIONS

/DISCARD/ : { /* Exit code and data */
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
#ifndef CONFIG_MMU
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/blackfin/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/blackfin/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/blackfin/kernel/vmlinux.lds.S 2007-10-12 02:56:53.000000000 +0000
+++ linux-2.6.23-20071012/arch/blackfin/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -94,6 +94,10 @@ SECTIONS
*(.init.text)
__einittext = .;
}
+ .init.str1 :
+ {
+ *(.init.str1)
+ }
.init.data :
{
. = ALIGN(16);
@@ -194,6 +198,7 @@ SECTIONS
/DISCARD/ :
{
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/frv/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/frv/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/frv/kernel/vmlinux.lds.S 2007-09-04 04:55:18.000000000 +0000
+++ linux-2.6.23-20071012/arch/frv/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -35,6 +35,7 @@ SECTIONS
#endif
}
_einittext = .;
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }

. = ALIGN(8);
@@ -124,6 +125,7 @@ SECTIONS
__trap_fixup_tables = .;
*(.trap.fixup.user .trap.fixup.kernel)

+ *(.exit.str1)
}

. = ALIGN(8); /* Exception table */
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/h8300/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/h8300/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/h8300/kernel/vmlinux.lds.S 2007-07-10 04:55:29.000000000 +0000
+++ linux-2.6.23-20071012/arch/h8300/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -112,6 +112,7 @@ SECTIONS
__sinittext = .;
*(.init.text)
__einittext = .;
+ *(.init.str1)
*(.init.data)
. = ALIGN(0x4) ;
___setup_start = .;
@@ -125,6 +126,7 @@ SECTIONS
*(.con_initcall.init)
___con_initcall_end = .;
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
#if defined(CONFIG_BLK_DEV_INITRD)
. = ALIGN(4);
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/ia64/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/ia64/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/ia64/kernel/vmlinux.lds.S 2007-09-04 04:55:19.000000000 +0000
+++ linux-2.6.23-20071012/arch/ia64/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -28,6 +28,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
*(.IA_64.unwind.exit.text)
@@ -123,6 +124,9 @@ SECTIONS
_einittext = .;
}

+ .exit.str1 : AT(ADDR(.init.str1) - LOAD_OFFSET)
+ { *(.exit.str1) }
+
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET)
{ *(.init.data) }

diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/m32r/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/m32r/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/m32r/kernel/vmlinux.lds.S 2007-09-04 04:55:19.000000000 +0000
+++ linux-2.6.23-20071012/arch/m32r/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -79,6 +79,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
@@ -101,6 +102,7 @@ SECTIONS
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : { *(.exit.text) }
+ .exit.str1 : { *(.exit.str1) }
.exit.data : { *(.exit.data) }

#ifdef CONFIG_BLK_DEV_INITRD
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/m68k/kernel/vmlinux-std.lds linux-2.6.23-20071012/arch/m68k/kernel/vmlinux-std.lds
--- linux-2.6.23-20071012.macro/arch/m68k/kernel/vmlinux-std.lds 2007-09-04 04:55:19.000000000 +0000
+++ linux-2.6.23-20071012/arch/m68k/kernel/vmlinux-std.lds 2007-10-12 13:53:22.000000000 +0000
@@ -48,6 +48,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
@@ -83,6 +84,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/m68k/kernel/vmlinux-sun3.lds linux-2.6.23-20071012/arch/m68k/kernel/vmlinux-sun3.lds
--- linux-2.6.23-20071012.macro/arch/m68k/kernel/vmlinux-sun3.lds 2007-09-04 04:55:19.000000000 +0000
+++ linux-2.6.23-20071012/arch/m68k/kernel/vmlinux-sun3.lds 2007-10-12 13:53:22.000000000 +0000
@@ -41,6 +41,7 @@ __init_begin = .;
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
@@ -78,6 +79,7 @@ __init_begin = .;
/* Sections to be discarded */
/DISCARD/ : {
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/m68knommu/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/m68knommu/kernel/vmlinux.lds.S 2007-07-10 04:55:30.000000000 +0000
+++ linux-2.6.23-20071012/arch/m68knommu/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -145,6 +145,7 @@ SECTIONS {
_sinittext = .;
*(.init.text)
_einittext = .;
+ *(.init.str1)
*(.init.data)
. = ALIGN(16);
__setup_start = .;
@@ -171,6 +172,7 @@ SECTIONS {

/DISCARD/ : {
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/mips/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/mips/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/mips/kernel/vmlinux.lds.S 2007-10-11 04:56:52.000000000 +0000
+++ linux-2.6.23-20071012/arch/mips/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -107,6 +107,9 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : {
+ *(.init.str1)
+ }
.init.data : {
*(.init.data)
}
@@ -136,6 +139,9 @@ SECTIONS
.exit.text : {
*(.exit.text)
}
+ .exit.str1 : {
+ *(.exit.str1)
+ }
.exit.data : {
*(.exit.data)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/parisc/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/parisc/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/parisc/kernel/vmlinux.lds.S 2007-09-04 04:55:20.000000000 +0000
+++ linux-2.6.23-20071012/arch/parisc/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -150,6 +150,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
@@ -176,6 +177,7 @@ SECTIONS
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : { *(.exit.text) }
+ .exit.str1 : { *(.exit.str1) }
.exit.data : { *(.exit.data) }
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(ASM_PAGE_SIZE);
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/powerpc/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/powerpc/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/powerpc/kernel/vmlinux.lds.S 2007-09-04 04:55:20.000000000 +0000
+++ linux-2.6.23-20071012/arch/powerpc/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -23,6 +23,7 @@ SECTIONS
/* Sections to be discarded. */
/DISCARD/ : {
*(.exitcall.exit)
+ *(.exit.str1)
*(.exit.data)
}

@@ -84,6 +85,8 @@ SECTIONS
*/
.exit.text : { *(.exit.text) }

+ .init.str1 : { *(.init.str1) }
+
.init.data : {
*(.init.data);
__vtop_table_begin = .;
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/ppc/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/ppc/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/ppc/kernel/vmlinux.lds.S 2007-09-04 04:55:26.000000000 +0000
+++ linux-2.6.23-20071012/arch/ppc/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -101,6 +101,7 @@ SECTIONS
/* .exit.text is discarded at runtime, not link time,
to deal with references from __bug_table */
.exit.text : { *(.exit.text) }
+ .init.str1 : { *(.init.str1) }
.init.data : {
*(.init.data);
__vtop_table_begin = .;
@@ -162,6 +163,7 @@ SECTIONS
/* Sections to be discarded. */
/DISCARD/ : {
*(.exitcall.exit)
+ *(.exit.str1)
*(.exit.data)
}
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/s390/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/s390/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/s390/kernel/vmlinux.lds.S 2007-09-04 04:55:27.000000000 +0000
+++ linux-2.6.23-20071012/arch/s390/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -87,6 +87,7 @@ SECTIONS
* to deal with references from __bug_table
*/
.exit.text : { *(.exit.text) }
+ .init.str1 : { *(.init.str1) }

.init.data : { *(.init.data) }
. = ALIGN(256);
@@ -124,7 +125,7 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.data) *(.exitcall.exit)
+ *(.exit.str1) *(.exit.data) *(.exitcall.exit)
}

/* Stabs debugging sections. */
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/sh/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/sh/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/sh/kernel/vmlinux.lds.S 2007-09-04 04:55:28.000000000 +0000
+++ linux-2.6.23-20071012/arch/sh/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -74,6 +74,7 @@ SECTIONS
_sinittext = .;
.init.text : { *(.init.text) }
_einittext = .;
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/sh64/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/sh64/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/sh64/kernel/vmlinux.lds.S 2007-09-04 04:55:29.000000000 +0000
+++ linux-2.6.23-20071012/arch/sh64/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -105,6 +105,7 @@ SECTIONS
_sinittext = .;
.init.text : C_PHYS(.init.text) { *(.init.text) }
_einittext = .;
+ .init.str1 : C_PHYS(.init.str1) { *(.init.str1) }
.init.data : C_PHYS(.init.data) { *(.init.data) }
. = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */
__setup_start = .;
@@ -141,6 +142,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
*(.exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/sparc/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/sparc/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/sparc/kernel/vmlinux.lds.S 2007-09-04 04:55:29.000000000 +0000
+++ linux-2.6.23-20071012/arch/sparc/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -45,6 +45,7 @@ SECTIONS
}
_einittext = .;
__init_text_end = .;
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
@@ -83,7 +84,7 @@ SECTIONS
}
_end = . ;
PROVIDE (end = .);
- /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) }
+ /DISCARD/ : { *(.exit.text) *(.exit.str1) *(.exit.data) *(.exitcall.exit) }

STABS_DEBUG

diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/sparc64/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/sparc64/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/sparc64/kernel/vmlinux.lds.S 2007-09-04 04:55:30.000000000 +0000
+++ linux-2.6.23-20071012/arch/sparc64/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -54,6 +54,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
.init.data : { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
@@ -106,7 +107,7 @@ SECTIONS
}
_end = . ;
PROVIDE (end = .);
- /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) }
+ /DISCARD/ : { *(.exit.text) *(.exit.str1) *(.exit.data) *(.exitcall.exit) }

STABS_DEBUG

diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/um/kernel/dyn.lds.S linux-2.6.23-20071012/arch/um/kernel/dyn.lds.S
--- linux-2.6.23-20071012.macro/arch/um/kernel/dyn.lds.S 2007-09-04 04:55:30.000000000 +0000
+++ linux-2.6.23-20071012/arch/um/kernel/dyn.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -22,6 +22,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }

. = ALIGN(4096);

diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/um/kernel/uml.lds.S linux-2.6.23-20071012/arch/um/kernel/uml.lds.S
--- linux-2.6.23-20071012.macro/arch/um/kernel/uml.lds.S 2007-09-04 04:55:30.000000000 +0000
+++ linux-2.6.23-20071012/arch/um/kernel/uml.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -33,6 +33,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : { *(.init.str1) }
. = ALIGN(4096);

.text :
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/v850/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/v850/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/v850/kernel/vmlinux.lds.S 2007-07-10 04:55:50.000000000 +0000
+++ linux-2.6.23-20071012/arch/v850/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -99,6 +99,7 @@
*(.text.lock) \
*(.exitcall.exit) \
__real_etext = . ; /* There may be data after here. */ \
+ *(.exit.str1) \
RODATA_CONTENTS \
. = ALIGN (4) ; \
*(.call_table_data) \
@@ -159,6 +160,7 @@
__sinittext = .; \
*(.init.text) /* 2.5 convention */ \
__einittext = .; \
+ *(.init.str1) \
*(.init.data) \
*(.text.init) /* 2.4 convention */ \
*(.data.init) \
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.23-20071012/arch/x86/kernel/vmlinux_32.lds.S
--- linux-2.6.23-20071012.macro/arch/x86/kernel/vmlinux_32.lds.S 2007-10-12 02:56:54.000000000 +0000
+++ linux-2.6.23-20071012/arch/x86/kernel/vmlinux_32.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -134,6 +134,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : AT(ADDR(.init.str1) - LOAD_OFFSET) { *(.init.str1) }
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
. = ALIGN(16);
.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
@@ -170,6 +171,7 @@ SECTIONS
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
+ .exit.str1 : AT(ADDR(.exit.str1) - LOAD_OFFSET) { *(.exit.str1) }
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
#if defined(CONFIG_BLK_DEV_INITRD)
. = ALIGN(4096);
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.23-20071012/arch/x86/kernel/vmlinux_64.lds.S
--- linux-2.6.23-20071012.macro/arch/x86/kernel/vmlinux_64.lds.S 2007-10-12 02:56:54.000000000 +0000
+++ linux-2.6.23-20071012/arch/x86/kernel/vmlinux_64.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -158,6 +158,7 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ .init.str1 : AT(ADDR(.init.str1) - LOAD_OFFSET) { *(.init.str1) }
__initdata_begin = .;
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
__initdata_end = .;
@@ -188,6 +189,7 @@ SECTIONS
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
+ .exit.str1 : AT(ADDR(.exit.str1) - LOAD_OFFSET) { *(.exit.str1) }
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }

/* vdso blob that is mapped into user space */
diff -up --recursive --new-file linux-2.6.23-20071012.macro/arch/xtensa/kernel/vmlinux.lds.S linux-2.6.23-20071012/arch/xtensa/kernel/vmlinux.lds.S
--- linux-2.6.23-20071012.macro/arch/xtensa/kernel/vmlinux.lds.S 2007-09-04 04:55:30.000000000 +0000
+++ linux-2.6.23-20071012/arch/xtensa/kernel/vmlinux.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -140,6 +140,8 @@ SECTIONS
_einittext = .;
}

+ .init.str1 : { *(.init.str1) }
+
.init.data :
{
*(.init.data)
@@ -279,6 +281,7 @@ SECTIONS
/DISCARD/ :
{
*(.exit.literal .exit.text)
+ *(.exit.str1)
*(.exit.data)
*(.exitcall.exit)
}
diff -up --recursive --new-file linux-2.6.23-20071012.macro/include/asm-um/common.lds.S linux-2.6.23-20071012/include/asm-um/common.lds.S
--- linux-2.6.23-20071012.macro/include/asm-um/common.lds.S 2007-09-04 04:56:18.000000000 +0000
+++ linux-2.6.23-20071012/include/asm-um/common.lds.S 2007-10-12 13:53:22.000000000 +0000
@@ -98,6 +98,7 @@
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
.exit.text : { *(.exit.text) }
+ .exit.str1 : { *(.exit.str1) }
.exit.data : { *(.exit.data) }

.preinit_array : {
diff -up --recursive --new-file linux-2.6.23-20071012.macro/include/linux/init.h linux-2.6.23-20071012/include/linux/init.h
--- linux-2.6.23-20071012.macro/include/linux/init.h 2007-10-12 02:56:54.000000000 +0000
+++ linux-2.6.23-20071012/include/linux/init.h 2007-10-12 13:53:22.000000000 +0000
@@ -36,6 +36,20 @@
* section.
*
* Also note, that this data cannot be "const".
+ *
+ * For strings:
+ * Use __initstr, __exitstr like __initdata:
+ *
+ * static const char welcome[] __initstr = "Hello World!\n";
+ * static const char goodbye[] __exitstr = "Farewell then.\n";
+ *
+ * but also:
+ *
+ * pr_info(_i("%s: Thanks for selecting, will do my best\n"), dev->name);
+ * pr_info(_e("%s: Hope to be of use again soon\n"), dev->name);
+ *
+ * Note that strings have to be "const" and they are put in mergeable
+ * sections which means the linker will do nasty things to them. ;-)
*/

/* These are for everybody (although not all archs will actually
@@ -45,6 +59,24 @@
#define __exitdata __attribute__ ((__section__(".exit.data")))
#define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))

+#define __initstr __attribute__((__section__(".init.str1" __strflags)))
+#define __exitstr __attribute__((__section__(".exit.str1" __strflags)))
+
+#define _i(str) \
+({ \
+ static const char __istr[] __initstr = (str); \
+ __istr; \
+})
+#define _e(str) \
+({ \
+ static const char __estr[] __exitstr = (str); \
+ __istr; \
+})
+
+/* Internal implementation detail for the above; just disregard. ;-) */
+#define __strflags ",\"aMS\",@progbits,1\n" \
+ "# Useless section flags supplied by GCC follow: "
+
/* modpost check for section mismatches during the kernel build.
* A section mismatch happens when there are references from a
* code or data section to an init section (both code or data).
@@ -247,46 +279,74 @@ void __init parse_early_param(void);
#ifdef CONFIG_MODULES
#define __init_or_module
#define __initdata_or_module
+#define __initstr_or_module
+#define _iom(str) (str)
#else
#define __init_or_module __init
#define __initdata_or_module __initdata
+#define __initstr_or_module __initstr
+#define _iom(str) _i(str)
#endif /*CONFIG_MODULES*/

#ifdef CONFIG_HOTPLUG
#define __devinit
#define __devinitdata
+#define __devinitstr
+#define _di(str) (str)
#define __devexit
#define __devexitdata
+#define __devexitstr
+#define _de(str) (str)
#else
#define __devinit __init
#define __devinitdata __initdata
+#define __devinitstr __initstr
+#define _di(str) _i(str)
#define __devexit __exit
#define __devexitdata __exitdata
+#define __devexitstr __exitstr
+#define _de(str) _e(str)
#endif

#ifdef CONFIG_HOTPLUG_CPU
#define __cpuinit
#define __cpuinitdata
+#define __cpuinitstr
+#define _ci(str) (str)
#define __cpuexit
#define __cpuexitdata
+#define __cpuexitstr
+#define _ce(str) (str)
#else
#define __cpuinit __init
#define __cpuinitdata __initdata
+#define __cpuinitstr __initstr
+#define _ci(str) _i(str)
#define __cpuexit __exit
#define __cpuexitdata __exitdata
+#define __cpuexitstr __exitstr
+#define _ce(str) _e(str)
#endif

#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
|| defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
#define __meminit
#define __meminitdata
+#define __meminitstr
+#define _mi(str) (str)
#define __memexit
#define __memexitdata
+#define __memexitstr
+#define _me(str) (str)
#else
#define __meminit __init
#define __meminitdata __initdata
+#define __meminitstr __initstr
+#define _mi(str) _i(str)
#define __memexit __exit
#define __memexitdata __exitdata
+#define __memexitstr __exitstr
+#define _me(str) _e(str)
#endif

/* Functions marked as __devexit may be discarded at kernel link time, depending
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/