|
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.
|