plt-findfre-2.c revision 1.1 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