Skip to content

Commit

Permalink
Enable PROGMEM safe handlers in exceptions for 4.8
Browse files Browse the repository at this point in the history
  • Loading branch information
earlephilhower committed Jul 16, 2019
1 parent e44a7c6 commit b40a506
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 0 deletions.
48 changes: 48 additions & 0 deletions patches/gcc4.8/gcc-ctype-inline-pgmread.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
diff --git a/libstdc++-v3/config/os/newlib/ctype_inline.h b/libstdc++-v3/config/os/newlib/ctype_inline.h
index a4714f9bcce..479ceef7191 100644
--- a/libstdc++-v3/config/os/newlib/ctype_inline.h
+++ b/libstdc++-v3/config/os/newlib/ctype_inline.h
@@ -34,6 +34,26 @@
// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
// functions go in ctype.cc

+#ifndef __ctype__pgm_read_with_offset
+
+#define __ctype__pgm_read_with_offset(addr, res) \
+ asm("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \
+ "sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \
+ "l32i.n %1, %1, 0x0\n" /* Load word from aligned address */ \
+ "ssa8l %0\n" /* Prepare to shift by offset (in bits) */ \
+ "src %0, %1, %1\n" /* Shift right; now the requested byte is the first one */ \
+ :"=r"(res), "=r"(addr) \
+ :"1"(addr) \
+:);
+
+static inline uint8_t __ctype__pgm_read_byte_inlined(const void* addr) {
+ register uint32_t res;
+ __ctype__pgm_read_with_offset(addr, res);
+ return (uint8_t) res; /* This masks the lower byte from the returned word */
+}
+
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -41,14 +61,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
ctype<char>::
is(mask __m, char __c) const
- { return _M_table[static_cast<unsigned char>(__c)] & __m; }
+ { return __ctype__pgm_read_byte_inlined(&_M_table[static_cast<unsigned char>(__c)]) & __m; }

const char*
ctype<char>::
is(const char* __low, const char* __high, mask* __vec) const
{
while (__low < __high)
- *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
+ *__vec++ = __ctype__pgm_read_byte_inlined(&_M_table[static_cast<unsigned char>(*__low++)]);
return __high;
}

35 changes: 35 additions & 0 deletions patches/gcc4.8/gcc-enable-mforcel32-eh.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index ea390a5bbea..9268851c44a 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -851,7 +851,7 @@ endif
# libgcc_eh.a, only LIB2ADDEH matters. If we do, only LIB2ADDEHSTATIC and
# LIB2ADDEHSHARED matter. (Usually all three are identical.)

-c_flags := -fexceptions
+c_flags := -fexceptions -mforce-l32

ifeq ($(enable_shared),yes)

@@ -874,7 +874,7 @@ endif
# Build LIBUNWIND. Use -fno-exceptions so that the unwind library does
# not generate calls to __gcc_personality_v0.

-c_flags := -fno-exceptions
+c_flags := -fno-exceptions -mforce-l32

libunwind-objects += $(addsuffix $(objext),$(basename $(notdir $(LIBUNWIND))))

diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 8bf86f35af6..b6adcc7ab49 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -335,7 +335,7 @@ toolexeclibdir = $(glibcxx_toolexeclibdir)
# These bits are all figured out from configure. Look in acinclude.m4
# or configure.ac to see how they are set. See GLIBCXX_EXPORT_FLAGS.
CONFIG_CXXFLAGS = \
- $(SECTION_FLAGS) $(HWCAP_FLAGS) -frandom-seed=$@
+ $(SECTION_FLAGS) $(HWCAP_FLAGS) -frandom-seed=$@ -mforce-l32

WARN_CXXFLAGS = \
$(WARN_FLAGS) $(WERROR_FLAG) -fdiagnostics-show-location=once
124 changes: 124 additions & 0 deletions patches/gcc4.8/gcc-stdcsupp-safe.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
diff --git a/libstdc++-v3/libsupc++/tinfo.cc b/libstdc++-v3/libsupc++/tinfo.cc
index f10e270b6ae..3fcac0469a4 100644
--- a/libstdc++-v3/libsupc++/tinfo.cc
+++ b/libstdc++-v3/libsupc++/tinfo.cc
@@ -26,6 +26,22 @@
#include <cstddef>
#include "tinfo.h"

+ // Write own version so it's compiled with mforce-l32 and won't crash
+static int strcmp_safe(const char *p1, const char *p2) {
+ const unsigned char *s1 = (const unsigned char *) p1;
+ const unsigned char *s2 = (const unsigned char *) p2;
+ unsigned char c1, c2;
+ do
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0')
+ return c1 - c2;
+ }
+ while (c1 == c2);
+ return c1 - c2;
+ }
+
std::type_info::
~type_info ()
{ }
@@ -43,7 +59,7 @@ operator== (const std::type_info& arg) const _GLIBCXX_NOEXCEPT
take care to look at __name rather than name() when looking for
the "pointer" prefix. */
return (&arg == this)
- || (__name[0] != '*' && (__builtin_strcmp (name (), arg.name ()) == 0));
+ || (__name[0] != '*' && (strcmp_safe (name (), arg.name ()) == 0));
#endif
}

diff --git a/libstdc++-v3/libsupc++/tinfo2.cc b/libstdc++-v3/libsupc++/tinfo2.cc
index 533824ca032..545df820fb6 100644
--- a/libstdc++-v3/libsupc++/tinfo2.cc
+++ b/libstdc++-v3/libsupc++/tinfo2.cc
@@ -29,6 +29,21 @@
using std::type_info;

#if !__GXX_TYPEINFO_EQUALITY_INLINE
+ // Write own version so it's compiled with mforce-l32 and won't crash
+static int strcmp_safe(const char *p1, const char *p2) {
+ const unsigned char *s1 = (const unsigned char *) p1;
+ const unsigned char *s2 = (const unsigned char *) p2;
+ unsigned char c1, c2;
+ do
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0')
+ return c1 - c2;
+ }
+ while (c1 == c2);
+ return c1 - c2;
+ }

bool
type_info::before (const type_info &arg) const _GLIBCXX_NOEXCEPT
@@ -37,7 +52,7 @@ type_info::before (const type_info &arg) const _GLIBCXX_NOEXCEPT
return name () < arg.name ();
#else
return (name ()[0] == '*') ? name () < arg.name ()
- : __builtin_strcmp (name (), arg.name ()) < 0;
+ : strcmp_safe (name (), arg.name ()) < 0;
#endif
}

diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo
index 0ed47fcdfb6..345c95b3270 100644
--- a/libstdc++-v3/libsupc++/typeinfo
+++ b/libstdc++-v3/libsupc++/typeinfo
@@ -50,7 +50,7 @@ namespace __cxxabiv1
// must be compared), and whether comparison is to be implemented inline or
// not. We used to do inline pointer comparison by default if weak symbols
// are available, but even with weak symbols sometimes names are not merged
-// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by
+// when objects are loaded with RTLD_LOCAL, so now we always use p2 by
// default. For ABI compatibility, we do the strcmp inline if weak symbols
// are available, and out-of-line if not. Out-of-line pointer comparison
// is used where the object files are to be portable to multiple systems,
@@ -115,13 +115,13 @@ namespace std
bool before(const type_info& __arg) const _GLIBCXX_NOEXCEPT
{ return (__name[0] == '*' && __arg.__name[0] == '*')
? __name < __arg.__name
- : __builtin_strcmp (__name, __arg.__name) < 0; }
+ : strcmp_safe (__name, __arg.__name) < 0; }

bool operator==(const type_info& __arg) const _GLIBCXX_NOEXCEPT
{
return ((__name == __arg.__name)
|| (__name[0] != '*' &&
- __builtin_strcmp (__name, __arg.__name) == 0));
+ strcmp_safe (__name, __arg.__name) == 0));
}
#else
// On some targets we can rely on type_info's NTBS being unique,
@@ -176,6 +176,23 @@ namespace std
/// Assigning type_info is not supported.
type_info& operator=(const type_info&);
type_info(const type_info&);
+
+ // Write own version so it's compiled with mforce-l32 and won't crash
+ static int strcmp_safe(const char *p1, const char *p2) {
+ const unsigned char *s1 = (const unsigned char *) p1;
+ const unsigned char *s2 = (const unsigned char *) p2;
+ unsigned char c1, c2;
+ do
+ {
+ c1 = (unsigned char) *s1++;
+ c2 = (unsigned char) *s2++;
+ if (c1 == '\0')
+ return c1 - c2;
+ }
+ while (c1 == c2);
+ return c1 - c2;
+ }
+
};

/**
56 changes: 56 additions & 0 deletions patches/gcc4.8/gcc-unwind-safe.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
index 24b4ecee68c..56328c47e1e 100644
--- a/libgcc/unwind-dw2-fde.c
+++ b/libgcc/unwind-dw2-fde.c
@@ -285,6 +285,15 @@ base_from_object (unsigned char encoding, struct object *ob)
}
}

+
+// Write own version so it's compiled with mforce-l32 and won't crash
+static size_t strlen_safe(const char *s) {
+ size_t len = 0;
+ while(*s++) len++;
+ return len;
+}
+
+
/* Return the FDE pointer encoding from the CIE. */
/* ??? This is a subset of extract_cie_info from unwind-dw2.c. */

@@ -297,7 +306,7 @@ get_cie_encoding (const struct dwarf_cie *cie)
_sleb128_t stmp;

aug = cie->augmentation;
- p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string. */
+ p = aug + strlen_safe ((const char *)aug) + 1; /* Skip the augmentation string. */
if (__builtin_expect (cie->version >= 4, 0))
{
if (p[0] != sizeof (void *) || p[1] != 0)
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index e6130af2fb5..f2bd0ba454e 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -410,6 +410,13 @@ _Unwind_GetTextRelBase (struct _Unwind_Context *context)

#include "md-unwind-support.h"

+// Write own version so it's compiled with mforce-l32 and won't crash
+static size_t strlen_safe(const char *s) {
+ size_t len = 0;
+ while(*s++) len++;
+ return len;
+}
+
/* Extract any interesting information from the CIE for the translation
unit F belongs to. Return a pointer to the byte after the augmentation,
or NULL if we encountered an undecipherable augmentation. */
@@ -419,7 +426,7 @@ extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
_Unwind_FrameState *fs)
{
const unsigned char *aug = cie->augmentation;
- const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+ const unsigned char *p = aug + strlen_safe ((const char *)aug) + 1;
const unsigned char *ret = NULL;
_uleb128_t utmp;
_sleb128_t stmp;

0 comments on commit b40a506

Please sign in to comment.