mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
libctf: dump CTF array dimensions in the right order
Before GCC PR114186, all looked good in the land of multidimensional arrays: you wrote int a[5][10]; and ctf_type_aname() et al would print it as int [5][10] Unfortunately this was two bugs in one. GCC was emitting the array as if it were int a[10][5], i.e. as this: a -> [10] -> [5] -> int rather than a -> [5] -> [10] -> int as it should be. libctf was hiding this by printing them in the wrong order, concealing the bug from anyone using objdump --ctf or anything but actual type graph traversal. Once this was fixed for GCC, the bug was visible in libctf: multidimensional arrays were printed backwards! (But this is just a print-time bug: the underlying bug, that something traversing the type graph would see the array in backwards order, was fixed by the fix to GCC.) Fix this libctf bug, printing the arrays the right way round. In a possibly futile attempt to retain some vestige of backwards compatibility, introduce a new bug-compat flag CTF_F_ARRNELEMS, which, if on, indicates that PR114186 is fixed and GCC is emitting array elements the right way round. (Unfortunately, the fix went in without this flag, so some GCCs will still emit CTF that will cause libctf to print them wrong, even with this fix -- but it's no wronger than it was before, and new GCC and new binutils, as well as GCC older than any fix for PR114186 and new binutils, will print things properly. Someone traversing the type graph will see things right after the GCC fix, wrong before it, and there isn't really any reliable way to tell which you have, though if CTF_F_ARRNELEMS is set, you definitely have a fixed GCC. The test checks for this, but it's not something we expect actual users to ever do -- CTF dict flags are an internal implementation detail with no user-visible API for a reason.) [nca: log message, test compat with older compilers] include/ * ctf.h (CTF_F_ARRNELEMS): New bug-compat flag. (CTF_F_MAX): Adjust. libctf/ PR libctf/32161 * ctf-decl.c (ctf_decl_push): Prepend if this is an array and the bug-compat flag is set. * ctf-dump.c (ctf_dump_header): Dump the new bug-compat flag. * testsuite/libctf-lookup/multidim-array*: New test.
This commit is contained in:
committed by
Nick Alcock
parent
572b0825c7
commit
47111cfd4f
@@ -213,8 +213,9 @@ typedef struct ctf_header
|
||||
#define CTF_F_NEWFUNCINFO 0x2 /* New v3 func info section format. */
|
||||
#define CTF_F_IDXSORTED 0x4 /* Index sections already sorted. */
|
||||
#define CTF_F_DYNSTR 0x8 /* Strings come from .dynstr. */
|
||||
#define CTF_F_ARRNELEMS 0x10 /* Array elems no longer reversed. */
|
||||
#define CTF_F_MAX (CTF_F_COMPRESS | CTF_F_NEWFUNCINFO | CTF_F_IDXSORTED \
|
||||
| CTF_F_DYNSTR)
|
||||
| CTF_F_DYNSTR | CTF_F_ARRNELEMS)
|
||||
|
||||
typedef struct ctf_lblent
|
||||
{
|
||||
|
||||
@@ -154,9 +154,12 @@ ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
|
||||
cd->cd_qualp = prec;
|
||||
|
||||
/* By convention qualifiers of base types precede the type specifier (e.g.
|
||||
const int vs. int const) even though the two forms are equivalent. */
|
||||
const int vs. int const) even though the two forms are equivalent.
|
||||
As of gcc-14.2.0, arrays must also be prepended in order to dump with the
|
||||
dimensions properly ordered. */
|
||||
|
||||
if (is_qual && prec == CTF_PREC_BASE)
|
||||
if ((is_qual && prec == CTF_PREC_BASE) || ((kind == CTF_K_ARRAY) &&
|
||||
(fp->ctf_openflags & (CTF_F_ARRNELEMS))))
|
||||
ctf_list_prepend (&cd->cd_nodes[prec], cdp);
|
||||
else
|
||||
ctf_list_append (&cd->cd_nodes[prec], cdp);
|
||||
|
||||
@@ -326,7 +326,7 @@ ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
|
||||
|
||||
if (fp->ctf_openflags > 0)
|
||||
{
|
||||
if (asprintf (&flagstr, "%s%s%s%s%s%s%s",
|
||||
if (asprintf (&flagstr, "%s%s%s%s%s%s%s%s%s",
|
||||
fp->ctf_openflags & CTF_F_COMPRESS
|
||||
? "CTF_F_COMPRESS": "",
|
||||
(fp->ctf_openflags & CTF_F_COMPRESS)
|
||||
@@ -343,6 +343,12 @@ ctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state)
|
||||
&& (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
|
||||
| CTF_F_IDXSORTED))
|
||||
? ", " : "",
|
||||
fp->ctf_openflags & CTF_F_ARRNELEMS
|
||||
? "CTF_F_ARRNELEMS" : "",
|
||||
fp->ctf_openflags & (CTF_F_ARRNELEMS)
|
||||
&& (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO
|
||||
| CTF_F_IDXSORTED | CTF_F_ARRNELEMS))
|
||||
? ", " : "",
|
||||
fp->ctf_openflags & CTF_F_DYNSTR
|
||||
? "CTF_F_DYNSTR" : "") < 0)
|
||||
goto err;
|
||||
|
||||
3
libctf/testsuite/libctf-lookup/multidim-array-ctf.c
Normal file
3
libctf/testsuite/libctf-lookup/multidim-array-ctf.c
Normal file
@@ -0,0 +1,3 @@
|
||||
int a[3][5][9];
|
||||
int b[1][2];
|
||||
|
||||
71
libctf/testsuite/libctf-lookup/multidim-array.c
Normal file
71
libctf/testsuite/libctf-lookup/multidim-array.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <ctf-api.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ctf_archive_t *ctf;
|
||||
ctf_dict_t *fp;
|
||||
int err;
|
||||
ctf_dump_state_t *dump_state = NULL;
|
||||
char *dumpstr;
|
||||
ctf_next_t *it = NULL;
|
||||
ctf_id_t type;
|
||||
int flagged = 0;
|
||||
|
||||
if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
|
||||
goto open_err;
|
||||
if ((fp = ctf_dict_open (ctf, NULL, &err)) == NULL)
|
||||
goto open_err;
|
||||
|
||||
/* First, check for signs that the compiler is fixed but not emitting the
|
||||
relevant flag yet. This combination is not expected to work right. */
|
||||
|
||||
while ((dumpstr = ctf_dump (fp, &dump_state, CTF_SECT_HEADER,
|
||||
NULL, NULL)) != NULL)
|
||||
{
|
||||
if (strstr (dumpstr, "CTF_F_ARRNELEMS") != NULL)
|
||||
flagged = 1;
|
||||
free (dumpstr);
|
||||
}
|
||||
|
||||
if (!flagged)
|
||||
{
|
||||
ctf_arinfo_t ar;
|
||||
|
||||
if ((type = ctf_lookup_by_symbol_name (fp, "a")) == CTF_ERR)
|
||||
goto unexpected;
|
||||
|
||||
if (ctf_array_info (fp, type, &ar) < 0)
|
||||
goto unexpected;
|
||||
|
||||
if (ar.ctr_nelems == 3)
|
||||
{
|
||||
fprintf (stderr, "UNSUPPORTED: compiler has GCC PR114186 fixed but "
|
||||
"no indicative flag\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check for the actual bug. */
|
||||
|
||||
while ((type = ctf_type_next (fp, &it, NULL, 1)) != -1)
|
||||
printf ("%s\n", ctf_type_aname (fp, type));
|
||||
|
||||
ctf_dict_close (fp);
|
||||
ctf_close (ctf);
|
||||
|
||||
return 0;
|
||||
|
||||
open_err:
|
||||
fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
|
||||
return 1;
|
||||
|
||||
unexpected:
|
||||
fprintf (stderr, "Cannot look up symbol to determine compiler bugginess: %s\n",
|
||||
ctf_errmsg (ctf_errno (fp)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
9
libctf/testsuite/libctf-lookup/multidim-array.lk
Normal file
9
libctf/testsuite/libctf-lookup/multidim-array.lk
Normal file
@@ -0,0 +1,9 @@
|
||||
# source: multidim-array-ctf.c
|
||||
int
|
||||
long unsigned int
|
||||
int \[9\]
|
||||
int \[5\]\[9\]
|
||||
int \[3\]\[5\]\[9\]
|
||||
int \[2\]
|
||||
int \[1\]\[2\]
|
||||
|
||||
Reference in New Issue
Block a user