/* Name of host specific core header file to include in elf.c. */
#undef CORE_HEADER
+/* Define to enable annobin runtime checks for static linker (warnings only)
+ */
+#undef ENABLE_ANNOBIN_VERIFICATION
+
+/* Define to enable annobin runtime strict checks (error mode) */
+#undef ENABLE_ANNOBIN_VERIFICATION_STRICT
+
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#undef ENABLE_NLS
with_mmap
enable_secureplt
enable_leading_mingw64_underscores
+enable_annobin_verification
with_separate_debug_dir
with_pkgversion
with_bugurl
--enable-secureplt Default to creating read-only plt entries
--enable-leading-mingw64-underscores
Enable leading underscores on 64 bit mingw targets
+ --enable-annobin-verification[=warn|strict]
+ enable runtime checks with dynamic notes generated
+ by annobin plugin
--enable-werror treat compile warnings as errors
--enable-build-warnings enable build-time compiler warnings
--enable-maintainer-mode enable make rules and dependencies not useful
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11430 "configure"
+#line 11434 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11536 "configure"
+#line 11540 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
fi
+# Check whether --enable-annobin_verification was given.
+if test "${enable_annobin_verification+set}" = set; then :
+ enableval=$enable_annobin_verification; case "${enableval}" in
+ yes | warn | "" ) annobin_verification=warn ;;
+ strict ) annobin_verification=strict ;;
+ no) annobin_verification=no ;;
+ *) annobin_verification=no ;;
+ esac
+else
+ annobin_verification=no
+fi
+
+if test "$annobin_verification" = "yes" ||
+ test "$annobin_verification" = "warn" ||
+ test "$annobin_verification" = "strict"; then
+
+$as_echo "#define ENABLE_ANNOBIN_VERIFICATION 1" >>confdefs.h
+
+ if test "$annobin_verification" = "strict"; then
+
+$as_echo "#define ENABLE_ANNOBIN_VERIFICATION_STRICT 1" >>confdefs.h
+
+ fi
+fi
+
DEBUGDIR=${libdir}/debug
# Check whether --with-separate-debug-dir was given.
[AC_DEFINE(USE_MINGW64_LEADING_UNDERSCORES, 1,
[Define if we should use leading underscore on 64 bit mingw targets])])
+AC_ARG_ENABLE(annobin_verification,
+[AS_HELP_STRING([[--enable-annobin-verification[=warn|strict]]],
+[enable runtime checks with dynamic notes generated by annobin plugin])],
+[case "${enableval}" in
+ yes | warn | "" ) annobin_verification=warn ;;
+ strict ) annobin_verification=strict ;;
+ no) annobin_verification=no ;;
+ *) annobin_verification=no ;;
+ esac],
+[annobin_verification=no])
+if test "$annobin_verification" = "yes" ||
+ test "$annobin_verification" = "warn" ||
+ test "$annobin_verification" = "strict"; then
+ AC_DEFINE(ENABLE_ANNOBIN_VERIFICATION, 1,
+ [Define to enable annobin runtime checks for static linker (warnings only)])
+ if test "$annobin_verification" = "strict"; then
+ AC_DEFINE(ENABLE_ANNOBIN_VERIFICATION_STRICT, 1,
+ [Define to enable annobin runtime strict checks (error mode)])
+ fi
+fi
+
DEBUGDIR=${libdir}/debug
AC_ARG_WITH(separate-debug-dir,
AS_HELP_STRING([--with-separate-debug-dir=DIR],
/* Add a new one if elf_property_kind is updated. */
} u;
enum elf_property_kind pr_kind;
+ const char *filename;
} elf_property;
typedef struct elf_property_list
memset (p, 0, sizeof (*p));
p->property.pr_type = type;
p->property.pr_datasz = datasz;
+ p->property.filename = abfd->filename;
p->next = *lastp;
*lastp = p;
return &p->property;
prop->pr_kind = property_number;
goto next;
+ case GNU_PROPERTY_COMPILER_FLAGS:
+ /* Note that annobin uses 4-byte alignment even on 64-bit targets. */
+ if (!((datasz == 4) || (datasz == 8)))
+ {
+ _bfd_error_handler
+ (_("warning: %B: corrupt compiler flags: 0x%x\n"),
+ abfd, datasz);
+ /* Clear all properties. */
+ elf_properties (abfd) = NULL;
+ return FALSE;
+ }
+ prop = _bfd_elf_get_property (abfd, type, datasz);
+ if (datasz == 8)
+ prop->u.number = bfd_h_get_64 (abfd, ptr);
+ else
+ prop->u.number = bfd_h_get_32 (abfd, ptr);
+
+ prop->pr_kind = property_number;
+ goto next;
+
default:
break;
}
return TRUE;
}
+/* If validation bits are set - compare bit flags for equality. */
+inline static bfd_boolean
+elf_gnu_property_validate_flag (bfd_vma anum,
+ bfd_vma bnum,
+ bfd_vma validation_bit_flag,
+ bfd_vma validation_bit)
+{
+ if ((anum & validation_bit_flag) && (bnum & validation_bit_flag)
+ && ((anum & validation_bit) != (bnum & validation_bit)))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bfd_boolean
+elf_validate_compiler_flags_properties (elf_property *aprop,
+ elf_property *bprop)
+{
+ bfd_boolean is_flag_set;
+
+ /* Sanity check to verify correct usage. */
+ BFD_ASSERT(aprop);
+ BFD_ASSERT(bprop);
+
+ if (aprop->pr_type != bprop->pr_type)
+ return TRUE;
+
+ BFD_ASSERT(aprop->pr_type == GNU_PROPERTY_COMPILER_FLAGS);
+
+ /* Return TRUE if compiler flags are identical (likely?). */
+ if (aprop->u.number == bprop->u.number)
+ return TRUE;
+
+ if (!elf_gnu_property_validate_flag(aprop->u.number,
+ bprop->u.number,
+ GNU_PROPERTY_SANITIZE_VALIDATION,
+ GNU_PROPERTY_SANITIZE_ADDRESS))
+ {
+ is_flag_set = bprop->u.number & GNU_PROPERTY_SANITIZE_ADDRESS;
+ _bfd_error_handler
+ (_("%s: ERROR: Validation failed, linking %s object with previous %s"),
+ bprop->filename, is_flag_set ? "sanitized" : "unsanitized",
+ !is_flag_set ? "sanitized" : "unsanitized");
+ return FALSE;
+ }
+
+ if (!elf_gnu_property_validate_flag(aprop->u.number,
+ bprop->u.number,
+ GNU_PROPERTY_USECXX_VALIDATION,
+ GNU_PROPERTY_USECXX11_ABI))
+ {
+ is_flag_set = bprop->u.number & GNU_PROPERTY_USECXX11_ABI;
+ _bfd_error_handler
+ (_("ERROR: Validation failed, linking %s ABI object with %s ABI"),
+ bprop->filename, is_flag_set ? "pre-cxx11" : "cxx11",
+ !is_flag_set ? "pre-cxx11" : "cxx11");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* Merge bprop into aprop according compiler-flags properties, return TRUE if */
+/* aprop is updated. */
+static bfd_boolean
+elf_merge_gnu_properties_compiler_flags (elf_property *aprop,
+ elf_property *bprop)
+{
+ bfd_boolean is_updated = FALSE;
+ /* Likely that objects have the same properties. */
+ if (aprop->u.number == bprop->u.number) {
+ return FALSE;
+ }
+
+ /* Validation bit + no-validation bit = validation bit. */
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_VALIDATION)
+ {
+ aprop->u.number |= GNU_PROPERTY_SANITIZE_VALIDATION;
+ is_updated = TRUE;
+ }
+ /* Sanitized object + unsanitized results = sanitized final object. */
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_ADDRESS)
+ {
+ aprop->u.number |= GNU_PROPERTY_SANITIZE_ADDRESS;
+ is_updated = TRUE;
+ }
+
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX_VALIDATION)
+ {
+ aprop->u.number |= GNU_PROPERTY_USECXX_VALIDATION;
+ is_updated = TRUE;
+ }
+
+ if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX11_ABI)
+ {
+ aprop->u.number |= GNU_PROPERTY_USECXX11_ABI;
+ is_updated = TRUE;
+ }
+
+ return is_updated;
+}
+
/* Merge GNU property BPROP with APROP. If APROP isn't NULL, return TRUE
if APROP is updated. Otherwise, return TRUE if BPROP should be merged
with ABFD. */
/* Return TRUE if APROP is NULL to indicate that BPROP should
be added to ABFD. */
return aprop == NULL;
+ /* FALLTHROUGH */
+
+ case GNU_PROPERTY_COMPILER_FLAGS:
+ {
+ bfd_boolean is_updated;
+ if (aprop != NULL && bprop != NULL)
+ {
+#ifdef ENABLE_ANNOBIN_VERIFICATION
+ if (!elf_validate_compiler_flags_properties (aprop, bprop))
+ {
+ _bfd_error_handler(_("ERROR: Linking failed due to incompatible "
+ "compilation flags used to generate objects\n"));
+ /* Strict mode, abort. */
+#ifdef ENABLE_ANNOBIN_VERIFICATION_STRICT
+ _exit (EXIT_FAILURE);
+#endif
+ }
+#endif
+ is_updated = elf_merge_gnu_properties_compiler_flags (aprop, bprop);
+ }
+ else
+ {
+ is_updated = FALSE;
+ /* aprop or bprop is NULL, warn for missing GNU_PROPERTY_COMPILER_FLAGS.
+
+ This is too noisy since glibc's crt{i,n}.o are compiled with
+ predefined flags (without annobin support), so we'll have at
+ least 2x of the following warning for every linking. May be
+ enabled after we verified crt* compilation with plugins. */
+ /* if (bprop == NULL)
+ _bfd_error_handler
+ (_("WARNING: not found (generated by annobin gcc plugin), "
+ "runtime verification may be incomplete"),
+ NOTE_GNU_PROPERTY_SECTION_NAME); */
+ }
+ return is_updated;
+ }
+ /* FALLTHROUGH */
default:
/* Never should happen. */
sec = bfd_get_section_by_name (first_pbfd,
NOTE_GNU_PROPERTY_SECTION_NAME);
+ if (!sec)
+ return;
+
/* Update stack size in .note.gnu.property with -z stack-size=N
if N > 0. */
if (info->stacksize > 0)
}
static void
+decode_compiler_flags_notes (unsigned long bitmask)
+{
+ printf("%#lx [", bitmask);
+
+ printf("%c%ccxx11, ", bitmask & GNU_PROPERTY_USECXX_VALIDATION ? '=' : '~',
+ bitmask & GNU_PROPERTY_USECXX11_ABI ? '+' : '!');
+
+ printf("%c%casan", bitmask & GNU_PROPERTY_SANITIZE_VALIDATION ? '=' : '~',
+ bitmask & GNU_PROPERTY_SANITIZE_ADDRESS ? '+' : '!');
+
+ printf("]");
+}
+
+static void
print_gnu_property_note (Elf_Internal_Note * pnote)
{
unsigned char * ptr = (unsigned char *) pnote->descdata;
printf (_("<corrupt length: %#x> "), datasz);
goto next;
+ case GNU_PROPERTY_COMPILER_FLAGS:
+ printf ("compilations flags: ");
+ if ((datasz != 4) && (datasz != 8))
+ printf (_("<corrupt length: %#x> "), datasz);
+ else
+ {
+ unsigned long bitmask_flags;
+ bitmask_flags = (unsigned long) byte_get (ptr, size);
+ decode_compiler_flags_notes (bitmask_flags);
+ }
+ goto next;
+
default:
break;
}
/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
#define GNU_PROPERTY_STACK_SIZE 1
#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
+#define GNU_PROPERTY_COMPILER_FLAGS 32
+
+/* Bit masks for compiler flags: */
+/* Pre/post cxx11 ABI. */
+#define GNU_PROPERTY_USECXX_VALIDATION (1U << 0)
+#define GNU_PROPERTY_USECXX11_ABI (1U << 1)
+/* Sanitizer flags. */
+#define GNU_PROPERTY_SANITIZE_VALIDATION (1U << 2)
+#define GNU_PROPERTY_SANITIZE_ADDRESS (1U << 3)
+#define GNU_PROPERTY_SANITIZE_UNDEFINED (1U << 4)
+#define GNU_PROPERTY_SANITIZE_THREAD (1U << 5)
/* Processor-specific semantics, lo */
#define GNU_PROPERTY_LOPROC 0xc0000000
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \
--with-pic \
--build=%{host_arch} --target=%{target_arch} \
--host=%{host_arch} \
+ %{?annobin_verification: --enable-annobin-verification=warn } \
+ %{?annobin_verification_strict: --enable-annobin-verification=strict } \
%{?cross: \
--enable-targets=%{target_arch} \
--enable-64-bit-bfd \