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