]>
Commit | Line | Data |
---|---|---|
42b6953b IB |
1 | /* sframe-dump.c - Textual dump of .sframe. |
2 | ||
fd67aa11 | 3 | Copyright (C) 2022-2024 Free Software Foundation, Inc. |
42b6953b | 4 | |
f4af4272 | 5 | This file is part of libsframe. |
42b6953b IB |
6 | |
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include <string.h> | |
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <inttypes.h> | |
24 | #include "sframe-impl.h" | |
25 | ||
26 | #define SFRAME_HEADER_FLAGS_STR_MAX_LEN 50 | |
27 | ||
95e829af IB |
28 | /* Return TRUE if the SFrame section is associated with the aarch64 ABIs. */ |
29 | ||
30 | static bool | |
31 | is_sframe_abi_arch_aarch64 (sframe_decoder_ctx *sfd_ctx) | |
32 | { | |
33 | bool aarch64_p = false; | |
34 | ||
de4879fe IB |
35 | uint8_t abi_arch = sframe_decoder_get_abi_arch (sfd_ctx); |
36 | if (abi_arch == SFRAME_ABI_AARCH64_ENDIAN_BIG | |
37 | || abi_arch == SFRAME_ABI_AARCH64_ENDIAN_LITTLE) | |
95e829af IB |
38 | aarch64_p = true; |
39 | ||
40 | return aarch64_p; | |
41 | } | |
42 | ||
42b6953b IB |
43 | static void |
44 | dump_sframe_header (sframe_decoder_ctx *sfd_ctx) | |
45 | { | |
ce9a8725 IB |
46 | uint8_t ver; |
47 | uint8_t flags; | |
48 | char *flags_str; | |
49 | const char *ver_str = NULL; | |
42b6953b IB |
50 | const sframe_header *header = &(sfd_ctx->sfd_header); |
51 | ||
52 | /* Prepare SFrame section version string. */ | |
53 | const char *version_names[] | |
54 | = { "NULL", | |
ce9a8725 IB |
55 | "SFRAME_VERSION_1", |
56 | "SFRAME_VERSION_2" }; | |
57 | ||
58 | /* PS: Keep SFRAME_HEADER_FLAGS_STR_MAX_LEN in sync if adding more members to | |
59 | this array. */ | |
60 | const char *flag_names[] | |
61 | = { "SFRAME_F_FDE_SORTED", | |
62 | "SFRAME_F_FRAME_POINTER" }; | |
63 | ||
64 | ver = sframe_decoder_get_version (sfd_ctx); | |
42b6953b | 65 | if (ver <= SFRAME_VERSION) |
ce9a8725 | 66 | ver_str = version_names[ver]; |
42b6953b IB |
67 | |
68 | /* Prepare SFrame section flags string. */ | |
ce9a8725 IB |
69 | flags = header->sfh_preamble.sfp_flags; |
70 | flags_str = (char*) calloc (sizeof (char), SFRAME_HEADER_FLAGS_STR_MAX_LEN); | |
42b6953b IB |
71 | if (flags) |
72 | { | |
42b6953b IB |
73 | if (flags & SFRAME_F_FDE_SORTED) |
74 | strcpy (flags_str, flag_names[0]); | |
75 | if (flags & SFRAME_F_FRAME_POINTER) | |
76 | { | |
77 | if (strlen (flags_str) > 0) | |
78 | strcpy (flags_str, ","); | |
79 | strcpy (flags_str, flag_names[1]); | |
80 | } | |
81 | } | |
82 | else | |
83 | strcpy (flags_str, "NONE"); | |
84 | ||
85 | const char* subsec_name = "Header"; | |
86 | printf ("\n"); | |
87 | printf (" %s :\n", subsec_name); | |
88 | printf ("\n"); | |
ce9a8725 | 89 | printf (" Version: %s\n", ver_str); |
42b6953b | 90 | printf (" Flags: %s\n", flags_str); |
ce9a8725 | 91 | printf (" Num FDEs: %d\n", sframe_decoder_get_num_fidx (sfd_ctx)); |
42b6953b IB |
92 | printf (" Num FREs: %d\n", header->sfh_num_fres); |
93 | ||
94 | free (flags_str); | |
95 | } | |
96 | ||
97 | static void | |
98 | dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx, | |
99 | unsigned int funcidx, | |
100 | uint64_t sec_addr) | |
101 | { | |
102 | uint32_t j = 0; | |
103 | uint32_t num_fres = 0; | |
104 | uint32_t func_size = 0; | |
105 | int32_t func_start_address = 0; | |
106 | unsigned char func_info = 0; | |
107 | ||
108 | uint64_t func_start_pc_vma = 0; | |
109 | uint64_t fre_start_pc_vma = 0; | |
110 | const char *base_reg_str[] = {"fp", "sp"}; | |
111 | int32_t cfa_offset = 0; | |
112 | int32_t fp_offset = 0; | |
113 | int32_t ra_offset = 0; | |
a9f1da26 | 114 | uint8_t base_reg_id = 0; |
42b6953b IB |
115 | int err[3] = {0, 0, 0}; |
116 | ||
117 | sframe_frame_row_entry fre; | |
118 | ||
119 | /* Get the SFrame function descriptor. */ | |
120 | sframe_decoder_get_funcdesc (sfd_ctx, funcidx, &num_fres, | |
121 | &func_size, &func_start_address, &func_info); | |
122 | /* Calculate the virtual memory address for function start pc. */ | |
123 | func_start_pc_vma = func_start_address + sec_addr; | |
124 | ||
125 | /* Mark FDEs with [m] where the FRE start address is interpreted as a | |
126 | mask. */ | |
127 | int fde_type_addrmask_p = (SFRAME_V1_FUNC_FDE_TYPE (func_info) | |
128 | == SFRAME_FDE_TYPE_PCMASK); | |
129 | const char *fde_type_marker | |
130 | = (fde_type_addrmask_p ? "[m]" : " "); | |
131 | ||
132 | printf ("\n func idx [%d]: pc = 0x%"PRIx64 ", size = %d bytes", | |
133 | funcidx, | |
134 | func_start_pc_vma, | |
135 | func_size); | |
136 | ||
95e829af IB |
137 | if (is_sframe_abi_arch_aarch64 (sfd_ctx) |
138 | && (SFRAME_V1_FUNC_PAUTH_KEY (func_info) == SFRAME_AARCH64_PAUTH_KEY_B)) | |
139 | printf (", pauth = B key"); | |
140 | ||
42b6953b | 141 | char temp[100]; |
42b6953b | 142 | |
f4af4272 IB |
143 | printf ("\n %-7s%-8s %-10s%-10s%-13s", |
144 | "STARTPC", fde_type_marker, "CFA", "FP", "RA"); | |
42b6953b IB |
145 | for (j = 0; j < num_fres; j++) |
146 | { | |
147 | sframe_decoder_get_fre (sfd_ctx, funcidx, j, &fre); | |
148 | ||
149 | fre_start_pc_vma = (fde_type_addrmask_p | |
150 | ? fre.fre_start_addr | |
151 | : func_start_pc_vma + fre.fre_start_addr); | |
152 | ||
153 | /* FIXME - fixup the err caching in array. | |
154 | assert no error for base reg id. */ | |
155 | base_reg_id = sframe_fre_get_base_reg_id (&fre, &err[0]); | |
156 | cfa_offset = sframe_fre_get_cfa_offset (sfd_ctx, &fre, &err[0]); | |
157 | fp_offset = sframe_fre_get_fp_offset (sfd_ctx, &fre, &err[1]); | |
158 | ra_offset = sframe_fre_get_ra_offset (sfd_ctx, &fre, &err[2]); | |
159 | ||
160 | /* Dump CFA info. */ | |
161 | printf ("\n"); | |
162 | printf (" %016"PRIx64, fre_start_pc_vma); | |
163 | sprintf (temp, "%s+%d", base_reg_str[base_reg_id], cfa_offset); | |
164 | printf (" %-10s", temp); | |
165 | ||
166 | /* Dump SP/FP info. */ | |
42b6953b IB |
167 | if (err[1] == 0) |
168 | sprintf (temp, "c%+d", fp_offset); | |
169 | else | |
170 | strcpy (temp, "u"); | |
171 | printf ("%-10s", temp); | |
172 | ||
36aecb41 IB |
173 | /* Dump RA info. |
174 | If an ABI does not track RA offset, e.g., AMD64, display a 'u', | |
175 | else display the offset d as 'c+-d'. */ | |
176 | if (sframe_decoder_get_fixed_ra_offset(sfd_ctx) | |
177 | != SFRAME_CFA_FIXED_RA_INVALID) | |
42b6953b | 178 | strcpy (temp, "u"); |
36aecb41 IB |
179 | else if (err[2] == 0) |
180 | sprintf (temp, "c%+d", ra_offset); | |
181 | ||
49948bce IB |
182 | /* Mark SFrame FRE's RA information with "[s]" if the RA is mangled |
183 | with signature bits. */ | |
184 | const char *ra_mangled_p_str | |
185 | = ((sframe_fre_get_ra_mangled_p (sfd_ctx, &fre, &err[2])) | |
186 | ? "[s]" : " "); | |
68e0003e | 187 | strcat (temp, ra_mangled_p_str); |
49948bce | 188 | printf ("%-13s", temp); |
42b6953b IB |
189 | } |
190 | } | |
191 | ||
192 | static void | |
193 | dump_sframe_functions (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr) | |
194 | { | |
195 | uint32_t i; | |
196 | uint32_t num_fdes; | |
197 | ||
198 | const char* subsec_name = "Function Index"; | |
199 | printf ("\n %s :\n", subsec_name); | |
200 | ||
201 | num_fdes = sframe_decoder_get_num_fidx (sfd_ctx); | |
202 | for (i = 0; i < num_fdes; i++) | |
203 | { | |
204 | dump_sframe_func_with_fres (sfd_ctx, i, sec_addr); | |
205 | printf ("\n"); | |
206 | } | |
207 | } | |
208 | ||
209 | void | |
210 | dump_sframe (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr) | |
211 | { | |
ce9a8725 IB |
212 | uint8_t ver; |
213 | ||
42b6953b | 214 | dump_sframe_header (sfd_ctx); |
ce9a8725 IB |
215 | |
216 | ver = sframe_decoder_get_version (sfd_ctx); | |
217 | if (ver == SFRAME_VERSION) | |
218 | dump_sframe_functions (sfd_ctx, sec_addr); | |
219 | else | |
220 | printf ("\n No further information can be displayed. %s", | |
221 | "SFrame version not supported\n"); | |
42b6953b | 222 | } |