tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Binutils 2.39 on -CURRENT: Seemingly bogus warnings about .note.GNU-stack



Hi,


-CURRNET has Binutils 2.39 which introduces new warnings about .note.GNU-stack section [1]. It's a GNU extension in the ELF header to ask the kernel to mark the stack pages executable or not. However, stack on NetBSD is always non-executable and our kernel just ignores it (which is fine).

It appears that recent versions of GCC emit .note.GNU-stack on Linux but don't on NetBSD (which is also fine), and BFD ld gladly produces executables without PT_GNU_STACK when every object file lacks .note.GNU-stack section.

Things get interesting when some of object files to be linked together have .note.GNU-stack but others don't. In this case Binutils 2.39 emits the following warning and marks the resulting object as "stack needs to be executable":

ld: warning: foo.o: missing .note.GNU-stack section implies executable stack ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker

I believe this doesn't make sense on NetBSD, where stack is never executable. Binutils has a configure-time option "--enable-warn-execstack=no" to disable this, and I think we should use this option. But (1) I don't know how configure scripts are executed in base, and (2) I'd like to hear how other people think. Here's a test case:
https://gist.github.com/depressed-pho/2d379beb39759d810c93d19dda42eede

[1] https://www.redhat.com/en/blog/linkers-warnings-about-executable-stacks-and-segments


# The reason why I stumbled on this (TL;DR)

I'm in the process of porting GHC, The Glasgow Haskell Compiler 9.4 to pkgsrc. GHC usually compiles Haskell source files directly to asm and invokes as(1) and cc(1) to assemble and link them. In the configuration phase (./configure) it checks if the toolchain supports .note.GNU-stack, and if so it emits the following section saying "I don't need the stack to be executable" for all the assembly sources it produces:

   .section .note.GNU-stack,"",@progbits

This is because GHC never requires executable stack. However, there is a case where GHC needs to generate some C source and ask cc(1) to compile it. In Haskell you can declare a C function and treat it as if it were a regular Haskell function like so:

   foreign import capi "stdlib.h putenv" ::
     c_putenv :: CString -> IO CInt

This tells the compiler to find a C function putenv() in a C header <stdlib.h>, and treat it as a Haskell function of type CString -> IO CInt. When GHC sees this, it produces something equivalent to the following C source:

   #include <stdlib.h>

   int c_putenv_wrapper(char* arg0) {
       return putenv(arg0);
   }

The reason why it needs to do this, is that the imported C function (putenv(3) in this case) might not be an actual symbol but can in fact be a CPP macro. GHC then invokes cc(1) to compile it into a .o file, and uses "ld -r" to merge it with the main Haskell object file.

But since GCC doesn't emit .note.GNU-stack for this auxiliary object while GHC does for the main object, Binutils 2.39 complains about this and marks the merged object as requiring executable stack. The resulting object file will then be linked together with other objects, and again ld(1) emits a warning while producing the final executable. This happens basically every time GHC is invoked and is a major source of noise.

While I can probably patch GHC to not bother with .note.GNU-stack, the whole mess Binutils created is worth sorting out IMO.

Home | Main Index | Thread Index | Old Index