mirror of
https://github.com/autc04/Retro68.git
synced 2024-06-08 04:29:46 +00:00
314 lines
10 KiB
C++
314 lines
10 KiB
C++
/* Copyright (C) 2021 Free Software Foundation, Inc.
|
|
Contributed by Oracle.
|
|
|
|
This file is part of GNU Binutils.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, 51 Franklin Street - Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <locale.h>
|
|
#include <sys/param.h>
|
|
|
|
#include "demangle.h"
|
|
#include "gp-defs.h"
|
|
#include "StringBuilder.h"
|
|
#include "CompCom.h"
|
|
#include "Elf.h"
|
|
#include "util.h"
|
|
#include "i18n.h"
|
|
#include "comp_com.c"
|
|
|
|
CompComment::CompComment (Elf *_elf, int _compcom)
|
|
{
|
|
elf = _elf;
|
|
compcom = _compcom;
|
|
elf_cls = elf->elf_getclass ();
|
|
}
|
|
|
|
CompComment::~CompComment () { }
|
|
|
|
int
|
|
CompComment::get_align (int64_t offset, int align)
|
|
{
|
|
int val = (int) (offset % align);
|
|
if (val)
|
|
val = align - val;
|
|
return val;
|
|
}
|
|
|
|
/*
|
|
* Preprocesses the header structure, builds a table of messages with the line
|
|
* numbers, PCoffsets, original index, and compmsg pointer for each message.
|
|
* If the show_bits field is not in the message, this routine would fill it in
|
|
* from the mapping from COMPMSG_ID
|
|
*/
|
|
int
|
|
CompComment::compcom_open (CheckSrcName check_src)
|
|
{
|
|
if (check_src == NULL)
|
|
return 0;
|
|
Elf_Data *data = elf->elf_getdata (compcom);
|
|
uint64_t b_offset = data->d_off;
|
|
if (get_align (b_offset, 4)) // not align 4
|
|
return 0;
|
|
char *CommData = (char *) data->d_buf;
|
|
uint64_t offset = b_offset;
|
|
for (uint64_t e_offset = b_offset + data->d_size; offset < e_offset;)
|
|
{
|
|
offset += get_align (offset, (int) data->d_align);
|
|
if (offset >= e_offset)
|
|
return 0;
|
|
compcomhdr *hdr = (compcomhdr *) (CommData + (offset - b_offset));
|
|
int hdr_msgcount = elf->decode (hdr->msgcount);
|
|
int hdr_srcname = elf->decode (hdr->srcname);
|
|
int hdr_stringlen = elf->decode (hdr->stringlen);
|
|
int hdr_paramcount = elf->decode (hdr->paramcount);
|
|
size_t length = sizeof (compcomhdr) + hdr_msgcount * sizeof (compmsg) +
|
|
hdr_paramcount * sizeof (int32_t);
|
|
if (offset + length + hdr_stringlen > e_offset || hdr_srcname < 0
|
|
|| hdr_srcname >= hdr_stringlen)
|
|
return 0;
|
|
|
|
// check source file
|
|
char *src_name = (char *) (((char*) hdr) + length + hdr_srcname);
|
|
if (check_src (src_name))
|
|
{
|
|
msgs = (compmsg *) (((char *) hdr) + sizeof (compcomhdr));
|
|
params = (int32_t *) ((char *) msgs + hdr_msgcount * sizeof (compmsg));
|
|
strs = (char *) ((char *) params + hdr_paramcount * sizeof (int32_t));
|
|
|
|
// initialize the I18N/L10N strings & set the visible table
|
|
ccm_vis_init ();
|
|
return hdr_msgcount;
|
|
}
|
|
offset += (length + hdr_stringlen);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
CompComment::get_demangle_name (char *fname)
|
|
{
|
|
if (*fname == '_')
|
|
return cplus_demangle (fname, DMGL_PARAMS);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* takes the message, and returns the I18N string for the message.
|
|
*/
|
|
char *
|
|
CompComment::compcom_format (int index, compmsg *msg, int &visible)
|
|
{
|
|
compmsg *p = msgs + index;
|
|
msg->instaddr = elf->decode (p->instaddr);
|
|
msg->lineno = elf->decode (p->lineno);
|
|
msg->msg_type = elf->decode (p->msg_type);
|
|
msg->nparam = elf->decode (p->nparam);
|
|
msg->param_index = elf->decode (p->param_index);
|
|
|
|
int vindex = ccm_vis_index (msg->msg_type);
|
|
char *mbuf;
|
|
Ccm_Primtype_t prim_ty;
|
|
visible = ccm_attrs[vindex].vis;
|
|
if (ccm_attrs[vindex].msg == NULL)
|
|
{
|
|
/* Print CCM_UNKNOWN message */
|
|
int uindex = ccm_vis_index (CCM_UNKNOWN);
|
|
visible = ccm_attrs[uindex].vis;
|
|
return dbe_sprintf (ccm_attrs[uindex].msg, vindex);
|
|
}
|
|
|
|
/*
|
|
* Construct the output buffer based on the primitive types of the
|
|
* message parameters.
|
|
*
|
|
* Parameter lists have to be handled carefully -- the 1 parameter
|
|
* is built up of all the elements separated by ", ".
|
|
*
|
|
* Old way: Case by message format string.
|
|
*/
|
|
int *ind = params + msg->param_index;
|
|
int plist_idx = ccm_paramlist_index (msg->msg_type);
|
|
if (plist_idx <= 0)
|
|
{
|
|
/* No parameter list to handle; 0 parameters case is handled */
|
|
|
|
enum
|
|
{
|
|
MAX_COMPCOM_ARGS = 13
|
|
};
|
|
char *parms[MAX_COMPCOM_ARGS];
|
|
if (msg->nparam >= MAX_COMPCOM_ARGS)
|
|
{
|
|
fprintf (stderr,
|
|
GTXT ("Warning: improperly formatted compiler commentary message (%d parameters >= %d);\n please report this bug against the compiler\n"),
|
|
msg->nparam, MAX_COMPCOM_ARGS);
|
|
return NULL;
|
|
}
|
|
for (int i = 0; i < MAX_COMPCOM_ARGS; i++)
|
|
parms[i] = NULL; // initialize array
|
|
int prm_cnt = ccm_num_params (msg->msg_type);
|
|
if (prm_cnt != msg->nparam)
|
|
{
|
|
fprintf (stderr,
|
|
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"),
|
|
prm_cnt, msg->nparam, msg->msg_type, ccm_attrs[vindex].msg);
|
|
return NULL;
|
|
}
|
|
for (int i = 0; i < msg->nparam; i++)
|
|
{
|
|
/* Parameters in message-type numbered from '1' */
|
|
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
|
if (prim_ty == CCM_PRIMTYPE_INTEGER)
|
|
{
|
|
unsigned long v = elf->decode (ind[i]);
|
|
parms[i] = (char*) v;
|
|
}
|
|
else if (prim_ty == CCM_PRIMTYPE_STRING)
|
|
{
|
|
char *fname = strs + elf->decode (ind[i]);
|
|
char *demName = get_demangle_name (fname);
|
|
parms[i] = demName ? demName : dbe_strdup (fname);
|
|
}
|
|
else if (prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
|
parms[i] = dbe_sprintf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"),
|
|
(unsigned long long) msg->instaddr);
|
|
else
|
|
{
|
|
fprintf (stderr,
|
|
GTXT ("Warning, improperly formatted compiler commentary message (unexpected primitive type %d);\n please report this bug against the compiler\n"),
|
|
prim_ty);
|
|
// Dummy code to avoid compiler's warning: static function ccm_param_hightype is not used
|
|
Ccm_Hitype_t hightype = CCM_HITYPE_NONE;
|
|
if (hightype != CCM_HITYPE_NONE)
|
|
hightype = ccm_param_hightype (msg->msg_type, i + 1);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Must make sure to pass _ALL_ params; may pass more because
|
|
* the format won't access the 'extra' parameters if all the
|
|
* rules for messages have been followed.
|
|
*/
|
|
mbuf = dbe_sprintf (ccm_attrs[vindex].msg, parms[0], parms[1], parms[2],
|
|
parms[3], parms[4], parms[5], parms[6], parms[7],
|
|
parms[8], parms[9], parms[10], parms[11]);
|
|
// Cleanup allocated memory.
|
|
for (int i = 0; i < msg->nparam; i++)
|
|
{
|
|
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
|
if (prim_ty == CCM_PRIMTYPE_STRING || prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
|
free (parms[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Parameter list messages never have 0 parameters; the
|
|
* primitive type for the parameter list elements is always
|
|
* the same. And as of 22-Sep-2006, it was always
|
|
* CCM_PRIMTYPE_STRING.
|
|
*
|
|
* Account for different bases of parameter indices and
|
|
* 'nparam' count (1 and 0, respectively).
|
|
*/
|
|
char *parms[3];
|
|
if (plist_idx > (int) ((sizeof (parms) / sizeof (char*))))
|
|
{
|
|
fprintf (stderr,
|
|
GTXT ("Warning: improperly formatted compiler commentary message (msg->nparam=%d plist_idx=%d);\n please report this bug against the compiler\n"),
|
|
msg->nparam, plist_idx);
|
|
return NULL;
|
|
}
|
|
for (size_t i = 0; i < (sizeof (parms) / sizeof (char*)); i++)
|
|
parms[i] = NULL; // initialize array
|
|
|
|
StringBuilder sb;
|
|
prim_ty = ccm_param_primtype (msg->msg_type, plist_idx);
|
|
for (int i = plist_idx - 1; i < msg->nparam; i++)
|
|
{
|
|
if (i != plist_idx - 1)
|
|
sb.append (GTXT (", "));
|
|
if (prim_ty == CCM_PRIMTYPE_INTEGER)
|
|
sb.append (elf->decode (ind[i]));
|
|
else if (prim_ty == CCM_PRIMTYPE_STRING)
|
|
{
|
|
char *fname = strs + elf->decode (ind[i]);
|
|
char *demName = get_demangle_name (fname);
|
|
if (demName)
|
|
{
|
|
sb.append (demName);
|
|
delete demName;
|
|
}
|
|
else
|
|
sb.append (fname);
|
|
}
|
|
else if (prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
|
sb.appendf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"),
|
|
(unsigned long long) msg->instaddr);
|
|
}
|
|
parms[plist_idx - 1] = sb.toString ();
|
|
|
|
for (int i = 0; i < plist_idx - 1; i++)
|
|
{
|
|
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
|
if (prim_ty == CCM_PRIMTYPE_INTEGER)
|
|
{
|
|
unsigned long v = elf->decode (ind[i]);
|
|
parms[i] = (char*) v;
|
|
}
|
|
else if (prim_ty == CCM_PRIMTYPE_STRING)
|
|
{
|
|
char *fname = strs + elf->decode (ind[i]);
|
|
char *demName = get_demangle_name (fname);
|
|
parms[i] = demName ? demName : dbe_strdup (fname);
|
|
}
|
|
else if (prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
|
parms[i] = dbe_sprintf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"),
|
|
(unsigned long long) msg->instaddr);
|
|
else
|
|
{
|
|
fprintf (stderr,
|
|
GTXT ("Warning, improperly formatted compiler commentary message (unexpected primitive type %d);\n please report this bug against the compiler\n"),
|
|
prim_ty);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We have reduced the parameter list to a single string (as
|
|
* the printf format specifier requires), so only have
|
|
* 'plist_idx' parameters.
|
|
*/
|
|
mbuf = dbe_sprintf (ccm_attrs[vindex].msg, parms[0], parms[1], parms[2]);
|
|
|
|
// Cleanup allocated memory.
|
|
free (parms[plist_idx - 1]);
|
|
for (int i = 0; i < plist_idx - 1; i++)
|
|
{
|
|
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
|
if (prim_ty == CCM_PRIMTYPE_STRING || prim_ty == CCM_PRIMTYPE_STRING)
|
|
free (parms[i]);
|
|
}
|
|
}
|
|
return mbuf;
|
|
}
|