(root)/
glibc-2.38/
elf/
dl-addr-obj.c
       1  /* Determine if address is inside object load segments.
       2     Copyright (C) 1996-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <link.h>
      20  #include <elf.h>
      21  
      22  /* Return non-zero if ADDR lies within one of L's loadable segments.
      23     We have three cases we care about.
      24  
      25     Case 1: addr is above a segment.
      26     +==================+<- l_map_end
      27     |                  |<- addr
      28     |------------------|<- l_addr + p_vaddr + p_memsz
      29     |                  |
      30     |                  |
      31     |------------------|<- l_addr + p_vaddr
      32     |------------------|<- l_addr
      33     |                  |
      34     +==================+<- l_map_start
      35  
      36     Case 2: addr is within a segments.
      37     +==================+<- l_map_end
      38     |                  |
      39     |------------------|<- l_addr + p_vaddr + p_memsz
      40     |                  |<- addr
      41     |                  |
      42     |------------------|<- l_addr + p_vaddr
      43     |------------------|<- l_addr
      44     |                  |
      45     +==================+<- l_map_start
      46  
      47     Case 3: addr is below a segments.
      48     +==================+<- l_map_end
      49     |                  |
      50     |------------------|<- l_addr + p_vaddr + p_memsz
      51     |                  |
      52     |                  |
      53     |------------------|<- l_addr + p_vaddr
      54     |------------------|<- l_addr
      55     |                  |<- addr
      56     +==================+<- l_map_start
      57  
      58     All the arithmetic is unsigned and we shift all the values down by
      59     l_addr + p_vaddr and then compare the normalized addr to the range
      60     of interest i.e. 0 <= addr < p_memsz.
      61  
      62  */
      63  int
      64  _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
      65  {
      66    int n = l->l_phnum;
      67    const ElfW(Addr) reladdr = addr - l->l_addr;
      68  
      69    while (--n >= 0)
      70      if (l->l_phdr[n].p_type == PT_LOAD
      71  	&& reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
      72        return 1;
      73    return 0;
      74  }