1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 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, or (at your option) 9 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, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <stdio.h> 23#include <string.h> 24#include <stdlib.h> 25#include <locale.h> 26#include <sys/param.h> 27 28#include "demangle.h" 29#include "gp-defs.h" 30#include "StringBuilder.h" 31#include "CompCom.h" 32#include "Elf.h" 33#include "util.h" 34#include "i18n.h" 35#include "comp_com.c" 36 37CompComment::CompComment (Elf *_elf, int _compcom) 38{ 39 elf = _elf; 40 compcom = _compcom; 41 elf_cls = elf->elf_getclass (); 42} 43 44CompComment::~CompComment () { } 45 46int 47CompComment::get_align (int64_t offset, int align) 48{ 49 int val = (int) (offset % align); 50 if (val) 51 val = align - val; 52 return val; 53} 54 55/* 56 * Preprocesses the header structure, builds a table of messages with the line 57 * numbers, PCoffsets, original index, and compmsg pointer for each message. 58 * If the show_bits field is not in the message, this routine would fill it in 59 * from the mapping from COMPMSG_ID 60 */ 61int 62CompComment::compcom_open (CheckSrcName check_src) 63{ 64 if (check_src == NULL) 65 return 0; 66 Elf_Data *data = elf->elf_getdata (compcom); 67 uint64_t b_offset = data->d_off; 68 if (get_align (b_offset, 4)) // not align 4 69 return 0; 70 char *CommData = (char *) data->d_buf; 71 uint64_t offset = b_offset; 72 for (uint64_t e_offset = b_offset + data->d_size; offset < e_offset;) 73 { 74 offset += get_align (offset, (int) data->d_align); 75 if (offset >= e_offset) 76 return 0; 77 compcomhdr *hdr = (compcomhdr *) (CommData + (offset - b_offset)); 78 int hdr_msgcount = elf->decode (hdr->msgcount); 79 int hdr_srcname = elf->decode (hdr->srcname); 80 int hdr_stringlen = elf->decode (hdr->stringlen); 81 int hdr_paramcount = elf->decode (hdr->paramcount); 82 size_t length = sizeof (compcomhdr) + hdr_msgcount * sizeof (compmsg) + 83 hdr_paramcount * sizeof (int32_t); 84 if (offset + length + hdr_stringlen > e_offset || hdr_srcname < 0 85 || hdr_srcname >= hdr_stringlen) 86 return 0; 87 88 // check source file 89 char *src_name = (char *) (((char*) hdr) + length + hdr_srcname); 90 if (check_src (src_name)) 91 { 92 msgs = (compmsg *) (((char *) hdr) + sizeof (compcomhdr)); 93 params = (int32_t *) ((char *) msgs + hdr_msgcount * sizeof (compmsg)); 94 strs = (char *) ((char *) params + hdr_paramcount * sizeof (int32_t)); 95 96 // initialize the I18N/L10N strings & set the visible table 97 ccm_vis_init (); 98 return hdr_msgcount; 99 } 100 offset += (length + hdr_stringlen); 101 } 102 return 0; 103} 104 105char * 106CompComment::get_demangle_name (char *fname) 107{ 108 if (*fname == '_') 109 return cplus_demangle (fname, DMGL_PARAMS); 110 return NULL; 111} 112 113/* 114 * takes the message, and returns the I18N string for the message. 115 */ 116char * 117CompComment::compcom_format (int index, compmsg *msg, int &visible) 118{ 119 compmsg *p = msgs + index; 120 msg->instaddr = elf->decode (p->instaddr); 121 msg->lineno = elf->decode (p->lineno); 122 msg->msg_type = elf->decode (p->msg_type); 123 msg->nparam = elf->decode (p->nparam); 124 msg->param_index = elf->decode (p->param_index); 125 126 int vindex = ccm_vis_index (msg->msg_type); 127 char *mbuf; 128 Ccm_Primtype_t prim_ty; 129 visible = ccm_attrs[vindex].vis; 130 if (ccm_attrs[vindex].msg == NULL) 131 { 132 /* Print CCM_UNKNOWN message */ 133 int uindex = ccm_vis_index (CCM_UNKNOWN); 134 visible = ccm_attrs[uindex].vis; 135 return dbe_sprintf (ccm_attrs[uindex].msg, vindex); 136 } 137 138 /* 139 * Construct the output buffer based on the primitive types of the 140 * message parameters. 141 * 142 * Parameter lists have to be handled carefully -- the 1 parameter 143 * is built up of all the elements separated by ", ". 144 * 145 * Old way: Case by message format string. 146 */ 147 int *ind = params + msg->param_index; 148 int plist_idx = ccm_paramlist_index (msg->msg_type); 149 if (plist_idx <= 0) 150 { 151 /* No parameter list to handle; 0 parameters case is handled */ 152 153 enum 154 { 155 MAX_COMPCOM_ARGS = 13 156 }; 157 char *parms[MAX_COMPCOM_ARGS]; 158 if (msg->nparam >= MAX_COMPCOM_ARGS) 159 { 160 fprintf (stderr, 161 GTXT ("Warning: improperly formatted compiler commentary message (%d parameters >= %d);\n please report this bug against the compiler\n"), 162 msg->nparam, MAX_COMPCOM_ARGS); 163 return NULL; 164 } 165 for (int i = 0; i < MAX_COMPCOM_ARGS; i++) 166 parms[i] = NULL; // initialize array 167 int prm_cnt = ccm_num_params (msg->msg_type); 168 if (prm_cnt != msg->nparam) 169 { 170 fprintf (stderr, 171 GTXT ("Warning, improperly formatted compiler commentary message (parameter count mismatch = %d, param# = %d, msg_type = %x, `%s');\n please report this bug against the compiler\n"), 172 prm_cnt, msg->nparam, msg->msg_type, ccm_attrs[vindex].msg); 173 return NULL; 174 } 175 for (int i = 0; i < msg->nparam; i++) 176 { 177 /* Parameters in message-type numbered from '1' */ 178 prim_ty = ccm_param_primtype (msg->msg_type, i + 1); 179 if (prim_ty == CCM_PRIMTYPE_INTEGER) 180 { 181 unsigned long v = elf->decode (ind[i]); 182 parms[i] = (char*) v; 183 } 184 else if (prim_ty == CCM_PRIMTYPE_STRING) 185 { 186 char *fname = strs + elf->decode (ind[i]); 187 char *demName = get_demangle_name (fname); 188 parms[i] = demName ? demName : dbe_strdup (fname); 189 } 190 else if (prim_ty == CCM_PRIMTYPE_HEXSTRING) 191 parms[i] = dbe_sprintf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"), 192 (unsigned long long) msg->instaddr); 193 else 194 { 195 fprintf (stderr, 196 GTXT ("Warning, improperly formatted compiler commentary message (unexpected primitive type %d);\n please report this bug against the compiler\n"), 197 prim_ty); 198 // Dummy code to avoid compiler's warning: static function ccm_param_hightype is not used 199 Ccm_Hitype_t hightype = CCM_HITYPE_NONE; 200 if (hightype != CCM_HITYPE_NONE) 201 hightype = ccm_param_hightype (msg->msg_type, i + 1); 202 return NULL; 203 } 204 } 205 206 /* 207 * Must make sure to pass _ALL_ params; may pass more because 208 * the format won't access the 'extra' parameters if all the 209 * rules for messages have been followed. 210 */ 211 mbuf = dbe_sprintf (ccm_attrs[vindex].msg, parms[0], parms[1], parms[2], 212 parms[3], parms[4], parms[5], parms[6], parms[7], 213 parms[8], parms[9], parms[10], parms[11]); 214 // Cleanup allocated memory. 215 for (int i = 0; i < msg->nparam; i++) 216 { 217 prim_ty = ccm_param_primtype (msg->msg_type, i + 1); 218 if (prim_ty == CCM_PRIMTYPE_STRING || prim_ty == CCM_PRIMTYPE_HEXSTRING) 219 free (parms[i]); 220 } 221 } 222 else 223 { 224 /* 225 * Parameter list messages never have 0 parameters; the 226 * primitive type for the parameter list elements is always 227 * the same. And as of 22-Sep-2006, it was always 228 * CCM_PRIMTYPE_STRING. 229 * 230 * Account for different bases of parameter indices and 231 * 'nparam' count (1 and 0, respectively). 232 */ 233 char *parms[3]; 234 if (plist_idx > (int) ((sizeof (parms) / sizeof (char*)))) 235 { 236 fprintf (stderr, 237 GTXT ("Warning: improperly formatted compiler commentary message (msg->nparam=%d plist_idx=%d);\n please report this bug against the compiler\n"), 238 msg->nparam, plist_idx); 239 return NULL; 240 } 241 for (size_t i = 0; i < (sizeof (parms) / sizeof (char*)); i++) 242 parms[i] = NULL; // initialize array 243 244 StringBuilder sb; 245 prim_ty = ccm_param_primtype (msg->msg_type, plist_idx); 246 for (int i = plist_idx - 1; i < msg->nparam; i++) 247 { 248 if (i != plist_idx - 1) 249 sb.append (GTXT (", ")); 250 if (prim_ty == CCM_PRIMTYPE_INTEGER) 251 sb.append (elf->decode (ind[i])); 252 else if (prim_ty == CCM_PRIMTYPE_STRING) 253 { 254 char *fname = strs + elf->decode (ind[i]); 255 char *demName = get_demangle_name (fname); 256 if (demName) 257 { 258 sb.append (demName); 259 delete demName; 260 } 261 else 262 sb.append (fname); 263 } 264 else if (prim_ty == CCM_PRIMTYPE_HEXSTRING) 265 sb.appendf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"), 266 (unsigned long long) msg->instaddr); 267 } 268 parms[plist_idx - 1] = sb.toString (); 269 270 for (int i = 0; i < plist_idx - 1; i++) 271 { 272 prim_ty = ccm_param_primtype (msg->msg_type, i + 1); 273 if (prim_ty == CCM_PRIMTYPE_INTEGER) 274 { 275 unsigned long v = elf->decode (ind[i]); 276 parms[i] = (char*) v; 277 } 278 else if (prim_ty == CCM_PRIMTYPE_STRING) 279 { 280 char *fname = strs + elf->decode (ind[i]); 281 char *demName = get_demangle_name (fname); 282 parms[i] = demName ? demName : dbe_strdup (fname); 283 } 284 else if (prim_ty == CCM_PRIMTYPE_HEXSTRING) 285 parms[i] = dbe_sprintf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"), 286 (unsigned long long) msg->instaddr); 287 else 288 { 289 fprintf (stderr, 290 GTXT ("Warning, improperly formatted compiler commentary message (unexpected primitive type %d);\n please report this bug against the compiler\n"), 291 prim_ty); 292 return NULL; 293 } 294 } 295 296 /* 297 * We have reduced the parameter list to a single string (as 298 * the printf format specifier requires), so only have 299 * 'plist_idx' parameters. 300 */ 301 mbuf = dbe_sprintf (ccm_attrs[vindex].msg, parms[0], parms[1], parms[2]); 302 303 // Cleanup allocated memory. 304 free (parms[plist_idx - 1]); 305 for (int i = 0; i < plist_idx - 1; i++) 306 { 307 prim_ty = ccm_param_primtype (msg->msg_type, i + 1); 308 if (prim_ty == CCM_PRIMTYPE_STRING || prim_ty == CCM_PRIMTYPE_STRING) 309 free (parms[i]); 310 } 311 } 312 return mbuf; 313} 314