[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gcc-patches
Subject:    Re: [RFC] [PATCH] Implement -ffortify for C/C++
From:       Jakub Jelinek <jakub () redhat ! com>
Date:       2007-03-01 8:56:25
Message-ID: 20070301085625.GP355 () devserv ! devel ! redhat ! com
[Download RAW message or body]

On Wed, Feb 21, 2007 at 07:22:25PM +0100, Dirk Mueller wrote:
> On Wednesday, 21. February 2007 18:25, Ulrich Drepper wrote:#
> 
> > There is an easy enough method to handle C++ in the runtime headers
> > without resorting to macros.  It requires one generic compiler
> > change/extension which then can be used for all wrapper functions and
> > other functionality as well.  Jakub might illustrate this soon, I hope.
> 
> Jakub, what are you plans? adding an __attribute__ to be able to mark 
> additional functions?

My preference would be to add a new attribute which would provide
GNU89 extern inline semantics in C++, i.e. if a function is successfully
inlined, it will behave like a normal C++ inline, but if it can't be
inlined, then no out of line copy is created from it.  Then glibc
can just define __extern_inline to this attribute in C++ and just use the
__extern_inline _FORTIFY_SOURCE and other wrappers.

In C++ we can't use function-like macros for this, as the same thing can
be defined a different way in a different namespace.  And plain C++ inline
semantics is unusable here.
Consider two examples (one where GCC has a builtin, another where it
doesn't):
namespace std
{
  extern "C" inline void *memcpy (void *__d, const void *__s, size_t __n)
  {
    return __builtin___memcpy_chk (__d, __s, __n, __bos0 (__d));
  }
};
namespace __glibc
{
  extern "C" __typeof(::getcwd) __getcwd_alias __asm ("getcwd");
  extern "C" char *__getcwd_chk (char *, std::size_t, std::size_t);
};
extern "C" inline char *getcwd (char *__buf, std::size_t __size)
{
  if (__bos (__buf) != (size_t) -1
      && (!__builtin_constant_p (__size) || __size > __bos (__buf)))
    return ::__glibc::__getcwd_chk (__buf, __size, __bos (__buf));
  return ::__glibc::__getcwd_alias (__buf, __size);
}

If the functions are successfully inlined, everything is ok, but if
they aren't, G++ will create an out of line copy and that's highly
undesirable.  For out of line std::memcpy, __bos0 (__d) will be -1
(nothing known about the destination, obviously) and thus
__builtin___memcpy_chk will expand to memcpy call.  So we'll have
.globl memcpy
.weak memcpy
jmp memcpy
emitted.  Similarly in the getcwd case.  With the GNU89 extern
inline semantics the out of line copies wouldn't be emitted at all
(unless a non-inline definition is present) and things would work just fine.

Over the hardcoded builtins in GCC this has the advantage that not only the
standard C++ or selected POSIX functions can be fortified, but also any
other where it is desirable, be it in glibc headers or in apps can use
it themselves to protect their own interfaces.  Additionally, one can
write with sufficient care (mainly using the right namespaces, which can
be macroized, see the __BEGIN_NAMESPACE_XXX and __END_NAMESPACE_XXX macros
in glibc) the _FORTIFY_SOURCE inlines just once for both
C and C++.

	Jakub
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic