OpenSolaris

Printable Version Enter a New Search
Bug ID 6736890
Synopsis PT_SUNWBSS should be disabled
State 10-Fix Delivered (Fix available in build)
Category:Subcategory compiler:linker
Keywords
Responsible Engineer Ali Bahrami
Reported Against
Duplicate Of
Introduced In solaris_7
Commit to Fix snv_104
Fixed In snv_104
Release Fixed solaris_nevada(snv_104)
Related Bugs 6773695 , 5064121
Submit Date 13-August-2008
Last Update Date 4-December-2008
Description
ELF defines SHT_SUNW_MOVE sections.  These sections allow large data buffers to
be expressed as NOBITS sections that can be initialized at runtime with small
numbers of data items.  The concept stemmed from a desire to provide for Fortran
common blocks, which can often be larges blocks of zero's with a small number of
no-zero items.  These blocks are traditionally defined as .data items, which
means they can take up substantial disc space.

The SHT_SUNW_MOVE implementation is described in the Linker and Libraries Guide:

  http://docs.sun.com/app/docs/doc/819-0690/6n33n7fci?l=en&a=view&q=SHT_SUNW_MOVE

The use of these sections isn't limited to Fortran, in fact our SPARC compilers
use Move sections to express large (mostly zero) data arrays (our Intel compilers
don't seem to use Move sections at all):

 % cat main1.c
 #include <stdio.h>

 int             move_1[0x1000] = { 0, 0x11, 0x12 };
 static int      move_2[0x1000] = { 0x21, 0, 0x22 };

 int main()
 {
        (void) printf("move_1[0] = 0x%x 0x%x\n", &move_1[0], move_1[0]);
        (void) printf("move_1[1] = 0x%x 0x%x\n", &move_1[1], move_1[1]);
        (void) printf("move_1[2] = 0x%x 0x%x\n", &move_1[2], move_1[2]);
        (void) printf("move_1[3] = 0x%x 0x%x\n", &move_1[3], move_1[3]);
        (void) printf("\n");
        (void) printf("move_2[0] = 0x%x 0x%x\n", &move_2[0], move_2[0]);
        (void) printf("move_2[1] = 0x%x 0x%x\n", &move_2[1], move_2[1]);
        (void) printf("move_2[2] = 0x%x 0x%x\n", &move_2[2], move_2[2]);
        (void) printf("move_2[3] = 0x%x 0x%x\n", &move_2[3], move_2[3]);

	return (0);
 }
 % cc -V -o main1 main1.c 
 cc: Sun C 5.8 Patch 121015-04 2007/01/10
 
 % elfdump -m main1

 Move Section:  .SUNW_move
    symndx offset   size repeat stride   value               with respect to
       [1]  16384      4      1      1 0x000000000000000021  .bss (section)
       [1]  16392      4      1      1 0x000000000000000022  .bss (section)
      [11]      4      4      1      1 0x000000000000000011  move_1
      [11]      8      4      1      1 0x000000000000000012  move_1
 % ./main1
 move_1[0] = 0x212a0 0x0
 move_1[1] = 0x212a4 0x11
 move_1[2] = 0x212a8 0x12
 move_1[3] = 0x212ac 0x0

 move_2[0] = 0x252a0 0x21
 move_2[1] = 0x252a4 0x0
 move_2[2] = 0x252a8 0x22
 move_2[3] = 0x252ac 0x0

The original design for SHT_SUNW_MOVE assumed that symbols that were to have data
moved to them would either be defined as .bss (local) or COMMON (global), as is the
standard for "tentative" symbols.  However, as can be seen from the above example,
and has been confirmed by the Fortran folks, the compiler implementations only emits
.bss symbols for Move information.

ld(1) has a implementation detail that would place any COMMON Move symbols into their
own PT_SUNWBSS segment.  This has little documentation other than a table entry within
the Linker and Libraries Guide.  The idea was that if multiple shared objects defined
the same PT_SUNWBSS segment, then only the first loaded shared object would have to
instantiate this segment.  All other segments would effectively be interposed upon.

However, ld.so.1 was never implemented to trigger off of this design.  Any
PT_SUNWBSS segments are treated as PT_LOAD segments.  And, given the compilers don't
create COMMON Move symbols, the only way we've ever generated a PT_SUNWBSS segment
is to essentially elfedit() it into existence.

But, let's revisit the PT_SUNWBSS idea, as there seem to be some "limitations":

 i.	You can't defer providing a PT_SUNWBSS segment.  An object that defines a
	PT_SUNWBSS segment must make a reservation for the address space when the
	object is loaded.  Trying to claim the address space later (when a relocation
	indicates you need the Move data) is too late, as the space may have been
	used for another mapping.

 ii.	Although a reservation must be made, the writing of the Move data could be
	deferred.  However, the PT_SUNWBSS segment should really reside on a page
	boundary to provide any potential savings.  Todays implementation simply
	butts the PT_SUNWBSS segment up against the last PT_LOAD segment.

 iii.	And can we assume that every shared object that defines Move data, defines
	the same Move data, so that one complete PT_SUNWBSS segment can interpose on
	all others?

Given that we don't create PT_SUNWBSS segments yet, and that they have limited use,
I propose that we remove their creation from ld(1).  This will simplify the ld(1)
implementation, and those responsible for mapping objects.   We should:


 i.	Leave the PT_SUNWBSS definition in our headers, but comment the definition
	as unused.  With this definition we might as well leave diagnostics tools like
	elfdump/elfedit/libconv with the ability to display the header.

 ii.	Remove the PT_SUNWBSS creation from ld(1), and the PT_SUNWBSS evaluation from
	ld.so.1(1) and mmapobj(2).

 iii.	Remove the PT_SUNWBSS table entries from the Linker and Libraries Guide.

 iv.	ld(1) should probably continue to process a COMMON Move symbol, but simply
	direct this symbol to a .bss section.

 vi.	ld.so.1 could be smarter, and rather than executing Move sections could defer
	this processing until a relocation is bound to the move data.  Thus, any .bss
	areas would not be written to until needed.  However, the complexity of this
	implementation might outweigh the benefits.  This should be a low priority.
Work Around
N/A
Comments
N/A