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