(root)/
glibc-2.38/
elf/
tst-_dl_addr_inside_object.c
       1  /* Unit test for _dl_addr_inside_object.
       2     Copyright (C) 2016-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 <stdio.h>
      20  #include <stdlib.h>
      21  #include <link.h>
      22  #include <elf.h>
      23  #include <libc-symbols.h>
      24  
      25  extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr);
      26  
      27  static int
      28  do_test (void)
      29  {
      30    int ret, err = 0;
      31    ElfW(Addr) addr;
      32    struct link_map map;
      33    ElfW(Phdr) header;
      34    map.l_phdr = &header;
      35    map.l_phnum = 1;
      36    map.l_addr = 0x0;
      37    /* Segment spans 0x2000 -> 0x4000.  */
      38    header.p_vaddr = 0x2000;
      39    header.p_memsz = 0x2000;
      40    header.p_type = PT_LOAD;
      41    /* Address is above the segment e.g. > 0x4000.  */
      42    addr = 0x5000;
      43    ret = _dl_addr_inside_object (&map, addr);
      44    switch (ret)
      45      {
      46        case 0:
      47  	printf ("PASS: Above: Address is detected as outside the segment.\n");
      48  	break;
      49        case 1:
      50          printf ("FAIL: Above: Address is detected as inside the segment.\n");
      51  	err++;
      52  	break;
      53        default:
      54  	printf ("FAIL: Above: Invalid return value.\n");
      55  	exit (1);
      56      }
      57    /* Address is inside the segment e.g. 0x2000 < addr < 0x4000.  */
      58    addr = 0x3000;
      59    ret = _dl_addr_inside_object (&map, addr);
      60    switch (ret)
      61      {
      62        case 0:
      63  	printf ("FAIL: Inside: Address is detected as outside the segment.\n");
      64  	err++;
      65  	break;
      66        case 1:
      67          printf ("PASS: Inside: Address is detected as inside the segment.\n");
      68  	break;
      69        default:
      70  	printf ("FAIL: Inside: Invalid return value.\n");
      71  	exit (1);
      72      }
      73    /* Address is below the segment e.g. < 0x2000.  */
      74    addr = 0x1000;
      75    ret = _dl_addr_inside_object (&map, addr);
      76    switch (ret)
      77      {
      78        case 0:
      79  	printf ("PASS: Below: Address is detected as outside the segment.\n");
      80  	break;
      81        case 1:
      82          printf ("FAIL: Below: Address is detected as inside the segment.\n");
      83  	err++;
      84  	break;
      85        default:
      86  	printf ("FAIL: Below: Invalid return value.\n");
      87  	exit (1);
      88      }
      89    /* Address is in the segment and addr == p_vaddr.  */
      90    addr = 0x2000;
      91    ret = _dl_addr_inside_object (&map, addr);
      92    switch (ret)
      93      {
      94        case 0:
      95  	printf ("FAIL: At p_vaddr: Address is detected as outside the segment.\n");
      96  	err++;
      97  	break;
      98        case 1:
      99          printf ("PASS: At p_vaddr: Address is detected as inside the segment.\n");
     100  	break;
     101        default:
     102  	printf ("FAIL: At p_vaddr: Invalid return value.\n");
     103  	exit (1);
     104      }
     105    /* Address is in the segment and addr == p_vaddr + p_memsz - 1.  */
     106    addr = 0x2000 + 0x2000 - 0x1;
     107    ret = _dl_addr_inside_object (&map, addr);
     108    switch (ret)
     109      {
     110        case 0:
     111  	printf ("FAIL: At p_memsz-1: Address is detected as outside the segment.\n");
     112  	err++;
     113  	break;
     114        case 1:
     115          printf ("PASS: At p_memsz-1: Address is detected as inside the segment.\n");
     116  	break;
     117        default:
     118  	printf ("FAIL: At p_memsz-1: Invalid return value.\n");
     119  	exit (1);
     120      }
     121    /* Address is outside the segment and addr == p_vaddr + p_memsz.  */
     122    addr = 0x2000 + 0x2000;
     123    ret = _dl_addr_inside_object (&map, addr);
     124    switch (ret)
     125      {
     126        case 0:
     127  	printf ("PASS: At p_memsz: Address is detected as outside the segment.\n");
     128  	break;
     129        case 1:
     130          printf ("FAIL: At p_memsz: Address is detected as inside the segment.\n");
     131  	err++;
     132  	break;
     133        default:
     134  	printf ("FAIL: At p_memsz: Invalid return value.\n");
     135  	exit (1);
     136      }
     137    /* Address is outside the segment and p_vaddr at maximum address.  */
     138    addr = 0x0 - 0x2;
     139    header.p_vaddr = 0x0 - 0x1;
     140    header.p_memsz = 0x1;
     141    ret = _dl_addr_inside_object (&map, addr);
     142    switch (ret)
     143      {
     144        case 0:
     145  	printf ("PASS: At max: Address is detected as outside the segment.\n");
     146  	break;
     147        case 1:
     148          printf ("FAIL: At max: Address is detected as inside the segment.\n");
     149  	err++;
     150  	break;
     151        default:
     152  	printf ("FAIL: At max: Invalid return value.\n");
     153  	exit (1);
     154      }
     155    /* Address is outside the segment and p_vaddr at minimum address.  */
     156    addr = 0x1;
     157    header.p_vaddr = 0x0;
     158    header.p_memsz = 0x1;
     159    ret = _dl_addr_inside_object (&map, addr);
     160    switch (ret)
     161      {
     162        case 0:
     163  	printf ("PASS: At min: Address is detected as outside the segment.\n");
     164  	break;
     165        case 1:
     166          printf ("FAIL: At min: Address is detected as inside the segment.\n");
     167  	err++;
     168  	break;
     169        default:
     170  	printf ("FAIL: At min: Invalid return value.\n");
     171  	exit (1);
     172      }
     173    /* Address is always inside the segment with p_memsz at max.  */
     174    addr = 0x0;
     175    header.p_vaddr = 0x0;
     176    header.p_memsz = 0x0 - 0x1;
     177    ret = _dl_addr_inside_object (&map, addr);
     178    switch (ret)
     179      {
     180        case 0:
     181  	printf ("FAIL: At maxmem: Address is detected as outside the segment.\n");
     182  	err++;
     183  	break;
     184        case 1:
     185          printf ("PASS: At maxmem: Address is detected as inside the segment.\n");
     186  	break;
     187        default:
     188  	printf ("FAIL: At maxmem: Invalid return value.\n");
     189  	exit (1);
     190      }
     191    /* Attempt to wrap addr into the segment.
     192       Pick a load address in the middle of the address space.
     193       Place the test address at 0x0 so it wraps to the middle again.  */
     194    map.l_addr = 0x0 - 0x1;
     195    map.l_addr = map.l_addr / 2;
     196    addr = 0;
     197    /* Setup a segment covering 1/2 the address space.  */
     198    header.p_vaddr = 0x0;
     199    header.p_memsz = 0x0 - 0x1 - map.l_addr;
     200    /* No matter where you place addr everything is shifted modulo l_addr
     201       and even with this underflow you're always 1 byte away from being
     202       in the range.  */
     203    ret = _dl_addr_inside_object (&map, addr);
     204    switch (ret)
     205      {
     206        case 0:
     207  	printf ("PASS: Underflow: Address is detected as outside the segment.\n");
     208  	break;
     209        case 1:
     210  	printf ("FAIL: Underflow: Address is detected as inside the segment.\n");
     211  	err++;
     212  	break;
     213        default:
     214  	printf ("FAIL: Underflow: Invalid return value.\n");
     215  	exit (1);
     216      }
     217  
     218    return err;
     219  }
     220  
     221  #include <support/test-driver.c>