diff --git a/patches/gcc4.8/gcc-ctype-inline-pgmread.patch b/patches/gcc4.8/gcc-ctype-inline-pgmread.patch new file mode 100644 index 0000000..318a216 --- /dev/null +++ b/patches/gcc4.8/gcc-ctype-inline-pgmread.patch @@ -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:: + is(mask __m, char __c) const +- { return _M_table[static_cast(__c)] & __m; } ++ { return __ctype__pgm_read_byte_inlined(&_M_table[static_cast(__c)]) & __m; } + + const char* + ctype:: + is(const char* __low, const char* __high, mask* __vec) const + { + while (__low < __high) +- *__vec++ = _M_table[static_cast(*__low++)]; ++ *__vec++ = __ctype__pgm_read_byte_inlined(&_M_table[static_cast(*__low++)]); + return __high; + } + diff --git a/patches/gcc4.8/gcc-enable-mforcel32-eh.patch b/patches/gcc4.8/gcc-enable-mforcel32-eh.patch new file mode 100644 index 0000000..4800003 --- /dev/null +++ b/patches/gcc4.8/gcc-enable-mforcel32-eh.patch @@ -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 diff --git a/patches/gcc4.8/gcc-stdcsupp-safe.patch b/patches/gcc4.8/gcc-stdcsupp-safe.patch new file mode 100644 index 0000000..d05a33e --- /dev/null +++ b/patches/gcc4.8/gcc-stdcsupp-safe.patch @@ -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 + #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; ++ } ++ + }; + + /** diff --git a/patches/gcc4.8/gcc-unwind-safe.patch b/patches/gcc4.8/gcc-unwind-safe.patch new file mode 100644 index 0000000..e2f0c8a --- /dev/null +++ b/patches/gcc4.8/gcc-unwind-safe.patch @@ -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;