This is the mail archive of the
mailing list for the binutils project.
RFC: binutils PATCH: Set e_type to ET_EXEC for -pie -Ttext-segment=
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: LKML <linux-kernel at vger dot kernel dot org>, Binutils <binutils at sourceware dot org>
- Date: Mon, 9 Dec 2013 19:10:23 -0800
- Subject: RFC: binutils PATCH: Set e_type to ET_EXEC for -pie -Ttext-segment=
- Authentication-results: sourceware.org; auth=none
My original post was rejected by LKML. Resend.
On Mon, Dec 9, 2013 at 4:41 PM, H.J. Lu <email@example.com> wrote:
> On Mon, Dec 9, 2013 at 4:37 PM, H. Peter Anvin <firstname.lastname@example.org> wrote:
>> On 12/09/2013 03:53 PM, H.J. Lu wrote:
>>>>> x86-64 small model is limited to 4GB in size. You can't build
>>>>> a dynamic executable in small model larger than 4GB.
>>>>> There are medium and large models. But they are slower than
>>>>> small models as well as small models in PIE. Also there are
>>>>> no glibc run-times for medium and large models.
>>>> Compiling for the small PIC model shouldn't automatically mean
>>>> generating a PIE (ET_DYN) executable, though (and if those are
>>>> inherently linked, that is a fundamental bug IMNSHO.)
>>> PIE uses PIC. But GCC has -fPIE and -fPIC. They aren't
>>> the same. You build PIE with
>>> 1. Compile with -fPIE.
>>> 2. Link with -pie.
>> I'm talking about the memory model ("small PIC model"). I don't see why
>> it should be encapsulated in a PIE (ET_DYN) container if the user
>> doesn't want it to be relocatable.
> I see. Maybe linker can set ET_EXEC if vaddr is non-zero.
Linker sets e_type in ELF header to ET_DYN for -pie -Ttext-segment=0xXXX.
When I added -Ttext-segment=0xXXX, one goal was to load
small model executable above 4GB on Linux/x86-64, which
was done with -pie -Ttext-segment=0xXXX. But -pie sets
e_type in ELF header to ET_DYN and kernel may ignore
p_vaddr in ELF header to load ET_DYN binary at a random
address. This patch changes ld to set e_type in ELF header
to ET_EXEC if the first PT_LOAD segment has non-zero
p_vaddr. If this is unacceptable as generic ELF change,
I can make it specific to x86.
diff --git a/bfd/elf.c b/bfd/elf.c
index 8df38ee..5862460 100644
@@ -5152,6 +5152,27 @@ assign_file_positions_except_relocs (bfd *abfd,
+ if (link_info != NULL
+ && link_info->executable
+ && link_info->shared)
+ Elf_Internal_Phdr *segment;
+ unsigned int i;
+ unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
+ bfd_vma p_vaddr = 0;
+ for (i = 0, segment = elf_tdata (abfd)->phdr;
+ i < num_segments;
+ i++, segment++)
+ if (segment->p_type == PT_LOAD)
+ p_vaddr = segment->p_vaddr;
+ if (p_vaddr)
+ i_ehdrp->e_type = ET_EXEC;
/* Write out the program headers. */
alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0