diff mbox

xtensa: ldso: coalesce dl_mprotect address ranges

Message ID 1420808135-4282-1-git-send-email-jcmvbkbc@gmail.com
State Superseded
Headers show

Commit Message

Max Filippov Jan. 9, 2015, 12:55 p.m. UTC
This noticeably lowers the number of mprotect calls at program startup,
e.g. for busybox: 7 calls vs 1835 calls.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 ldso/ldso/xtensa/dl-startup.h | 18 +++++++++++++++++-
 ldso/ldso/xtensa/dl-sysdep.h  | 22 +++++++++++++++++++++-
 2 files changed, 38 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h
index b135a4c..c60c9cf 100644
--- a/ldso/ldso/xtensa/dl-startup.h
+++ b/ldso/ldso/xtensa/dl-startup.h
@@ -83,6 +83,7 @@  do { \
 	unsigned long l_addr = tpnt->loadaddr; \
 	Elf32_Word relative_count; \
 	unsigned long rel_addr; \
+	Elf32_Addr prev_got_start = 0, prev_got_end = 0; \
 	int x; \
 \
 	got_loc = (xtensa_got_location *) \
@@ -93,7 +94,22 @@  do { \
 		got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
 		got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
 				   & ~(PAGE_SIZE - 1)); \
-		_dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \
+		if (got_start >= prev_got_start && got_start <= prev_got_end) { \
+			if (got_end > prev_got_end) \
+				prev_got_end = got_end; \
+			continue; \
+		} else if (prev_got_start != prev_got_end) { \
+			_dl_mprotect ((void *)(prev_got_start + l_addr), \
+						  prev_got_end - prev_got_start, \
+						  PROT_READ | PROT_WRITE | PROT_EXEC); \
+		} \
+		prev_got_start = got_start; \
+		prev_got_end = got_end; \
+	} \
+\
+	if (prev_got_start != prev_got_end) { \
+		_dl_mprotect ((void *)(prev_got_start + l_addr), \
+					  prev_got_end - prev_got_start, \
 					  PROT_READ | PROT_WRITE | PROT_EXEC); \
 	} \
 \
diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h
index a0ed4e5..06113b5 100644
--- a/ldso/ldso/xtensa/dl-sysdep.h
+++ b/ldso/ldso/xtensa/dl-sysdep.h
@@ -36,6 +36,7 @@  typedef struct xtensa_got_location_struct {
   do {									      \
     xtensa_got_location *got_loc;					      \
     Elf32_Addr l_addr = MODULE->loadaddr;				      \
+    Elf32_Addr prev_got_start, prev_got_end;				      \
     int x;								      \
 									      \
     got_loc = (xtensa_got_location *)					      \
@@ -47,7 +48,26 @@  typedef struct xtensa_got_location_struct {
 	got_start = got_loc[x].offset & ~(PAGE_SIZE - 1);		      \
 	got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1)    \
 		   & ~(PAGE_SIZE - 1));					      \
-	_dl_mprotect ((void *)(got_start + l_addr) , got_end - got_start,     \
+	if (got_start >= prev_got_start && got_start <= prev_got_end)	      \
+	  {								      \
+	    if (got_end > prev_got_end)					      \
+		prev_got_end = got_end;					      \
+	    continue;							      \
+	  }								      \
+        else if (prev_got_start != prev_got_end)			      \
+	  {								      \
+	    _dl_mprotect ((void *)(prev_got_start + l_addr),		      \
+			  prev_got_end - prev_got_start,		      \
+			  PROT_READ | PROT_WRITE | PROT_EXEC);		      \
+          }								      \
+        prev_got_start = got_start;					      \
+        prev_got_end = got_end;						      \
+      }									      \
+									      \
+    if (prev_got_start != prev_got_end)					      \
+      {									      \
+        _dl_mprotect ((void *)(prev_got_start + l_addr),		      \
+		      prev_got_end - prev_got_start,			      \
 		      PROT_READ | PROT_WRITE | PROT_EXEC);		      \
       }									      \
 									      \