> Date: Tue, 18 Aug 2015 19:29:58 +0000 > From: Miod Vallat <m...@online.fr> > > 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).