diff options
| author | Max Filippov <jcmvbkbc@gmail.com> | 2015-01-10 04:42:42 +0300 | 
|---|---|---|
| committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2015-01-23 21:16:12 +0100 | 
| commit | 59f06d06f05abf20092617fcfa34438c77d92bdd (patch) | |
| tree | 6e189b6098366a78325bcf9f2b9bd38a09f585bf | |
| parent | e55f589191162eb40f44696c77e569049313d381 (diff) | |
xtensa: ldso: coalesce dl_mprotect address ranges
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>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
| -rw-r--r-- | ldso/ldso/xtensa/dl-startup.h | 20 | ||||
| -rw-r--r-- | ldso/ldso/xtensa/dl-sysdep.h | 24 | 
2 files changed, 42 insertions, 2 deletions
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h index b135a4cb8..0c28d5e44 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,24 @@ 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_end >= prev_got_start && got_start <= prev_got_end) { \ +			if (got_end > prev_got_end) \ +				prev_got_end = got_end; \ +			if (got_start < prev_got_start) \ +				prev_got_start = got_start; \ +			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 a0ed4e5f2..5f8bcb0a8 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 = 0, prev_got_end = 0;			      \      int x;								      \  									      \      got_loc = (xtensa_got_location *)					      \ @@ -47,7 +48,28 @@ 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_end >= prev_got_start && got_start <= prev_got_end)	      \ +	  {								      \ +	    if (got_end > prev_got_end)					      \ +		prev_got_end = got_end;					      \ +	    if (got_start < prev_got_start)				      \ +		prev_got_start = got_start;				      \ +	    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);		      \        }									      \  									      \  | 
