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