[Bug ld/31795] New: ld.bfd makes elf type ET_EXEC for PIEs when load address non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 Bug ID: 31795 Summary: ld.bfd makes elf type ET_EXEC for PIEs when load address non-0 Product: binutils Version: 2.42 Status: UNCONFIRMED Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: mintsuki at protonmail dot com Target Milestone: --- When linking a static-pie kernel with ld.lld (from LLVM) or ld.gold, the output ELF file type is always ET_DYN (as I believe is correct), but, when linking using ld.bfd, the output ELF type is ET_DYN only if the load address of the PHDRs starts at 0, but gets set to ET_EXEC if the load address is a non-0 value. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 mintsuki changed: What|Removed |Added Summary|ld.bfd makes elf type |ld.bfd makes ELFs of type |ET_EXEC for PIEs when load |ET_EXEC for static PIEs |address non-0 |when load address is non-0 -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #2 from mintsuki --- (In reply to H.J. Lu from comment #1) > It is done to ensure that PIE is loaded at the specific address which may > be required for functional, performance or security purposes. This does not match what all the other major linkers do (LLD, gold). It also isn't properly documented anywhere that I could find. Additionally, why would someone generate a PIE just for it to be loaded *always* at the same specified address? What is the use case? >From what I know, if a PIE has a specific non-0 load address, it should be taken as a hint or preferred load address, but then the program loader should be able to apply any slide to it as it sees fit. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #3 from mintsuki --- Also, when generating a shared object with -shared, without -pie, having a non-0 base address does not affect the ELF file type, which is always ET_DYN. If what you just said is true, then why is this the behaviour here and not when making a static PIE? -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #6 from mintsuki --- (In reply to H.J. Lu from comment #4) > (In reply to mintsuki from comment #2) > > (In reply to H.J. Lu from comment #1) > > > It is done to ensure that PIE is loaded at the specific address which may > > > be required for functional, performance or security purposes. > > > > This does not match what all the other major linkers do (LLD, gold). It also > > isn't properly documented anywhere that I could find. Additionally, why > > would someone generate a PIE just for it to be loaded *always* at the same > > specified address? What is the use case? > > A program may work properly only when it is loaded above 4GB address. Yes, and I guess that could be explicitly specified as the functioning of a non-0 load address. But that doesn't mean the program needs to always be loaded at the specific load address. For example, my kernel's load address is 0x8000, aka the top 2GiB of address space, but it can be relocated to anywhere in the range from there to the top of the address space (as long as it fits), for things like, for example, KASLR. Setting the load address to 0 works, the bootloader can relocate the kernel to at or above 0x8000, but this makes debugging with KASLR disabled more annoying as one has to subtract the slide from addresses passed to addr2line, or tell GDB about the slide. > > > From what I know, if a PIE has a specific non-0 load address, it should be > > taken as a hint or preferred load address, but then the program loader > > should be able to apply any slide to it as it sees fit. > > If a PIE doesn't care where to load, set the load address to 0. See above. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #7 from mintsuki --- (In reply to H.J. Lu from comment #5) > (In reply to mintsuki from comment #3) > > Also, when generating a shared object with -shared, without -pie, having a > > non-0 base address does not affect the ELF file type, which is always > > You can't load the multiple shared libraries at the overlapping address > range. > > > ET_DYN. If what you just said is true, then why is this the behaviour here > > and not when making a static PIE? > > A testcase? Download and unpack https://github.com/limine-bootloader/limine-c-template/archive/d90875580fb74c3cf075b659c995e4070d265c24.tar.gz In the extracted directory, run "make -C kernel clean all KCC=gcc KLD=ld.bfd". The output kernel is found at "kernel/bin/kernel". The linker script is found at "kernel/linker.ld". So, building this with ld.bfd, the output ELF file type is ET_EXEC, as in the subject of this bug report. Replacing ld.bfd with ld.gold or ld.lld in the command above will generated a static PIE kernel with type ET_DYN and a non-0 base (0x8000). ld.bfd is the outlier here. Replacing -pie with -shared at line 73 of "kernel/GNUmakefile" and then rebuilding, as mentioned above, will cause all 3 linkers to (correctly) generate an ET_DYN shared object with the specified non-0 base. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #10 from mintsuki --- (In reply to H.J. Lu from comment #8) > (In reply to mintsuki from comment #7) > > (In reply to H.J. Lu from comment #5) > > > (In reply to mintsuki from comment #3) > > > > Also, when generating a shared object with -shared, without -pie, > > > > having a > > > > non-0 base address does not affect the ELF file type, which is always > > > > > > You can't load the multiple shared libraries at the overlapping address > > > range. > > > > > > > ET_DYN. If what you just said is true, then why is this the behaviour > > > > here > > > > and not when making a static PIE? > > > > > > A testcase? > > > > I was asking a testcase of static PIE where ELF type wasn't EXEC when a load > address was specified. There is no such case for ld.bfd. I never said there was, sorry if I wasn't clear enough. That said, lld and gold both allow for such case as previously mentioned. What I believe the bug consists of is the behaviour of ld.bfd not aligning with the other linkers. I think it makes perfect sense for an ET_DYN static PIE with non-0 load address to exist, as previously mentioned, and I believe the bug is ld.bfd not allowing this. If this is policy, then I believe it should be properly documented somewhere, if it wasn't already, and then ld.gold (as part of GNU binutils) should be changed to match ld.bfd's behaviour. Though I hope this isn't done as I consider ld.gold's (and LLD's) behaviour to be the preferrable one. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #12 from mintsuki --- (In reply to H.J. Lu from comment #11) > (In reply to mintsuki from comment #10) > > > If this is policy, then I believe it should be properly documented > > Updating document won't solve your debugging issue. Why does GDB have > no issues with PIE in user space? I do not have a debugging issue, I am merely asking why ld.bfd is refusing to generate static PIEs with type ET_DYN when the base address is non-0, while all the other linkers generate them fine. If the solution is to just never do that, I can easily instead generate a shared object instead of a PIE, with a non-0 base, as that is accepted by ld.bfd just fine, and by lld and gold. Why doesn't ld.bfd allow generating a PIE with a non-0 base when lld and gold allow that? Why is it not possible to change ld.bfd's behaviour to match lld and gold? Where in the ELF spec and/or binutils documentation is it explained that PIE ELFs should only ever have a 0 load address? Why this? -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #14 from mintsuki --- (In reply to H.J. Lu from comment #13) > Does PIE with zero load address cause any real problems for you? Why not just answer the question? Whether it causes real problems for me or not should be irrelevant to the question I am posing, which I won't repeat again as I already did several times over. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #16 from mintsuki --- (In reply to H.J. Lu from comment #15) > Here is the original discussion: > > https://lore.kernel.org/all/CAMe9rOoJvfJ- > r3zbwpecpiulfcdrxprpayzcammxf3k7014...@mail.gmail.com/T/ > #m2cfa035c82e32ca865ec0f1c352b14470dcc7f39 Okay, thank you. Then this seems like it was done as a hack to get the Linux kernel to cooperate, from a quick skimming. I do not agree with that change, but I guess my opinion hardly matters, especially not 10 years after it was done. I hope this can be reverted, then, or that a linker flag is added to allow this, as from all I can gather, this does not go against spec. Especially since shared objects (non-PIE) can be made with arbitary load addresses. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #18 from mintsuki --- (In reply to H.J. Lu from comment #17) > Fixed in 2.43 by: > > https://sourceware.org/git/?p=binutils-gdb.git;a=commit; > h=0daa17bf187cebd5b200f4fd5405cc55e75c391f Thank you very much! I'll just finish off by saying that, while I appreciate this being documented, I would've still preferred the behaviour to be reverted to the previous one, the same as lld and gold. Is there a chance that this will ever be done? It doesn't seem to be an issue for lld and gold, but maybe those aren't used enough and as much as ld.bfd to know... Anyways thanks again. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 mintsuki changed: What|Removed |Added Status|RESOLVED|REOPENED Resolution|FIXED |--- --- Comment #19 from mintsuki --- Why are shared libraries (linked with -shared) allowed to have a non-0 load address? Is this a bug or is this intended behaviour? If it is intended behaviour, then what is said behaviour? Why would said behaviour be any different compared to a -pie with a non-0 load address? I am sorry for my insistence, it's just that I strongly feel like forcing the ELF type to ET_EXEC with non-0 load addresses is a bug; a workaround for a specific situation from 10 years ago that should've never been added... Even the documentation you added doesn't really make anything clear, as it makes assumptions about the loader that are not necessarily what the ELF specification mandates, as far as I can tell. To be more specific, I am the author and main developer of the Limine bootloader; the Limine bootloader has its own boot protocol supporting loading 64-bit ELF files. When loading relocatable ELFs, so far what I had to do was ignore the ET_EXEC file type and instead rely on the presence of the DF_1_PIE flag (which your linker emits anyways even if the ELF type is forced to ET_EXEC) to determine whether an ELF file is relocatable or not (if the type wasn't ET_DYN already). This is because ld.bfd refuses to generate PIE ELFs with a non-0 base and ET_DYN type. There are solutions like recommending people to generate shared objects instead of PIEs, but I feel like that's almost like relying on a workaround to avoid the workaround, and I do not like that. The other solution was what I thought about doing first, which is to set the load address to 0; but as I mentioned before, that breaks addr2line, objdump, and friends if looking for the raw virtual address of something... Is this workaround in ld.bfd *really* still necessary after 10 years from when it was added? Can you please strongly consider reverting this behaviour? I would be extremely grateful if that was done. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #21 from mintsuki --- (In reply to H.J. Lu from comment #20) > It turns out that static PIE with non-zero load address must have ET_EXEC: > > https://sourceware.org/bugzilla/show_bug.cgi?id=31799 > > Otherwise, there is no way for loader to tell if the dynamic section entries > contain the relocated values for the load address or not. Since static PIE > with non-zero load address must have ET_EXEC, PIE with non-zero load address > also should have ET_EXEC. > > BTW, gold doesn't support static PIE and static PIE with non-zero load > address > generated by lld crashes with the fix glibc. At least in the context of making a kernel, gold does generate a static-pie, at least as printed out by the file command, and the output of readelf -a looks similar to ld.bfd's -static -pie generation, even without the -static part. I assume this is because no other dynamic libraries are linked in when using -nostdlib and not specifying any dynamic library explicitly. I do not know what the problem with glibc is, but static-pie kernels loaded by Limine with a non-0 load address (or shared objects with a non-0 load address for that matter) work perfectly fine if relocated (at or above whatever specified non-0 load address). -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #22 from mintsuki --- As far as I can tell, the linked issue seems to indicate more so that this is indeed a problem rather than some glibc bug. Does glibc crash without any patch if you patch ld.bfd to create an ET_DYN instead? -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #25 from mintsuki --- (In reply to H.J. Lu from comment #23) > (In reply to mintsuki from comment #21) > > (In reply to H.J. Lu from comment #20) > > > It turns out that static PIE with non-zero load address must have ET_EXEC: > > > > > > https://sourceware.org/bugzilla/show_bug.cgi?id=31799 > > > > > > Otherwise, there is no way for loader to tell if the dynamic section > > > entries > > > contain the relocated values for the load address or not. Since static > > > PIE > > > with non-zero load address must have ET_EXEC, PIE with non-zero load > > > address > > > also should have ET_EXEC. > > > > > > BTW, gold doesn't support static PIE and static PIE with non-zero load > > > address > > > generated by lld crashes with the fix glibc. > > > > At least in the context of making a kernel, gold does generate a static-pie, > > at least as printed out by the file command, and the output of readelf -a > > looks similar to ld.bfd's -static -pie generation, even without the -static > > part. > > [hjl@gnu-cfl-3 tmp]$ gcc -static-pie x.c > [hjl@gnu-cfl-3 tmp]$ gcc -static-pie x.c -fuse-ld=lld > [hjl@gnu-cfl-3 tmp]$ gcc -static-pie x.c -fuse-ld=gold > /usr/local/bin/ld.gold: --no-dynamic-linker: unknown option > /usr/local/bin/ld.gold: use the --help option for usage information > collect2: error: ld returned 1 exit status > [hjl@gnu-cfl-3 tmp]$ This is not an issue if you call ld.gold manually as done by the kernel in question (see above test case). I know that "you should not invoke the linker outside the driver" and I do agree, but I do make an exception for linking bare metal, freestanding stuff, as I like to have more control over the linking process. With that, I just didn't pass --no-dynamic-linker (as it is not supported by gold, and the linker script makes it a non issue), and I didn't pass -static, as frankly it seems to do nothing anyways when linking a -nostdlib -pie kernel, and isn't supported by gold in combination with -pie. Please once again see the test case above. > > > I assume this is because no other dynamic libraries are linked in when using > > -nostdlib and not specifying any dynamic library explicitly. > > > > I do not know what the problem with glibc is, but static-pie kernels loaded > > by Limine with a non-0 load address (or shared objects with a non-0 load > > address for that matter) work perfectly fine if relocated (at or above > > whatever specified non-0 load address). > > Does your kernel have any dynamic tags which need relocation? > > [hjl@gnu-cfl-3 tmp]$ readelf -d /bin/ld > > Dynamic section at offset 0x11f4a8 contains 35 entries: > TagType Name/Value > 0x0001 (NEEDED) Shared library: > [libbfd-2.42.50.0.1.20240523.so] > 0x0001 (NEEDED) Shared library: [libctf.so.0] > 0x0001 (NEEDED) Shared library: [libjansson.so.4] > 0x0001 (NEEDED) Shared library: [libc.so.6] > 0x000c (INIT) 0x6000 > 0x000d (FINI) 0x4e594 > 0x0019 (INIT_ARRAY) 0x1197f0 > 0x001b (INIT_ARRAYSZ) 8 (bytes) > 0x001a (FINI_ARRAY) 0x1197f8 > 0x001c (FINI_ARRAYSZ) 8 (bytes) > 0x6ef5 (GNU_HASH) 0x460 > 0x0005 (STRTAB) 0x2148 > 0x0006 (SYMTAB) 0x540 > 0x000a (STRSZ) 4860 (bytes) > 0x000b (SYMENT) 24 (bytes) > 0x7000 (DT_X86_64_PLT) 0x7140 > 0x7001 (DT_X86_64_PLTSZ)0x10c0 > 0x7003 (DT_X86_64_PLTENT) 0x10 > 0x0015 (DEBUG) 0x0 > 0x0003 (PLTGOT) 0x120728 > 0x0002 (PLTRELSZ) 6432 (bytes) > 0x0014 (PLTREL) RELA > 0x0017 (JMPREL) 0x39c8 > 0x0007 (RELA) 0x37a0 > 0x0008 (RELASZ) 552 (bytes) > 0x0009 (RELAENT)24 (bytes) > 0x001e (FLAGS) BIND_NOW > 0x6ffb (FLAGS_1)Flags: NOW PIE > 0x6ffe (VERNEED)0x36a0 > 0x6fff (VERNEEDNUM) 2 > 0x6ff0 (VERSYM) 0x3444 > 0x0024 (RELR) 0x52e8 > 0x0023 (RELRSZ) 536 (bytes) > 0x0025 (RELRENT)8 (bytes) > 0x (NULL) 0x0 > [hjl@gnu-cfl-3 tmp]$ > > These dynamic tags with addresses must be relocated before accessing the > memory. The test case above is too small to have any necessary relocation, but I have another kernel using the same build system that has plenty of R_X86_64_RELATIVE relocations and it works fine after Limine relocates it. -- You are receivin
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #26 from mintsuki --- (In reply to H.J. Lu from comment #24) > (In reply to mintsuki from comment #22) > > As far as I can tell, the linked issue seems to indicate more so that this > > is indeed a problem rather than some glibc bug. > > > > Does glibc crash without any patch if you patch ld.bfd to create an ET_DYN > > instead? > > My ld ET_EXEC change predates static PIE. lld generates ET_DYN and there is > no way for static PIE with non-zero load address to work if marked ET_DYN. Well, evidently it works fine enough for Limine to load these properly as made by ld.bfd, lld, or gold... Honestly to me this seems more of a glibc bug than anything, unless I am missing something. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #27 from mintsuki --- This is the aforementioned other kernel's readelf -d output: Dynamic section at offset 0x46b70 contains 13 entries: TagType Name/Value 0x0004 (HASH) 0x8003c140 0x6ef5 (GNU_HASH) 0x8003c150 0x0005 (STRTAB) 0x8003c138 0x0006 (SYMTAB) 0x8003c120 0x000a (STRSZ) 1 (bytes) 0x000b (SYMENT) 24 (bytes) 0x0015 (DEBUG) 0x0 0x0007 (RELA) 0x8003c170 0x0008 (RELASZ) 27264 (bytes) 0x0009 (RELAENT)24 (bytes) 0x6ffb (FLAGS_1)Flags: PIE 0x6ff9 (RELACOUNT) 1136 0x (NULL) 0x0 And then: Relocation section '.rela.dyn' at offset 0x3c170 contains 1136 entries: Offset Info Type Sym. ValueSym. Name + Addend 80042bf8 0008 R_X86_64_RELATIVE-7ffbc3a0 80042c08 0008 R_X86_64_RELATIVE-7ffbc300 80043c60 0008 R_X86_64_RELATIVE-7ffcaa06 80043c70 0008 R_X86_64_RELATIVE-7fffc3a0 80043d00 0008 R_X86_64_RELATIVE-7ffca920 80043d10 0008 R_X86_64_RELATIVE-7fff8670 80043ea0 0008 R_X86_64_RELATIVE-7ffca12c 80043ea8 0008 R_X86_64_RELATIVE-7ffca119 80043eb0 0008 R_X86_64_RELATIVE-7ffca113 80043eb8 0008 R_X86_64_RELATIVE-7ffca10f 80043ec0 0008 R_X86_64_RELATIVE-7ffca104 80043ec8 0008 R_X86_64_RELATIVE-7ffca0fb 80043ed0 0008 R_X86_64_RELATIVE-7ffca0e6 80043ed8 0008 R_X86_64_RELATIVE-7ffca0d7 ... continues ... -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #30 from mintsuki --- (In reply to H.J. Lu from comment #29) > (In reply to mintsuki from comment #27) > > This is the aforementioned other kernel's readelf -d output: > > > > > > Dynamic section at offset 0x46b70 contains 13 entries: > > TagType Name/Value > > 0x0004 (HASH) 0x8003c140 > > 0x6ef5 (GNU_HASH) 0x8003c150 > > 0x0005 (STRTAB) 0x8003c138 > > 0x0006 (SYMTAB) 0x8003c120 > > 0x000a (STRSZ) 1 (bytes) > > 0x000b (SYMENT) 24 (bytes) > > 0x0015 (DEBUG) 0x0 > > 0x0007 (RELA) 0x8003c170 > > 0x0008 (RELASZ) 27264 (bytes) > > 0x0009 (RELAENT)24 (bytes) > > 0x6ffb (FLAGS_1)Flags: PIE > > 0x6ff9 (RELACOUNT) 1136 > > 0x (NULL) 0x0 > > > > Your kernel contains the relocated addresses in dynamic section since its > load address != 0. Try load address == 0, these addresses will be different. > You need to decide how to handle addresses like > > 0x0007 (RELA) 0x8003c170 > > Should you add load address to them or not? Well, the way Limine has always dealt with this issue is: https://github.com/limine-bootloader/limine/blob/c204af454fc9c11b8ef3633664b6e03817c33ff1/common/lib/elf.c#L223 Basically, it tries to find a PHDR which contains the RELA section, and if it find it, it subtracts the PHDR's virtual address and adds its offset in order to find the offset of the RELA section inside the ELF file itself. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #32 from mintsuki --- (In reply to H.J. Lu from comment #31) > (In reply to mintsuki from comment #30) > > Basically, it tries to find a PHDR which contains the RELA section, and if > > it find it, it subtracts the PHDR's virtual address and adds its offset in > > order to find the offset of the RELA section inside the ELF file itself. > > In glibc, we know it is a static PIE. We relocate PT_DYNAMIC segment only if > it is ET_DYN. So what is the issue? And in any case, it doesn't feel right to me to have this behaviour in ld just to work around quirks of a specific ELF loader out of many. If anything, it needs to be handled in glibc, and the behaviour of ld should be reverted to match gold and lld. Just my opinion of course. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #34 from mintsuki --- (In reply to H.J. Lu from comment #33) > (In reply to mintsuki from comment #32) > > (In reply to H.J. Lu from comment #31) > > > (In reply to mintsuki from comment #30) > > > > Basically, it tries to find a PHDR which contains the RELA section, and > > > > if > > > > it find it, it subtracts the PHDR's virtual address and adds its offset > > > > in > > > > order to find the offset of the RELA section inside the ELF file itself. > > > > > > In glibc, we know it is a static PIE. We relocate PT_DYNAMIC segment > > > only if > > > it is ET_DYN. > > > > So what is the issue? And in any case, it doesn't feel right to me to have > > This is only after my patch: > > https://patchwork.sourceware.org/project/glibc/list/?series=34373 > > Currently glibc relocates PT_DYNAMIC segment unconditionally. > > > this behaviour in ld just to work around quirks of a specific ELF loader out > > of many. > > > > If anything, it needs to be handled in glibc, and the behaviour of ld should > > be reverted to match gold and lld. > > > > The static PIE generated by ldd with non-zero load address won't work with > glibc before and after my glibc fix. I will open an lld issue after glibc > is fixed. I *strongly* disagree with this. Why are glibc implementation details dictating how ld.bfd operates? Where does it say non-0 load addresses for static-PIE/PIE are not allowed in the ELF specification? If it is allowed, why is ld.bfd not allowing me to do it despite Limine accepting this form of ELF files just fine? At least please consider adding a flag or linker script directive to manually set the ELF type... -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #36 from mintsuki --- (In reply to H.J. Lu from comment #35) > (In reply to mintsuki from comment #34) > > > > The static PIE generated by ldd with non-zero load address won't work with > > > glibc before and after my glibc fix. I will open an lld issue after glibc > > > is fixed. > > > > I *strongly* disagree with this. > > > > Why are glibc implementation details dictating how ld.bfd operates? Where > > This is how ELF works on Linux. Well, ELF is not Linux specific, though. > > > does it say non-0 load addresses for static-PIE/PIE are not allowed in the > > ELF specification? If it is allowed, why is ld.bfd not allowing me to do it > > Static PIE isn't the part of ELF spec. There was a discussion: > > https://groups.google.com/g/generic-abi/c/mBKlSNldFW4/m/GRddmWGGBQAJ > Then what is ld.bfd following, exactly? Just what Linux/glibc wants? How loosely specified (or not at all) can this be? > > despite Limine accepting this form of ELF files just fine? > > > > At least please consider adding a flag or linker script directive to > > manually set the ELF type... > > That will generate the wrong static PIE with non-zero load address. You > should > check DF_1_PIE for PIE, not ET_DYN. Limine already does that. The algorithm for determining whether an ELF is relocatable or not is at https://github.com/limine-bootloader/limine/blob/c204af454fc9c11b8ef3633664b6e03817c33ff1/common/lib/elf.c#L148-L181 If that was the case, you could've said it earlier and it would've saved the time for this discussion. I still do not like this, but it never caused issues to me or Limine or Limine users. It's just a purely technical argument, because ld.bfd diverged in behaviour compared to other linkers in a silly way. Now I see that this is done to make Linux/glibc happy, and thus unlikely to be fixed or reverted. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #38 from mintsuki --- (In reply to Fangrui Song from comment #37) > I agree with mintsuki . The "-pie -Ttext-segment=non-zero => ET_EXEC" hack > should not be needed. > > From https://sourceware.org/pipermail/binutils/2013-December/083381.html > > > 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. > > Was the intention for the following command to load the text segment at an > address >= 0x6000 ? > > ``` > % cat a.c > #include > int main() { printf("%p\n", main); } > % gcc -pie -Wl,-no-pie a.c -fuse-ld=bfd > -Wl,--no-relax,-Ttext-segment=0x6000 -o a > % ./a > 0x60001139 > % ./a > 0x60001139 # no ASLR > ``` > > Changing ET_DYN to ET_EXEC fulfills the address requirement but disables > ASLR. > Is it intentional? > > I added `--no-pie` to GNU ld in 2021: > https://sourceware.org/cgit/binutils-gdb/commit/ > ?id=e8f6c2a5bab10b039a12b69a30a8248c91161e11 , with which we can do the > following instead. (GNU ld also needs `--no-relax` while lld doesn't). > > ``` > % gcc -pie a.c -fuse-ld=bfd > -Wl,--no-pie,--no-relax,-Ttext-segment=0x6000 -o a > % ./a > 0x60001139 > % ./a > 0x60001139 > ``` Thanks for agreeing with me and reopening this bug report. I appreciate that someone else sees this for the bug that it is, rather than trying to hand wave the issue away. I hope it will get addressed. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #41 from mintsuki --- (In reply to Adhemerval Zanella from comment #39) > (In reply to Fangrui Song from comment #37) > > I agree with mintsuki . The "-pie -Ttext-segment=non-zero => ET_EXEC" hack > > should not be needed. > > > > From https://sourceware.org/pipermail/binutils/2013-December/083381.html > > > > > 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. > > > > Was the intention for the following command to load the text segment at an > > address >= 0x6000 ? > > > > ``` > > % cat a.c > > #include > > int main() { printf("%p\n", main); } > > % gcc -pie -Wl,-no-pie a.c -fuse-ld=bfd > > -Wl,--no-relax,-Ttext-segment=0x6000 -o a > > % ./a > > 0x60001139 > > % ./a > > 0x60001139 # no ASLR > > ``` > > > > Changing ET_DYN to ET_EXEC fulfills the address requirement but disables > > ASLR. > > Is it intentional? > > That's my understanding of reading the -Ttext-segment documentation. The > question is whether we relax the semantic to have it as a minimum address or > define it as the expected address (thus disabling ASLR as a consequence). My understanding is that the PT_LOAD PHDR addresses could be slid, as long as they are slid above the specified address. The fact that the first PT_LOAD PHDR is 0 or not should be irrelevant. It makes no sense for it to be relevant, let alone for it to dictate the ELF type to be ET_EXEC. This is how Limine behaves, and how I interpret the ELF format. > > I don't have a strong opinion, but currently, Linux only enforces the former > (I think it is the main reason this makes some sense) so we will need to > discuss with kernel developers the expected semantics. > > > > > I added `--no-pie` to GNU ld in 2021: > > https://sourceware.org/cgit/binutils-gdb/commit/ > > ?id=e8f6c2a5bab10b039a12b69a30a8248c91161e11 , with which we can do the > > following instead. (GNU ld also needs `--no-relax` while lld doesn't). > > > > ``` > > % gcc -pie a.c -fuse-ld=bfd > > -Wl,--no-pie,--no-relax,-Ttext-segment=0x6000 -o a > > % ./a > > 0x60001139 > > % ./a > > 0x60001139 > > ``` -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #42 from mintsuki --- (In reply to H.J. Lu from comment #40) > -Ttext-segment=0x6000 should create a binary which is guaranteed to > be > loaded at 0x6000. ...as long as it's not a PIE. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #44 from mintsuki --- (In reply to H.J. Lu from comment #43) > (In reply to mintsuki from comment #42) > > (In reply to H.J. Lu from comment #40) > > > -Ttext-segment=0x6000 should create a binary which is guaranteed > > > to > > > be > > > loaded at 0x6000. > > > > ...as long as it's not a PIE. > > Please read x86-64 psABI: > > https://gitlab.com/x86-psABIs/x86-64-ABI > > PIE is the only way to create a small mode executable loaded at > 0x6000. Can you not use -mcmodel=large? In any case even if that was the case, it should be opt-in to make the ELF ET_EXEC, rather than automatic and not explicitly mentioned in a warning or anything. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #46 from mintsuki --- (In reply to H.J. Lu from comment #45) > (In reply to mintsuki from comment #44) > > (In reply to H.J. Lu from comment #43) > > > (In reply to mintsuki from comment #42) > > > > (In reply to H.J. Lu from comment #40) > > > > > -Ttext-segment=0x6000 should create a binary which is > > > > > guaranteed to > > > > > be > > > > > loaded at 0x6000. > > > > > > > > ...as long as it's not a PIE. > > > > > > Please read x86-64 psABI: > > > > > > https://gitlab.com/x86-psABIs/x86-64-ABI > > > > > > PIE is the only way to create a small mode executable loaded at > > > 0x6000. > > > > Can you not use -mcmodel=large? In any case even if that was the case, it > > There are 2 issues with -mcmodel=large: > > 1. Since there are no -mcmodel=large run-time libraries, you can't use > -mcmodel=large > to create any meaningful binaries. > 2. -mcmodel=large performance is much slower. > > > should be opt-in to make the ELF ET_EXEC, rather than automatic and not > > explicitly mentioned in a warning or anything. > > Opt-in to ET_EXEC will be wrong. Why will it be wrong? What if someone (me) wants to make a PIE that loads at a minimum at the specified address, but can be relocated above it? Currently ld makes this impossible by simply checking the ELF type, forcing my ELF loader to additionally check for the presence of the DF_1_PIE flag to decide whether an ELF file is relocatable or not... ...but Linux doesn't do that, apparently, but instead forces the load address to be the one specified, due to the ELF type being ET_EXEC. Earlier you said I should check DF_1_PIE to determine relocatability... so which one is it? If I check for DF_1_PIE then I am not following the same behaviour as the Linux ELF loader, which means that I either break from Linux's behaviour, or I follow it, but that means that ld will never allow me to make an ET_DYN PIE with a non-0 load address. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #48 from mintsuki --- (In reply to H.J. Lu from comment #47) > (In reply to mintsuki from comment #46) > g. > > > > > > Opt-in to ET_EXEC will be wrong. > > > > Why will it be wrong? What if someone (me) wants to make a PIE that loads at > > It is wrong because -Ttext-segment=0x6000 no longer works. > > > a minimum at the specified address, but can be relocated above it? Currently > > ld makes this impossible by simply checking the ELF type, forcing my ELF > > loader to additionally check for the presence of the DF_1_PIE flag to decide > > whether an ELF file is relocatable or not... > > > > ...but Linux doesn't do that, apparently, but instead forces the load > > address to be the one specified, due to the ELF type being ET_EXEC. > > > > Earlier you said I should check DF_1_PIE to determine relocatability... so > > No, that was not what I said. DF_1_PIE can be used to determine if a binary > is PIE. Okay, then how can I make a *relocatable* aka ET_DYN (?) ELF file which is PIE and has a non-0 text segment load address using ld? This is, as far as my knowledge goes, *impossible* using GNU ld.bfd. Why? I can still make an ET_DYN ELF using -shared instead of -pie, but then I have to build using -fPIC rather than -fPIE, as far as I understand. And in any case I don't understand why the limitation. > > > which one is it? If I check for DF_1_PIE then I am not following the same > > behaviour as the Linux ELF loader, which means that I either break from > > Linux's behaviour, or I follow it, but that means that ld will never allow > > me to make an ET_DYN PIE with a non-0 load address. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #50 from mintsuki --- (In reply to H.J. Lu from comment #49) > (In reply to mintsuki from comment #48) > > (In reply to H.J. Lu from comment #47) > > > (In reply to mintsuki from comment #46) > > > g. > > > > > > > > > > Opt-in to ET_EXEC will be wrong. > > > > > > > > Why will it be wrong? What if someone (me) wants to make a PIE that > > > > loads at > > > > > > It is wrong because -Ttext-segment=0x6000 no longer works. > > > > > > > a minimum at the specified address, but can be relocated above it? > > > > Currently > > > > ld makes this impossible by simply checking the ELF type, forcing my ELF > > > > loader to additionally check for the presence of the DF_1_PIE flag to > > > > decide > > > > whether an ELF file is relocatable or not... > > > > > > > > ...but Linux doesn't do that, apparently, but instead forces the load > > > > address to be the one specified, due to the ELF type being ET_EXEC. > > > > > > > > Earlier you said I should check DF_1_PIE to determine relocatability... > > > > so > > > > > > No, that was not what I said. DF_1_PIE can be used to determine if a > > > binary > > > is PIE. > > > > Okay, then how can I make a *relocatable* aka ET_DYN (?) ELF file which is > > PIE and has a non-0 text segment load address using ld? This is, as far as > > my knowledge goes, *impossible* using GNU ld.bfd. Why? > > Why can't you check DF_1_PIE for PIE? That is what I do now, but to check for *relocatability*. PIE in and of itself is not something that tells me whether I should relocate (for KASLR for example) or not. That is what you just said. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #53 from mintsuki --- (In reply to H.J. Lu from comment #51) > (In reply to mintsuki from comment #50) > > > > Why can't you check DF_1_PIE for PIE? > > > > That is what I do now, but to check for *relocatability*. PIE in and of > > itself is not something that tells me whether I should relocate (for KASLR > > for example) or not. That is what you just said. > > If DF_1_PIE is set, the binary can be relocated to any address. What did I > miss? This? : > > > > Earlier you said I should check DF_1_PIE to determine relocatability... > > > > so > > > > > > No, that was not what I said. DF_1_PIE can be used to determine if a > > > binary > > > is PIE. You said setting the text segment base address to non-0 means the load address has to be the one specified, due to the ELF type being forced to ET_EXEC by your linker; thus you *cannot* relocate it to any address. Linux *does not* relocate it, in fact, and ASLR is not done. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #54 from mintsuki --- (In reply to H.J. Lu from comment #52) > (In reply to H.J. Lu from comment #51) > > (In reply to mintsuki from comment #50) > > > > > > Why can't you check DF_1_PIE for PIE? > > > > > > That is what I do now, but to check for *relocatability*. PIE in and of > > > itself is not something that tells me whether I should relocate (for KASLR > > > for example) or not. That is what you just said. > > > > If DF_1_PIE is set, the binary can be relocated to any address. What did I > > miss? > > The first PT_LOAD segment has non-0 p_vaddr, the program may misbehave if > the load address != p_vaddr. How is this possible? Under which circumstances? It works fine with all the other linkers for me. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #56 from mintsuki --- (In reply to mintsuki from comment #54) > (In reply to H.J. Lu from comment #52) > > (In reply to H.J. Lu from comment #51) > > > (In reply to mintsuki from comment #50) > > > > > > > > Why can't you check DF_1_PIE for PIE? > > > > > > > > That is what I do now, but to check for *relocatability*. PIE in and of > > > > itself is not something that tells me whether I should relocate (for > > > > KASLR > > > > for example) or not. That is what you just said. > > > > > > If DF_1_PIE is set, the binary can be relocated to any address. What did I > > > miss? > > > > The first PT_LOAD segment has non-0 p_vaddr, the program may misbehave if > > the load address != p_vaddr. > > How is this possible? Under which circumstances? It works fine with all the > other linkers for me. And it has always worked fine when I simply checked DF_1_PIE and relocated to different addresses regardless of the ELF type. The only difference between 0 and non-0 base is that ld.bfd decides to force the ELF type to ET_EXEC, and nothing more. I do not care about what Linux does, nor what glibc does; this is purely between me and the linker, what some specific OS or ELF loader does should not be of any concern to me. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #57 from mintsuki --- (In reply to H.J. Lu from comment #55) > (In reply to mintsuki from comment #54) > > (In reply to H.J. Lu from comment #52) > > > (In reply to H.J. Lu from comment #51) > > > > (In reply to mintsuki from comment #50) > > > > > > > > > > Why can't you check DF_1_PIE for PIE? > > > > > > > > > > That is what I do now, but to check for *relocatability*. PIE in and > > > > > of > > > > > itself is not something that tells me whether I should relocate (for > > > > > KASLR > > > > > for example) or not. That is what you just said. > > > > > > > > If DF_1_PIE is set, the binary can be relocated to any address. What > > > > did I > > > > miss? > > > > > > The first PT_LOAD segment has non-0 p_vaddr, the program may misbehave if > > > the load address != p_vaddr. > > > > How is this possible? Under which circumstances? It works fine with all the > > other linkers for me. > > It works for your programs doesn't mean that it works all programs some of > which > won't correctly if ET_DYN is used. Which? Under which circumstances? Do you have an example that doesn't involve Linux/glibc? Is this an actual ELF/toolchain issue, or is it some Linux/glibc specific issue? If the latter is the case, why on earth is this being worked around in binutils rather than fixed in Linux/glibc? -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #59 from mintsuki --- (In reply to Adhemerval Zanella from comment #58) > (In reply to mintsuki from comment #41) > > (In reply to Adhemerval Zanella from comment #39) > > > (In reply to Fangrui Song from comment #37) > > > > I agree with mintsuki . The "-pie -Ttext-segment=non-zero => ET_EXEC" > > > > hack > > > > should not be needed. > > > > > > > > From https://sourceware.org/pipermail/binutils/2013-December/083381.html > > > > > > > > > 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. > > > > > > > > Was the intention for the following command to load the text segment at > > > > an > > > > address >= 0x6000 ? > > > > > > > > ``` > > > > % cat a.c > > > > #include > > > > int main() { printf("%p\n", main); } > > > > % gcc -pie -Wl,-no-pie a.c -fuse-ld=bfd > > > > -Wl,--no-relax,-Ttext-segment=0x6000 -o a > > > > % ./a > > > > 0x60001139 > > > > % ./a > > > > 0x60001139 # no ASLR > > > > ``` > > > > > > > > Changing ET_DYN to ET_EXEC fulfills the address requirement but disables > > > > ASLR. > > > > Is it intentional? > > > > > > That's my understanding of reading the -Ttext-segment documentation. The > > > question is whether we relax the semantic to have it as a minimum address > > > or > > > define it as the expected address (thus disabling ASLR as a consequence). > > > > My understanding is that the PT_LOAD PHDR addresses could be slid, as long > > as they are slid above the specified address. The fact that the first > > PT_LOAD PHDR is 0 or not should be irrelevant. It makes no sense for it to > > be relevant, let alone for it to dictate the ELF type to be ET_EXEC. > > > > This is how Limine behaves, and how I interpret the ELF format. > > Unfortunately, this is not what binutils documentation states ("When > creating an ELF executable, it will set the address of the first byte of the > text segment") nor how Linux handles it (where ET_DYN does not enforce > e_entry). > > And it seems to be a Linux-specific issue, since on FreeBSD: > > $ cc -pie a.c -fuse-ld=lld -Wl,--no-relax,--image-base=0x6000 > -Wl,-z,notext -o a-lld > $ readelf -h a-lld > ELF Header: > Magic: 7f 45 4c 46 02 01 01 09 00 00 00 00 00 00 00 00 > Class: ELF64 > Data: 2's complement, little endian > Version: 1 (current) > OS/ABI:FreeBSD > ABI Version: 0 > Type: DYN (Shared object file) > Machine: Advanced Micro Devices x86-64 > Version: 0x1 > Entry point address: 0x600016b0 > Start of program headers: 64 (bytes into file) > Start of section headers: 12928 (bytes into file) > Flags: 0 > Size of this header: 64 (bytes) > Size of program headers: 56 (bytes) > Number of program headers: 11 > Size of section headers: 64 (bytes) > Number of section headers: 39 > Section header string table index: 37 > $ readelf -d a-lld | grep -w FLAGS_1 > 0x6ffb FLAGS_1 PIE > $ doas sysctl -w kern.elf64.aslr.pie_enable=1 > kern.elf64.aslr.pie_enable: 0 -> 1 > $ ./a-lld > 0x600019d0 > $ ./a-lld > 0x600019d0 > > So maybe we either enable this iff targeting Linux, or check if kernel is > willing to enforce e_entry even for DYN. > > I am not sure if the correct approach is relaxing the > '-Ttext-segment/--image-base' to be a minimum address. For this, I would > add another linker option. I am not sure what you mean with "willing to enforce e_entry". In any case, how about checking what the generated ELF file's OS/ABI is and only doing the DYN->EXEC hack if it happens to be GNU/Linux? -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #61 from mintsuki --- (In reply to mintsuki from comment #59) > (In reply to Adhemerval Zanella from comment #58) > > (In reply to mintsuki from comment #41) > > > (In reply to Adhemerval Zanella from comment #39) > > > > (In reply to Fangrui Song from comment #37) > > > > > I agree with mintsuki . The "-pie -Ttext-segment=non-zero => ET_EXEC" > > > > > hack > > > > > should not be needed. > > > > > > > > > > From > > > > > https://sourceware.org/pipermail/binutils/2013-December/083381.html > > > > > > > > > > > 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. > > > > > > > > > > Was the intention for the following command to load the text segment > > > > > at an > > > > > address >= 0x6000 ? > > > > > > > > > > ``` > > > > > % cat a.c > > > > > #include > > > > > int main() { printf("%p\n", main); } > > > > > % gcc -pie -Wl,-no-pie a.c -fuse-ld=bfd > > > > > -Wl,--no-relax,-Ttext-segment=0x6000 -o a > > > > > % ./a > > > > > 0x60001139 > > > > > % ./a > > > > > 0x60001139 # no ASLR > > > > > ``` > > > > > > > > > > Changing ET_DYN to ET_EXEC fulfills the address requirement but > > > > > disables > > > > > ASLR. > > > > > Is it intentional? > > > > > > > > That's my understanding of reading the -Ttext-segment documentation. > > > > The > > > > question is whether we relax the semantic to have it as a minimum > > > > address or > > > > define it as the expected address (thus disabling ASLR as a > > > > consequence). > > > > > > My understanding is that the PT_LOAD PHDR addresses could be slid, as long > > > as they are slid above the specified address. The fact that the first > > > PT_LOAD PHDR is 0 or not should be irrelevant. It makes no sense for it to > > > be relevant, let alone for it to dictate the ELF type to be ET_EXEC. > > > > > > This is how Limine behaves, and how I interpret the ELF format. > > > > Unfortunately, this is not what binutils documentation states ("When > > creating an ELF executable, it will set the address of the first byte of the > > text segment") nor how Linux handles it (where ET_DYN does not enforce > > e_entry). > > > > And it seems to be a Linux-specific issue, since on FreeBSD: > > > > $ cc -pie a.c -fuse-ld=lld -Wl,--no-relax,--image-base=0x6000 > > -Wl,-z,notext -o a-lld > > $ readelf -h a-lld > > ELF Header: > > Magic: 7f 45 4c 46 02 01 01 09 00 00 00 00 00 00 00 00 > > Class: ELF64 > > Data: 2's complement, little endian > > Version: 1 (current) > > OS/ABI:FreeBSD > > ABI Version: 0 > > Type: DYN (Shared object file) > > Machine: Advanced Micro Devices x86-64 > > Version: 0x1 > > Entry point address: 0x600016b0 > > Start of program headers: 64 (bytes into file) > > Start of section headers: 12928 (bytes into file) > > Flags: 0 > > Size of this header: 64 (bytes) > > Size of program headers: 56 (bytes) > > Number of program headers: 11 > > Size of section headers: 64 (bytes) > > Number of section headers: 39 > > Section header string table index: 37 > > $ readelf -d a-lld | grep -w FLAGS_1 > > 0x6ffb FLAGS_1 PIE > > $ doas sysctl -w kern.elf64.aslr.pie_enable=1 > > kern.elf64.aslr.pie_enable: 0 -> 1 > > $ ./a-lld > > 0x600019d0 > > $ ./a-lld > > 0x600019d0 > > > > So maybe we either enable this iff targeting Linux, or check if kernel is > > willing to enforce e_entry even for DYN. > > > > I am not sure if the correct approach is relaxing the > > '-Ttext-segment/--image-base' to be a minimum address. For this, I would > > add another linker option. > > I am not sure what you mean with "willing to enforce e_entry". > > In any case, how about checking what the generated ELF file's OS/ABI is and > only doing the DYN->EXEC hack if it happens to be GNU/Linux? Actually I don't think that may be possible, at least not by checking the OS/ABI field alone, given on my Linux host it seems to be a generic UNIX - System V value... -- You are rece
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #62 from mintsuki --- (In reply to Adhemerval Zanella from comment #60) > (In reply to mintsuki from comment #59) > > (In reply to Adhemerval Zanella from comment #58) > > > (In reply to mintsuki from comment #41) > > > > So maybe we either enable this iff targeting Linux, or check if kernel is > > > willing to enforce e_entry even for DYN. > > > > > > I am not sure if the correct approach is relaxing the > > > '-Ttext-segment/--image-base' to be a minimum address. For this, I would > > > add another linker option. > > > > I am not sure what you mean with "willing to enforce e_entry". > > I meant enforcing the vaddr set by e_entry for ET_DYN (and thus disabling > ASLR), so this hack won't be necessary for Linux. Ah, I see. Makes sense. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #64 from mintsuki --- (In reply to Adhemerval Zanella from comment #63) > (In reply to mintsuki from comment #61) > > > > Actually I don't think that may be possible, at least not by checking the > > OS/ABI field alone, given on my Linux host it seems to be a generic UNIX - > > System V value... > > I think BFD can use the emulation (-m) option for this, since, for instance, > gcc will pass -maarch64linux for aarch64-linux-gnu. On my host system, gcc seems to just pass -m elf_x86_64, which is the same emulation mode we pass in the Limine template... -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for static PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #66 from mintsuki --- (In reply to Fangrui Song from comment #65) > > > Changing ET_DYN to ET_EXEC fulfills the address requirement but disables > > > ASLR. > > > Is it intentional? > > > > That's my understanding of reading the -Ttext-segment documentation. The > > question is whether we relax the semantic to have it as a minimum address > > or define it as the expected address (thus disabling ASLR as a > > consequence). > > > > I don't have a strong opinion, but currently, Linux only enforces the > > former (I think it is the main reason this makes some sense) so we will > > need to discuss with kernel developers the expected semantics. > > If there is a strong need for the address requirement (>=p_vaddr), Linux > kernel and glibc have the capability to implement it. > However, this alone does not justify keeping the ld hack that sets ET_EXEC > for -pie -Ttext-segment=$non_zero. > > > -Ttext-segment=0x6000 should create a binary which is guaranteed to > > be > > loaded at 0x6000. > > -Ttext-segment sets the address of the first byte of the text segment, which > likely influences the p_vaddr member of a PT_LOAD segment. > When e_type is ET_EXEC, this address is also the virtual address of the > first memory area. > However, if e_type is ET_DYN, there's no guarantee of this address, and > fulfilling this request is left to the discretion of the loaders. > > Since ld offers the -no-pie flag, there's no need for a workaround to make > -pie behave similarly. > (In addition, DF_1_PIE with ET_EXEC is very odd.) Indeed. This is not what lld does, at all. Also the statement that PIE executables with non-0 load addresses would misbehave if relocated is also something that I cannot wrap my head around, especially since I have been relocating these for years without issues. Those generated by lld, gold, and bfd, the former 2 of which have absolutely no issue generating a PIE with non-0 load address. Also I will change the title of the bug report from static PIE to PIE, because the PIE having or not having dynamically linked libraries is irrelevant to the issue at hand. > > If a user desires both address>=0x6000 && ASLR, this could be > achieved if ET_DYN is used and loaders satisfy the address requirement. > However, retaining the ET_EXEC hack in ld would prevent the fulfillment of > this goal. > > > PIE is the only way to create a small mode executable loaded at > > 0x6000. > > This is an oversimplification. > > The -mcmodel= flag imposes specific code generation restrictions that allow > relocatable files to be used in certain address space layouts after linking. > While it's (almost) a sufficient condition, it's not a necessary one. > > Achieving high-address functionality doesn't necessitate -mcmodel=large. For > instance, you can use PIC symbol addressing (combining -mcmodel=small -fpie > with non-preemptible symbols) to achieve the same result. > If your code is larger than 2GiB, you can even use range extension thunks. > > https://maskray.me/blog/2023-05-14-relocation-overflow-and-code-models#x86- > 64-code-models > > Similarly, for a function call, we no longer assume that the address of > the function or its PLT entry is within the ±2GiB range from the program > counter, so call callee cannot be used. > > Actually, call callee can still be used if we implement range extension > thunks in the linker, unfortunately GCC/GNU ld did not pursue this direction. > > > There are 2 issues with -mcmodel=large: > > > > 1. Since there are no -mcmodel=large run-time libraries, you can't use > > -mcmodel=large > > to create any meaningful binaries. > > 2. -mcmodel=large performance is much slower. > > True. (1) is an ecosystem issue with -mcmodel=large. > However, this point is unrelated to the ld ET_EXEC hack. > > > I think BFD can use the emulation (-m) option for this, since, for > > instance, gcc will pass -maarch64linux for aarch64-linux-gnu. > > I don't think this is necessary. > > `-pie -Wl,-no-pie` works today (lld doesn't even need `--no-relax`). > Therefore, there isn't a strong argument retaining the ET_EXEC hack. > > % gcc -pie -Wl,-no-pie a.c -fuse-ld=bfd > -Wl,--no-relax,-Ttext-segment=0x6000 -o a > % ./a > 0x60001139 > % ./a > 0x60001139 # no ASLR -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 mintsuki changed: What|Removed |Added Summary|ld.bfd makes ELFs of type |ld.bfd makes ELFs of type |ET_EXEC for static PIEs |ET_EXEC for PIEs when load |when load address is non-0 |address is non-0 -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #67 from mintsuki --- I'd like to give a summary of the issue, as the whole thread is pretty long and may get confusing: ld.bfd, *regardless of target*, be it GNU/Linux or even *freestanding environments* (for example using an x86_64-elf binutils toolchain), generates perfectly fine relocatable PIE ELFs with proper PT_DYNAMIC segment and all, but with ELF type ET_EXEC, when the base load address is non-0, as this was added as some coarse workaround for some GNU/Linux specific issue. This is a bug. It should be fixed, as ld.bfd doesn't exist in a bubble where it only builds executables for GNU/Linux necessitating some questionable workaround. Additionally, both ld.lld and ld.gold do not have this bug. What's worse: this[1] issue was opened against LLD requesting that the bug be added to LLD! Please, just revert the 2013 "workaround" for GNU/Linux or make it less coarse, and fix this bug. References: 1. https://github.com/llvm/llvm-project/issues/93420 -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 mintsuki changed: What|Removed |Added Version|2.42|2.43 -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #68 from mintsuki --- Bug is still present in 2.43... -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 mintsuki changed: What|Removed |Added Version|2.43|2.43.1 -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 mintsuki changed: What|Removed |Added Severity|normal |critical -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #70 from mintsuki --- The bug is still present in 2.43.1. I also elevated the importance to "critical" since I was allowed to do so. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug ld/31795] ld.bfd makes ELFs of type ET_EXEC for PIEs when load address is non-0
https://sourceware.org/bugzilla/show_bug.cgi?id=31795 --- Comment #71 from mintsuki --- Could, in principle, this issue be addressed now that glibc bug #31799 has been fixed? -- You are receiving this mail because: You are on the CC list for the bug.