1/* findfunc-1.c -- Test for sframe_get_funcdesc_with_addr in libsframe. 2 3 Copyright (C) 2023-2024 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18/* sframe_get_funcdesc_with_addr is a core API in the libsframe library, which 19 is used to find an FDE given a PC. It is used by sframe_find_fre (). The 20 latter is the mainstay for an SFrame based stack tracer. 21 22 The tests in here stress the sframe_get_funcdesc_with_addr API via calls to 23 the sframe_find_fre (). */ 24 25#include "config.h" 26 27#include <stdlib.h> 28#include <string.h> 29#include <sys/stat.h> 30 31#include "sframe-api.h" 32 33/* DejaGnu should not use gnulib's vsnprintf replacement here. */ 34#undef vsnprintf 35#include <dejagnu.h> 36 37static int 38add_fde1 (sframe_encoder_ctx *encode, int idx) 39{ 40 int i, err; 41 /* A contiguous block containing 4 FREs. */ 42 sframe_frame_row_entry fres[] 43 = { {0x0, {0x1, 0, 0}, 0x3}, 44 {0x1, {0x2, 0xf0, 0}, 0x5}, 45 {0x10, {0x3, 0xf0, 0}, 0x4}, 46 {0x38, {0x8, 0xf0, 0}, 0x5} 47 }; 48 49 unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1, 50 SFRAME_FDE_TYPE_PCINC); 51 err = sframe_encoder_add_funcdesc (encode, 0xfffff03e, 0x40, finfo, 4); 52 if (err == -1) 53 return err; 54 55 for (i = 0; i < 4; i++) 56 if (sframe_encoder_add_fre (encode, idx,fres+i) == SFRAME_ERR) 57 return -1; 58 59 return 0; 60} 61 62static int 63add_fde2 (sframe_encoder_ctx *encode, int idx) 64{ 65 int i, err; 66 /* A contiguous block containing 4 FREs. */ 67 sframe_frame_row_entry fres[] 68 = { {0x0, {0x10, 0, 0}, 0x3}, 69 {0x10, {0x12, 0xf0, 0}, 0x5}, 70 {0x14, {0x14, 0xf0, 0}, 0x4}, 71 {0x20, {0x15, 0xf0, 0}, 0x5} 72 }; 73 74 unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1, 75 SFRAME_FDE_TYPE_PCINC); 76 err = sframe_encoder_add_funcdesc (encode, 0xfffff08e, 0x60, finfo, 4); 77 if (err == -1) 78 return err; 79 80 for (i = 0; i < 4; i++) 81 if (sframe_encoder_add_fre (encode, idx, fres+i) == SFRAME_ERR) 82 return -1; 83 84 return 0; 85} 86 87static int 88add_fde3 (sframe_encoder_ctx *encode, int idx) 89{ 90 int i, err; 91 /* A contiguous block containing 4 FREs. */ 92 sframe_frame_row_entry fres[] 93 = { {0x0, {0x16, 0, 0}, 0x3}, 94 {0x1, {0x17, 0xf0, 0}, 0x5}, 95 {0x10, {0x18, 0xf0, 0}, 0x4}, 96 {0x38, {0x19, 0xf0, 0}, 0x5} 97 }; 98 99 unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1, 100 SFRAME_FDE_TYPE_PCINC); 101 err = sframe_encoder_add_funcdesc (encode, 0xfffff10e, 0x40, finfo, 4); 102 if (err == -1) 103 return err; 104 105 for (i = 0; i < 4; i++) 106 if (sframe_encoder_add_fre (encode, idx,fres+i) == SFRAME_ERR) 107 return -1; 108 109 return 0; 110} 111 112int main (void) 113{ 114 sframe_encoder_ctx *encode; 115 sframe_decoder_ctx *dctx; 116 sframe_frame_row_entry frep; 117 char *sframe_buf; 118 size_t sf_size; 119 int err = 0; 120 unsigned int fde_cnt = 0; 121 122#define TEST(name, cond) \ 123 do \ 124 { \ 125 if (cond) \ 126 pass (name); \ 127 else \ 128 fail (name); \ 129 } \ 130 while (0) 131 132 encode = sframe_encode (SFRAME_VERSION, 0, 133 SFRAME_ABI_AMD64_ENDIAN_LITTLE, 134 SFRAME_CFA_FIXED_FP_INVALID, 135 -8, /* Fixed RA offset for AMD64. */ 136 &err); 137 138 /* Add FDE at index 0. */ 139 err = add_fde1 (encode, 0); 140 TEST ("findfunc-1: Adding FDE1", err == 0); 141 142 /* Add FDE at index 1. */ 143 err = add_fde2 (encode, 1); 144 TEST ("findfunc-1: Adding FDE2", err == 0); 145 146 /* Add FDE at index 2. */ 147 err = add_fde3 (encode, 2); 148 TEST ("findfunc-1: Adding FDE3", err == 0); 149 150 fde_cnt = sframe_encoder_get_num_fidx (encode); 151 TEST ("findfunc-1: Test FDE count", fde_cnt == 3); 152 153 sframe_buf = sframe_encoder_write (encode, &sf_size, &err); 154 TEST ("findfunc-1: Encoder write", err == 0); 155 156 dctx = sframe_decode (sframe_buf, sf_size, &err); 157 TEST("findfunc-1: Decoder setup", dctx != NULL); 158 159 /* Following negative tests check that libsframe APIs 160 (sframe_get_funcdesc_with_addr, sframe_find_fre) work 161 well for PCs not covered by the FDEs. */ 162 163 /* Search with PC less than the first FDE's start addr. */ 164 err = sframe_find_fre (dctx, (0xfffff03e - 0x15), &frep); 165 TEST("findfunc-1: test-1: Find FRE for PC not in range", 166 (err == SFRAME_ERR)); 167 168 /* Search with a PC between func1's last PC and func2's first PC. */ 169 err = sframe_find_fre (dctx, (0xfffff03e + 0x40 + 0x1), &frep); 170 TEST("findfunc-1: test-2: Find FRE for PC not in range", 171 (err == SFRAME_ERR)); 172 173 /* Search for a PC between func2's last PC and func3's first PC. */ 174 err = sframe_find_fre (dctx, (0xfffff08e + 0x60 + 0x3), &frep); 175 TEST("findfunc-1: test-3: Find FRE for PC not in range", 176 (err == SFRAME_ERR)); 177 178 /* Search for a PC beyond the last func, i.e., > func3's last PC. */ 179 err = sframe_find_fre (dctx, (0xfffff10e + 0x40 + 0x10), &frep); 180 TEST("findfunc-1: test-4: Find FRE for PC not in range", 181 (err == SFRAME_ERR)); 182 183 /* And some positive tests... */ 184 185 /* Find an FRE for PC in FDE1. */ 186 err = sframe_find_fre (dctx, (0xfffff03e + 0x9), &frep); 187 TEST("findfunc-1: Find FRE in FDE1", 188 ((err == 0) && (sframe_fre_get_cfa_offset(dctx, &frep, &err) == 0x2))); 189 190 /* Find an FRE for PC in FDE2. */ 191 err = sframe_find_fre (dctx, (0xfffff08e + 0x11), &frep); 192 TEST("findfunc-1: Find FRE in FDE2", 193 ((err == 0) && (sframe_fre_get_cfa_offset(dctx, &frep, &err) == 0x12))); 194 195 /* Find an FRE for PC in FDE3. */ 196 err = sframe_find_fre (dctx, (0xfffff10e + 0x10), &frep); 197 TEST("findfunc-1: Find FRE in FDE3", 198 ((err == 0) && (sframe_fre_get_cfa_offset(dctx, &frep, &err) == 0x18))); 199 200 sframe_encoder_free (&encode); 201 sframe_decoder_free (&dctx); 202 203 return 0; 204} 205