blob: 14f877ad863f00eac8d5274f36a5bbd38336ec89 [file] [log] [blame]
/* Script for ld --shared: link shared library */
OUTPUT_FORMAT("elf32-nacl", "elf32-nacl",
"elf32-nacl")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32");
SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
PHDRS
{
seg_code PT_LOAD FLAGS(5) ; /* read + execute */
seg_rodata PT_LOAD FLAGS(4) ; /* read */
seg_rwdata PT_LOAD FLAGS(6) ; /* read + write */
seg_dynamic PT_DYNAMIC FLAGS(6) ;
seg_stack PT_GNU_STACK FLAGS(6) ;
seg_tls PT_TLS FLAGS(4) ;
seg_note PT_NOTE FLAGS(4) ;
}
SECTIONS
{
. = SEGMENT_START("text", 0);
_begin = .;
/* The ALIGN(32) instructions below are workarounds.
TODO(mseaborn): Get the object files to include the correct
alignments and padding themselves.
See http://code.google.com/p/nativeclient/issues/detail?id=499. */
.init : SUBALIGN(32)
{
KEEP (*(.init))
. = ALIGN(32); /* ensure nop padding */
} :seg_code =0x90909090
.plt : { *(.plt) }
.text : SUBALIGN(32)
{
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
/* Putting .fini here makes the align pad correctly when .fini is empty.
Listing the __libc* sections is also necessary to make padding work. */
KEEP (*(.fini))
*(__libc_freeres_fn)
*(__libc_thread_freeres_fn)
. = ALIGN(CONSTANT (MAXPAGESIZE)); /* ensures NOP fill */
} =0x90909090
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
. = ALIGN(SEGMENT_START("text", 0) + 0x10000000, CONSTANT (MAXPAGESIZE));
.note.gnu.build-id :
{
PROVIDE_HIDDEN (__note_gnu_build_id_start = .);
*(.note.gnu.build-id)
PROVIDE_HIDDEN (__note_gnu_build_id_end = .);
} :seg_rodata :seg_note
/* :seg_rodata is on .dummy rather than on .hash to avoid breaking the linker
script munging that glibc's Makerules does using sed. */
.dummy : {} :seg_rodata
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
.rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Executables loaded by sel_ldr are not required to have seg_rwdata aligned
to page boundary. So we can omit alignment here both for ld.so and normal
libraries. */
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } :seg_rwdata
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :seg_rwdata :seg_tls
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
. = 0x10030000; .nacl_irt_syscall_ptr : { KEEP(*(.nacl_irt_syscall_ptr)) }
. = 0x10030004; .preinit_array :
{
KEEP (*(.preinit_array))
} :seg_rwdata
.init_array :
{
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
}
.fini_array :
{
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) } :seg_dynamic :seg_rwdata
.got : { *(.got) } :seg_rwdata
/* This command ensures that the first 3 entries of .got.plt are separated
by page boundary from the rest of .got.plt and marks the end of RELRO
segment. This segment is part of read-write segment that is made read-only
after loading the library. The first 3 entries of .got.plt are special.
They are filled by the linker and are not changed after loading. The rest
of .got.plt is filled lazily and so must stay writable. That's why
the first 3 .got.plt entries mark the end of RELRO segment. */
. = DATA_SEGMENT_RELRO_END (12, .);
.got.plt : { *(.got.plt) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
KEEP (*(.gnu.linkonce.d.*personality*))
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
/* We place the BSS in a separate segment as a workaround for the
behaviour of NaCl's mmap() on the last page in a file. When using
copy-on-write MAP_PRIVATE, we cannot necessarily write beyond the
file's extent within the 64k page.
See http://code.google.com/p/nativeclient/issues/detail?id=824.
TODO(mseaborn): A better fix would be to change the dynamic linker
to copy the last page. This would save a page of memory because
the BSS could share a page with the data segment. But for now, it
is simpler to change the linker script. */
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .); . = DATA_SEGMENT_END(.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }
/DISCARD/ : { *(.note.ABI-tag) }
}