Home | History | Annotate | Line # | Download | only in libsframe.find
      1  1.1  christos /* plt-findfre-2.c -- Test for sframe_find_fre for SFrame FDE of type
      2  1.1  christos    PCMASK with with one SFrame FRE only.
      3  1.1  christos 
      4  1.1  christos    Copyright (C) 2025 Free Software Foundation, Inc.
      5  1.1  christos 
      6  1.1  christos    This program is free software; you can redistribute it and/or modify
      7  1.1  christos    it under the terms of the GNU General Public License as published by
      8  1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9  1.1  christos    (at your option) any later version.
     10  1.1  christos 
     11  1.1  christos    This program is distributed in the hope that it will be useful,
     12  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  christos    GNU General Public License for more details.
     15  1.1  christos 
     16  1.1  christos    You should have received a copy of the GNU General Public License
     17  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18  1.1  christos 
     19  1.1  christos #include "config.h"
     20  1.1  christos 
     21  1.1  christos #include <stdlib.h>
     22  1.1  christos #include <string.h>
     23  1.1  christos #include <sys/stat.h>
     24  1.1  christos 
     25  1.1  christos #include "sframe-api.h"
     26  1.1  christos 
     27  1.1  christos /* DejaGnu should not use gnulib's vsnprintf replacement here.  */
     28  1.1  christos #undef vsnprintf
     29  1.1  christos #include <dejagnu.h>
     30  1.1  christos 
     31  1.1  christos /* s390x-specific size in bytes of plt0 and pltN.  */
     32  1.1  christos #define PLT_SIZE 32
     33  1.1  christos 
     34  1.1  christos /* Magic values added to CFA offsets to make them distingishable.  Must
     35  1.1  christos    be multiple of 8 due to s390x-specific CFA alignment factor.  */
     36  1.1  christos #define PLT0_CFA_OFFSET_MAGIC 0
     37  1.1  christos #define PLTN_CFA_OFFSET_MAGIC 8
     38  1.1  christos 
     39  1.1  christos static int
     40  1.1  christos add_plt0_fde (sframe_encoder_ctx *ectx, uint32_t plt_vaddr,
     41  1.1  christos 	      uint32_t sframe_vaddr, int idx)
     42  1.1  christos {
     43  1.1  christos   /* 1 single FRE.  */
     44  1.1  christos   sframe_frame_row_entry fre
     45  1.1  christos     = { 0x0,
     46  1.1  christos 	{ SFRAME_V2_S390X_CFA_OFFSET_ENCODE (160 + PLT0_CFA_OFFSET_MAGIC) },
     47  1.1  christos 	SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) };
     48  1.1  christos 
     49  1.1  christos   unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
     50  1.1  christos 						     SFRAME_FDE_TYPE_PCINC);
     51  1.1  christos   uint32_t offsetof_fde_in_sec
     52  1.1  christos     = sframe_encoder_get_offsetof_fde_start_addr (ectx, idx, NULL);
     53  1.1  christos 
     54  1.1  christos   int32_t func_start_addr = (plt_vaddr
     55  1.1  christos 			     - (sframe_vaddr + offsetof_fde_in_sec));
     56  1.1  christos 
     57  1.1  christos   /* 1 PCINC-type FDE for 1 plt0 entry of 32 bytes.  */
     58  1.1  christos   int err = sframe_encoder_add_funcdesc_v2 (ectx, func_start_addr,
     59  1.1  christos 					    PLT_SIZE /* func size.  */,
     60  1.1  christos 					    finfo,
     61  1.1  christos 					    0 /* rep block size.  */,
     62  1.1  christos 					    1 /* num FREs.  */);
     63  1.1  christos   if (err == -1)
     64  1.1  christos     return err;
     65  1.1  christos 
     66  1.1  christos   if (sframe_encoder_add_fre (ectx, idx, &fre) == SFRAME_ERR)
     67  1.1  christos     return -1;
     68  1.1  christos 
     69  1.1  christos   return 0;
     70  1.1  christos }
     71  1.1  christos 
     72  1.1  christos static int
     73  1.1  christos add_pltn_fde (sframe_encoder_ctx *ectx, uint32_t plt_vaddr,
     74  1.1  christos 	      uint32_t sframe_vaddr, int idx)
     75  1.1  christos {
     76  1.1  christos   /* 1 single FRE.  */
     77  1.1  christos   sframe_frame_row_entry fre
     78  1.1  christos     = { 0x0,
     79  1.1  christos 	{ SFRAME_V2_S390X_CFA_OFFSET_ENCODE (160 + PLTN_CFA_OFFSET_MAGIC) },
     80  1.1  christos 	SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) };
     81  1.1  christos 
     82  1.1  christos   unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
     83  1.1  christos 						     SFRAME_FDE_TYPE_PCMASK);
     84  1.1  christos   uint32_t offsetof_fde_in_sec
     85  1.1  christos     = sframe_encoder_get_offsetof_fde_start_addr (ectx, idx, NULL);
     86  1.1  christos 
     87  1.1  christos   int32_t func_start_addr = (plt_vaddr
     88  1.1  christos 			     - (sframe_vaddr + offsetof_fde_in_sec));
     89  1.1  christos 
     90  1.1  christos   /* 1 PCMASK-type FDE for 5 pltN entries of 32 bytes each.  */
     91  1.1  christos   int err = sframe_encoder_add_funcdesc_v2 (ectx, func_start_addr,
     92  1.1  christos 					    5 * PLT_SIZE /* func size.  */,
     93  1.1  christos 					    finfo,
     94  1.1  christos 					    PLT_SIZE /* rep block size.  */,
     95  1.1  christos 					    1 /* num FREs.  */);
     96  1.1  christos   if (err == -1)
     97  1.1  christos     return err;
     98  1.1  christos 
     99  1.1  christos   if (sframe_encoder_add_fre (ectx, idx, &fre) == SFRAME_ERR)
    100  1.1  christos     return -1;
    101  1.1  christos 
    102  1.1  christos   return 0;
    103  1.1  christos }
    104  1.1  christos 
    105  1.1  christos static
    106  1.1  christos void test_plt_findfre (const char suffix, const uint32_t plt_vaddr,
    107  1.1  christos 		       const uint32_t sframe_vaddr)
    108  1.1  christos {
    109  1.1  christos   sframe_encoder_ctx *ectx;
    110  1.1  christos   sframe_decoder_ctx *dctx;
    111  1.1  christos   sframe_frame_row_entry frep;
    112  1.1  christos   char *sframe_buf;
    113  1.1  christos   size_t sf_size;
    114  1.1  christos   int err = 0;
    115  1.1  christos   unsigned int fde_cnt = 0;
    116  1.1  christos   int i;
    117  1.1  christos 
    118  1.1  christos #define TEST(cond, ...)							\
    119  1.1  christos   do									\
    120  1.1  christos     {									\
    121  1.1  christos       if (cond)								\
    122  1.1  christos 	pass (__VA_ARGS__);						\
    123  1.1  christos       else								\
    124  1.1  christos 	fail (__VA_ARGS__);						\
    125  1.1  christos     }									\
    126  1.1  christos     while (0)
    127  1.1  christos 
    128  1.1  christos   ectx = sframe_encode (SFRAME_VERSION, SFRAME_F_FDE_FUNC_START_PCREL,
    129  1.1  christos 			SFRAME_ABI_S390X_ENDIAN_BIG,
    130  1.1  christos 			SFRAME_CFA_FIXED_FP_INVALID,
    131  1.1  christos 			SFRAME_CFA_FIXED_RA_INVALID,
    132  1.1  christos 			&err);
    133  1.1  christos   TEST (ectx != NULL && err == 0, "plt-findfre-2%c: Creating SFrame encoder", suffix);
    134  1.1  christos 
    135  1.1  christos   err = add_plt0_fde (ectx, plt_vaddr, sframe_vaddr, 0);
    136  1.1  christos   TEST (err == 0, "plt-findfre-2%c: Adding FDE for plt0", suffix);
    137  1.1  christos 
    138  1.1  christos   fde_cnt = sframe_encoder_get_num_fidx (ectx);
    139  1.1  christos   TEST (fde_cnt == 1, "plt-findfre-2%c: Test FDE count after adding FDE for plt0", suffix);
    140  1.1  christos 
    141  1.1  christos   err = add_pltn_fde (ectx, plt_vaddr + PLT_SIZE, sframe_vaddr, 1);
    142  1.1  christos   TEST (err == 0, "plt-findfre-2%c: Adding FDE for pltN", suffix);
    143  1.1  christos 
    144  1.1  christos   fde_cnt = sframe_encoder_get_num_fidx (ectx);
    145  1.1  christos   TEST (fde_cnt == 2, "plt-findfre-2%c: Test FDE count after adding FDE for pltN", suffix);
    146  1.1  christos 
    147  1.1  christos   sframe_buf = sframe_encoder_write (ectx, &sf_size, &err);
    148  1.1  christos   TEST (err == 0, "plt-findfre-2%c: Encoder write", suffix);
    149  1.1  christos 
    150  1.1  christos   dctx = sframe_decode (sframe_buf, sf_size, &err);
    151  1.1  christos   TEST (dctx != NULL, "plt-findfre-2%c: Decoder setup", suffix);
    152  1.1  christos 
    153  1.1  christos   /* Find the only FRE in PLT0 at offset 0.  */
    154  1.1  christos   err = sframe_find_fre (dctx, (plt_vaddr + 0 - sframe_vaddr), &frep);
    155  1.1  christos   TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLT0_CFA_OFFSET_MAGIC,
    156  1.1  christos 	"plt-findfre-2%c: Find only FRE in PLT0 at offset 0", suffix);
    157  1.1  christos 
    158  1.1  christos   /* Find the only FRE in PLT0 at offset PLT_SIZE-1.  */
    159  1.1  christos   err = sframe_find_fre (dctx, (plt_vaddr + (PLT_SIZE-1) - sframe_vaddr), &frep);
    160  1.1  christos   TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLT0_CFA_OFFSET_MAGIC,
    161  1.1  christos 	"plt-findfre-2%c: Find only FRE in PLT0 at offset PLT_SIZE-1", suffix);
    162  1.1  christos 
    163  1.1  christos   /* Find the only FRE in PLT1-5 at offset 0 and PLT_SIZE-1.  */
    164  1.1  christos   for (i = 1; i < 5; i++)
    165  1.1  christos     {
    166  1.1  christos       /* Find the only FRE in PLTN at offset 0.  */
    167  1.1  christos       err = sframe_find_fre (dctx, (plt_vaddr + i * PLT_SIZE + 0 - sframe_vaddr), &frep);
    168  1.1  christos       TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLTN_CFA_OFFSET_MAGIC,
    169  1.1  christos 	    "plt-findfre-2%c: Find only FRE in PLT%d at offset 0", suffix, i);
    170  1.1  christos 
    171  1.1  christos       /* Find the only FRE in PLTN at offset 31.  */
    172  1.1  christos       err = sframe_find_fre (dctx, (plt_vaddr + i * PLT_SIZE + (PLT_SIZE-1) - sframe_vaddr), &frep);
    173  1.1  christos       TEST (err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 160 + PLTN_CFA_OFFSET_MAGIC,
    174  1.1  christos 	    "plt-findfre-2%c: Find only FRE in PLT%d at offset PLT_SIZE-1", suffix, i);
    175  1.1  christos     }
    176  1.1  christos 
    177  1.1  christos   /* Find no FRE in non-existing PLT6 at offset 0.  */
    178  1.1  christos   err = sframe_find_fre (dctx, (plt_vaddr + 6 * PLT_SIZE + 0 - sframe_vaddr), &frep);
    179  1.1  christos   TEST (err != 0, "plt-findfre-2%c: Find no FRE in out of range PLT6 at offset 0", suffix);
    180  1.1  christos 
    181  1.1  christos   sframe_encoder_free (&ectx);
    182  1.1  christos   sframe_decoder_free (&dctx);
    183  1.1  christos }
    184  1.1  christos 
    185  1.1  christos int
    186  1.1  christos main (void)
    187  1.1  christos {
    188  1.1  christos   uint32_t sframe_vaddr = 0x402220;
    189  1.1  christos   uint32_t plt_vaddr = 0x401020;
    190  1.1  christos   printf ("plt-findfre-2a: Testing with plt_vaddr = %#x; sframe_vaddr = %#x\n",
    191  1.1  christos 	  plt_vaddr, sframe_vaddr);
    192  1.1  christos   test_plt_findfre ('a', plt_vaddr, sframe_vaddr);
    193  1.1  christos 
    194  1.1  christos   sframe_vaddr = 0x401020;
    195  1.1  christos   plt_vaddr = 0x402220;
    196  1.1  christos   printf ("plt-findfre-2b: Testing with plt_vaddr = %#x; sframe_vaddr = %#x\n",
    197  1.1  christos 	  plt_vaddr, sframe_vaddr);
    198  1.1  christos   test_plt_findfre ('b', plt_vaddr, sframe_vaddr);
    199  1.1  christos 
    200  1.1  christos   return 0;
    201  1.1  christos }
    202