> Date: Tue, 18 Aug 2015 19:29:58 +0000
> From: Miod Vallat <[email protected]>
>
> 2. I believe that some light smarts could be added to bfd to make .ctors
> and .dtors read-only when linking a true static binary, which would
> alleviate crt0 (.got being already RO in that case). So I will come
> with a binutils diff shortly, so that you will be able to put your
> crt0 diff in.
Doesn't look like .got is already RO in that case. But we can make it
so. Diff below forces .got, .ctors and .dtors to be read0only if we
have not .dynamic section, i.e. for truly static executables. This
makes the segment that contains those sections read-only for
executables built with -static -nopie:
$ gcc -static -nopie -o hello hello.c
$ readelf -a hello.o
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000100000 0x0000000000100000
0x0000000000016b74 0x0000000000016b74 R E 100000
LOAD 0x0000000000016b80 0x0000000000216b80 0x0000000000216b80
0x00000000000017cc 0x00000000000017cc R 100000
LOAD 0x0000000000018350 0x0000000000318350 0x0000000000318350
0x0000000000000590 0x0000000000000590 RW 100000
LOAD 0x00000000000188e0 0x00000000004188e0 0x00000000004188e0
0x00000000000006d8 0x00000000000006d8 R 100000
LOAD 0x0000000000018fb8 0x0000000000718fb8 0x0000000000718fb8
0x0000000000001088 0x000000000000c150 RW 100000
NOTE 0x0000000000000238 0x0000000000100238 0x0000000000100238
0x0000000000000018 0x0000000000000018 R 4
OPENBSD_RANDOM 0x0000000000018350 0x0000000000318350 0x0000000000318350
0x0000000000000008 0x0000000000000008 RW 8
Section to Segment mapping:
Segment Sections...
00 .note.openbsd.ident .init .text .fini
01 .rodata .eh_frame
02 .openbsd.randomdata .jcr .data.rel.ro
03 .got .ctors .dtors
04 .data .bss
05 .note.openbsd.ident
06 .openbsd.randomdata
All other types retain a writable segment, that is made read-only by
either ld.so or rcrt0.o.
Tested on macppc and sparc64.
ok?
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/ld/emultempl/elf32.em,v
retrieving revision 1.3
diff -u -p -r1.3 elf32.em
--- ld/emultempl/elf32.em 4 Jul 2011 23:58:26 -0000 1.3
+++ ld/emultempl/elf32.em 21 Aug 2015 11:20:44 -0000
@@ -1109,6 +1109,22 @@ EOF
if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
cat >>e${EMULATION_NAME}.c <<EOF
+static void
+gld${EMULATION_NAME}_force_readonly(lang_input_statement_type *s)
+{
+ asection *sec;
+
+ if (s->the_bfd == NULL)
+ return;
+
+ sec = bfd_get_section_by_name (s->the_bfd, ".ctors");
+ if (sec)
+ sec->flags |= SEC_READONLY;
+ sec = bfd_get_section_by_name (s->the_bfd, ".dtors");
+ if (sec)
+ sec->flags |= SEC_READONLY;
+}
+
/* This is called after all the input files have been opened. */
static void
@@ -1119,6 +1135,27 @@ gld${EMULATION_NAME}_after_open (void)
/* We only need to worry about this when doing a final link. */
if (link_info.relocatable || !link_info.executable)
return;
+
+ /* If we don't have a .dynamic section, we have no relocations, and
+ we can make .got, .ctors and .dtors read-only. This will make
+ the segment containing those sections to be read-only in static
+ executables. */
+ if (link_info.hash->type == bfd_link_elf_hash_table
+ && !elf_hash_table (&link_info)->dynamic_sections_created)
+ {
+ bfd *dynobj = elf_hash_table (&link_info)->dynobj;
+
+ if (dynobj != NULL)
+ {
+ asection *sec;
+
+ sec = bfd_get_section_by_name (dynobj, ".got");
+ if (sec)
+ sec->flags |= SEC_READONLY;
+ }
+
+ lang_for_each_input_file (gld${EMULATION_NAME}_force_readonly);
+ }
/* Get the list of files which appear in DT_NEEDED entries in
dynamic objects included in the link (often there will be none).