mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			76 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Determine if address is inside object load segments.
 | |
|    Copyright (C) 1996-2017 Free Software Foundation, Inc.
 | |
|    This file is part of the GNU C Library.
 | |
| 
 | |
|    The GNU C Library is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU Lesser General Public
 | |
|    License as published by the Free Software Foundation; either
 | |
|    version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|    The GNU C Library is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|    Lesser General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU Lesser General Public
 | |
|    License along with the GNU C Library; if not, see
 | |
|    <http://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| #include <link.h>
 | |
| #include <elf.h>
 | |
| 
 | |
| /* Return non-zero if ADDR lies within one of L's loadable segments.
 | |
|    We have three cases we care about.
 | |
| 
 | |
|    Case 1: addr is above a segment.
 | |
|    +==================+<- l_map_end
 | |
|    |                  |<- addr
 | |
|    |------------------|<- l_addr + p_vaddr + p_memsz
 | |
|    |                  |
 | |
|    |                  |
 | |
|    |------------------|<- l_addr + p_vaddr
 | |
|    |------------------|<- l_addr
 | |
|    |                  |
 | |
|    +==================+<- l_map_start
 | |
| 
 | |
|    Case 2: addr is within a segments.
 | |
|    +==================+<- l_map_end
 | |
|    |                  |
 | |
|    |------------------|<- l_addr + p_vaddr + p_memsz
 | |
|    |                  |<- addr
 | |
|    |                  |
 | |
|    |------------------|<- l_addr + p_vaddr
 | |
|    |------------------|<- l_addr
 | |
|    |                  |
 | |
|    +==================+<- l_map_start
 | |
| 
 | |
|    Case 3: addr is below a segments.
 | |
|    +==================+<- l_map_end
 | |
|    |                  |
 | |
|    |------------------|<- l_addr + p_vaddr + p_memsz
 | |
|    |                  |
 | |
|    |                  |
 | |
|    |------------------|<- l_addr + p_vaddr
 | |
|    |------------------|<- l_addr
 | |
|    |                  |<- addr
 | |
|    +==================+<- l_map_start
 | |
| 
 | |
|    All the arithmetic is unsigned and we shift all the values down by
 | |
|    l_addr + p_vaddr and then compare the normalized addr to the range
 | |
|    of interest i.e. 0 <= addr < p_memsz.
 | |
| 
 | |
| */
 | |
| int
 | |
| internal_function
 | |
| _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
 | |
| {
 | |
|   int n = l->l_phnum;
 | |
|   const ElfW(Addr) reladdr = addr - l->l_addr;
 | |
| 
 | |
|   while (--n >= 0)
 | |
|     if (l->l_phdr[n].p_type == PT_LOAD
 | |
| 	&& reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
 | |
|       return 1;
 | |
|   return 0;
 | |
| }
 |