#3 enable dynamic page size support
Merged a year ago by fweimer. Opened a year ago by leifliddy.
Unknown source rawhide  into  rawhide

@@ -0,0 +1,355 @@

+ From cf6b9aadd60a85107afe5196251ca2ed198a96d0 Mon Sep 17 00:00:00 2001

+ From: Daniel Moody <daniel.moody@mongodb.com>

+ Date: Fri, 18 Feb 2022 14:24:37 -0600

+ Subject: [PATCH] Updated to determine PAGE_SIZE dynamically.

+ 

+ ---

+  include/libunwind_i.h |  9 +++++++++

+  src/aarch64/Ginit.c   | 19 ++++++++-----------

+  src/arm/Ginit.c       | 13 ++-----------

+  src/mi/init.c         | 28 ++++++++++++++++++++++++++--

+  src/riscv/Ginit.c     | 22 ++++++++--------------

+  src/s390x/Ginit.c     | 25 ++++++++++---------------

+  src/x86/Ginit.c       | 13 ++-----------

+  src/x86_64/Ginit.c    | 18 +++++-------------

+  8 files changed, 70 insertions(+), 77 deletions(-)

+ 

+ diff --git a/include/libunwind_i.h b/include/libunwind_i.h

+ index 6c7dda9a8..bcf229566 100644

+ --- a/include/libunwind_i.h

+ +++ b/include/libunwind_i.h

+ @@ -55,6 +55,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */

+  #include <string.h>

+  #include <unistd.h>

+  #include <sys/mman.h>

+ +#include <errno.h>

+ +#include <stdio.h>

+  

+  #if defined(HAVE_ELF_H)

+  # include <elf.h>

+ @@ -288,6 +290,13 @@ print_error (const char *string)

+    return write (2, string, strlen (string));

+  }

+  

+ +HIDDEN extern long unw_page_size;

+ +

+ +static inline unw_word_t uwn_page_start(unw_word_t addr)

+ +{

+ +  return addr & ~(unw_page_size - 1);

+ +}

+ +

+  #define mi_init         UNWI_ARCH_OBJ(mi_init)

+  

+  extern void mi_init (void);     /* machine-independent initializations */

+ diff --git a/src/aarch64/Ginit.c b/src/aarch64/Ginit.c

+ index 2b08feb36..fe6e511df 100644

+ --- a/src/aarch64/Ginit.c

+ +++ b/src/aarch64/Ginit.c

+ @@ -84,8 +84,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,

+    return 0;

+  }

+  

+ -#define PAGE_SIZE 4096

+ -#define PAGE_START(a)   ((a) & ~(PAGE_SIZE-1))

+  

+  static int mem_validate_pipe[2] = {-1, -1};

+  

+ @@ -197,11 +195,14 @@ tdep_init_mem_validate (void)

+  

+  #ifdef HAVE_MINCORE

+    unsigned char present = 1;

+ -  unw_word_t addr = PAGE_START((unw_word_t)&present);

+ +  size_t len = unw_page_size;

+ +  unw_word_t addr = uwn_page_start((unw_word_t)&present);

+    unsigned char mvec[1];

+    int ret;

+ -  while ((ret = mincore ((void*)addr, PAGE_SIZE, (unsigned char *)mvec)) == -1 &&

+ -         errno == EAGAIN) {}

+ +  while ((ret = mincore((void *)addr, len, (unsigned char *)mvec)) == -1 &&

+ +         errno == EAGAIN)

+ +  {

+ +  }

+    if (ret == 0)

+      {

+        Debug(1, "using mincore to validate memory\n");

+ @@ -295,12 +296,8 @@ validate_mem (unw_word_t addr)

+  {

+    size_t len;

+  

+ -  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))

+ -    len = PAGE_SIZE;

+ -  else

+ -    len = PAGE_SIZE * 2;

+ -

+ -  addr = PAGE_START(addr);

+ +  len = unw_page_size;

+ +  addr = uwn_page_start(addr);

+  

+    if (addr == 0)

+      return -1;

+ diff --git a/src/arm/Ginit.c b/src/arm/Ginit.c

+ index 0bac0d72d..bce52dc34 100644

+ --- a/src/arm/Ginit.c

+ +++ b/src/arm/Ginit.c

+ @@ -71,9 +71,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,

+    return 0;

+  }

+  

+ -#define PAGE_SIZE 4096

+ -#define PAGE_START(a)	((a) & ~(PAGE_SIZE-1))

+ -

+  /* Cache of already validated addresses */

+  #define NLGA 4

+  static unw_word_t last_good_addr[NLGA];

+ @@ -83,14 +80,8 @@ static int

+  validate_mem (unw_word_t addr)

+  {

+    int i, victim;

+ -  size_t len;

+ -

+ -  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))

+ -    len = PAGE_SIZE;

+ -  else

+ -    len = PAGE_SIZE * 2;

+ -

+ -  addr = PAGE_START(addr);

+ +  size_t len = unw_page_size;

+ +  addr = uwn_page_start(addr);

+  

+    if (addr == 0)

+      return -1;

+ diff --git a/src/mi/init.c b/src/mi/init.c

+ index 60a48c589..aa9319981 100644

+ --- a/src/mi/init.c

+ +++ b/src/mi/init.c

+ @@ -39,6 +39,30 @@ static const char rcsid[] UNUSED =

+  long unwi_debug_level;

+  

+  #endif /* UNW_DEBUG */

+ +long unw_page_size;

+ +static void

+ +unw_init_page_size ()

+ +{

+ +  errno = 0;

+ +  long result = sysconf (_SC_PAGESIZE);

+ +  if (result == -1)

+ +    {

+ +      if (errno != 0)

+ +        {

+ +          print_error ("Failed to get _SC_PAGESIZE: ");

+ +          print_error (strerror(errno));

+ +          print_error ("\n");

+ +        }

+ +        else

+ +          print_error ("Failed to get _SC_PAGESIZE, errno was not set.\n");

+ +

+ +      unw_page_size = 4096;

+ +    }

+ +  else

+ +    {

+ +      unw_page_size = result;

+ +    }

+ +}

+  

+  HIDDEN void

+  mi_init (void)

+ @@ -55,6 +79,6 @@ mi_init (void)

+        setbuf (stderr, NULL);

+      }

+  #endif

+ -

+ -  assert (sizeof (struct cursor) <= sizeof (unw_cursor_t));

+ +  unw_init_page_size();

+ +  assert(sizeof(struct cursor) <= sizeof(unw_cursor_t));

+  }

+ diff --git a/src/riscv/Ginit.c b/src/riscv/Ginit.c

+ index 907f72962..4faeecbfd 100644

+ --- a/src/riscv/Ginit.c

+ +++ b/src/riscv/Ginit.c

+ @@ -97,9 +97,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,

+  

+  // Memory validation routines are from aarch64

+  

+ -#define PAGE_SIZE 4096

+ -#define PAGE_START(a)   ((a) & ~(PAGE_SIZE-1))

+ -

+  static int mem_validate_pipe[2] = {-1, -1};

+  

+  #ifdef HAVE_PIPE2

+ @@ -210,11 +207,14 @@ tdep_init_mem_validate (void)

+  

+  #ifdef HAVE_MINCORE

+    unsigned char present = 1;

+ -  unw_word_t addr = PAGE_START((unw_word_t)&present);

+ +  size_t len = unw_page_size;

+ +  unw_word_t addr = uwn_page_start((unw_word_t)&present);

+    unsigned char mvec[1];

+    int ret;

+ -  while ((ret = mincore ((void*)addr, PAGE_SIZE, (unsigned char *)mvec)) == -1 &&

+ -         errno == EAGAIN) {}

+ +  while ((ret = mincore((void *)addr, len, (unsigned char *)mvec)) == -1 &&

+ +         errno == EAGAIN)

+ +  {

+ +  }

+    if (ret == 0)

+      {

+        Debug(1, "using mincore to validate memory\n");

+ @@ -306,14 +306,8 @@ cache_valid_mem(unw_word_t addr)

+  static int

+  validate_mem (unw_word_t addr)

+  {

+ -  size_t len;

+ -

+ -  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))

+ -    len = PAGE_SIZE;

+ -  else

+ -    len = PAGE_SIZE * 2;

+ -

+ -  addr = PAGE_START(addr);

+ +  size_t len = unw_page_size;

+ +  addr = uwn_page_start(addr);

+  

+    if (addr == 0)

+      return -1;

+ diff --git a/src/s390x/Ginit.c b/src/s390x/Ginit.c

+ index db01743c0..2bce2f4b6 100644

+ --- a/src/s390x/Ginit.c

+ +++ b/src/s390x/Ginit.c

+ @@ -27,6 +27,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION

+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION

+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */

+  

+ +#include "libunwind_i.h"

+  #ifdef HAVE_CONFIG_H

+  #include <config.h>

+  #endif

+ @@ -93,9 +94,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,

+    return 0;

+  }

+  

+ -#define PAGE_SIZE 4096

+ -#define PAGE_START(a)   ((a) & ~(PAGE_SIZE-1))

+ -

+  static int mem_validate_pipe[2] = {-1, -1};

+  

+  static inline void

+ @@ -163,7 +161,7 @@ static int mincore_validate (void *addr, size_t len)

+        return -1;

+      }

+  

+ -  for (i = 0; i < (len + PAGE_SIZE - 1) / PAGE_SIZE; i++)

+ +    for (i = 0; i < (len + unw_page_size - 1) / unw_page_size; i++)

+      {

+        if (!(mvec[i] & 1)) return -1;

+      }

+ @@ -183,11 +181,14 @@ tdep_init_mem_validate (void)

+  

+  #ifdef HAVE_MINCORE

+    unsigned char present = 1;

+ -  unw_word_t addr = PAGE_START((unw_word_t)&present);

+ +  size_t len = unw_page_size;

+ +  unw_word_t addr = uwn_page_start((unw_word_t)&present);

+    unsigned char mvec[1];

+    int ret;

+ -  while ((ret = mincore ((void*)addr, PAGE_SIZE, mvec)) == -1 &&

+ -         errno == EAGAIN) {}

+ +  while ((ret = mincore((void *)addr, len, mvec)) == -1 &&

+ +         errno == EAGAIN)

+ +  {

+ +  }

+    if (ret == 0 && (mvec[0] & 1))

+      {

+        Debug(1, "using mincore to validate memory\n");

+ @@ -210,14 +211,8 @@ static int

+  validate_mem (unw_word_t addr)

+  {

+    int i, victim;

+ -  size_t len;

+ -

+ -  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))

+ -    len = PAGE_SIZE;

+ -  else

+ -    len = PAGE_SIZE * 2;

+ -

+ -  addr = PAGE_START(addr);

+ +  size_t len = unw_page_size;

+ +  addr = uwn_page_start(addr);

+  

+    if (addr == 0)

+      return -1;

+ diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c

+ index 3cec74a21..4261fb523 100644

+ --- a/src/x86/Ginit.c

+ +++ b/src/x86/Ginit.c

+ @@ -74,9 +74,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,

+    return 0;

+  }

+  

+ -#define PAGE_SIZE 4096

+ -#define PAGE_START(a)   ((a) & ~(PAGE_SIZE-1))

+ -

+  /* Cache of already validated addresses */

+  #define NLGA 4

+  static unw_word_t last_good_addr[NLGA];

+ @@ -89,14 +86,8 @@ validate_mem (unw_word_t addr)

+  #ifdef HAVE_MINCORE

+    unsigned char mvec[2]; /* Unaligned access may cross page boundary */

+  #endif

+ -  size_t len;

+ -

+ -  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))

+ -    len = PAGE_SIZE;

+ -  else

+ -    len = PAGE_SIZE * 2;

+ -

+ -  addr = PAGE_START(addr);

+ +  size_t len = unw_page_size;

+ +  addr = uwn_page_start(addr);

+  

+    if (addr == 0)

+      return -1;

+ diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c

+ index 0b121bc91..e75f92a5f 100644

+ --- a/src/x86_64/Ginit.c

+ +++ b/src/x86_64/Ginit.c

+ @@ -73,9 +73,6 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,

+    return 0;

+  }

+  

+ -#define PAGE_SIZE 4096

+ -#define PAGE_START(a)   ((a) & ~(PAGE_SIZE-1))

+ -

+  static int mem_validate_pipe[2] = {-1, -1};

+  

+  #ifdef HAVE_PIPE2

+ @@ -191,10 +188,11 @@ tdep_init_mem_validate (void)

+  

+  #ifdef HAVE_MINCORE

+    unsigned char present = 1;

+ -  unw_word_t addr = PAGE_START((unw_word_t)&present);

+ +  size_t len = unw_page_size;

+ +  unw_word_t addr = uwn_page_start((unw_word_t)&present);

+    unsigned char mvec[1];

+    int ret;

+ -  while ((ret = mincore ((void*)addr, PAGE_SIZE, (unsigned char *)mvec)) == -1 &&

+ +  while ((ret = mincore ((void*)addr, len, (unsigned char *)mvec)) == -1 &&

+           errno == EAGAIN) {}

+    if (ret == 0)

+      {

+ @@ -287,14 +285,8 @@ cache_valid_mem(unw_word_t addr)

+  static int

+  validate_mem (unw_word_t addr)

+  {

+ -  size_t len;

+ -

+ -  if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr))

+ -    len = PAGE_SIZE;

+ -  else

+ -    len = PAGE_SIZE * 2;

+ -

+ -  addr = PAGE_START(addr);

+ +  size_t len = unw_page_size;

+ +  addr = uwn_page_start(addr);

+  

+    if (addr == 0)

+      return -1;

file modified
+4
@@ -13,6 +13,7 @@

  Patch1: libunwind-arm-default-to-exidx.patch

  # Make libunwind.h multilib friendly

  Patch2: libunwind-1.3.1-multilib-fix.patch

+ Patch3: libunwind-1.6.2-dynamic-page-size.patch

  

  ExclusiveArch: %{arm} aarch64 hppa ia64 mips ppc %{power64} s390x %{ix86} x86_64

  
@@ -89,6 +90,9 @@

  %{_includedir}/libunwind*.h

  

  %changelog

+ * Sun Aug 28 2022 Leif Liddy <leif.liddy@gmail.com> - 1.6.2-4

+ - enable dynamic page size support (bz2118019)

+ 

  * Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.6.2-3

  - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild

  

enable dynamic page size support by applying this patch here:
https://github.com/libunwind/libunwind/commit/e85b65cec757ef589f28957d0c6c21c498a03bdf

Resolves issue with processors that don't support 4K page sizes
https://bugzilla.redhat.com/show_bug.cgi?id=2118019

Looks reasonable, I'm going to merge this. Thanks.

Pull-Request has been merged by fweimer

a year ago