Compare commits

...

2 Commits

Author SHA1 Message Date
Walfred Tedeschi
3f772b1830 icc: allow code path for newer versions of icc.
Patch adds a version checkin for workaround an icc problem.
Icc problem was fixed in version 14, and gdb code has to
reflect the fix.
This patch contains a parser for the icc string version and conditional
workaround execution.  Adds also gdb self tests for the dwarf producers.

2017-06-28  Walfred Tedeschi  <walfred.tedeschi@intel.com>

gdb/ChangeLog:
	* dwarf2read.c (dwarf2_cu): Remove field producer_is_icc and add
	producer_is_icc_lt_14.
	(producer_is_icc_lt_14): New function.
	(check_producer): Add code for checking version of icc.
	(producer_is_icc): Move to dwarf2utils.
	(read_structure_type): Add a check for the later version of icc
	where the issue was still not fixed.
	(dwarf_producer_test): Add new unit test.
	(_initialize_dwarf2_read): Register the unit test.
	* dwarf2utils.c (producer_is_icc): New function.
	* dwarf2utils.h (producer_is_icc): Declaration of a new function.
	* dwarf2utils.c (_initialize_dwarf2utils): New function.

Change-Id: I70871846be4b70df477a63e700a52c41da81b92a
Signed-off-by: Walfred Tedeschi <walfred.tedeschi@intel.com>
2017-09-20 15:24:38 +02:00
Walfred Tedeschi
8bf5d94471 dwarf2read: move producers help functions to a dwarf specific file
This patch add new files to add dwarf reader utilities into it.
It is also a preparation path to add functions to detect the icc
version that produced a given compilation unit.

2017-09-18  Walfred Tedeschi  <walfred.tedeschi@intel.com>

	* Makefile.in (SFILES): Add dwarf2utils.c.
	(COMMON_OBS): Add dwarf2utils.o
	* amd64-tdep.c (dwarf2utils.h): Add new header.
	* dwarf2read.c (dwarf2utils.h): Add new header.
	* dwarf2utils.c: New file.
	* dwarf2utils.h: New file.
	* utils.c (producer_is_gcc, producer_is_gcc_ge_4): Move to
	dwarf2utils.c.
	* utils.h (producer_is_gcc, producer_is_gcc_ge_4): Move to
	dwarf2utils.h.
2017-09-20 16:15:02 +02:00
7 changed files with 294 additions and 71 deletions

View File

@@ -1088,6 +1088,7 @@ SFILES = \
dtrace-probe.c \
dummy-frame.c \
dwarf2-frame.c \
dwarf2utils.c \
dwarf2-frame-tailcall.c \
dwarf2expr.c \
dwarf2loc.c \
@@ -1707,6 +1708,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
dummy-frame.o \
dwarf2-frame.o \
dwarf2-frame-tailcall.o \
dwarf2utils.o \
dwarf2expr.o \
dwarf2loc.o \
dwarf2read.o \

View File

@@ -43,6 +43,7 @@
#include <algorithm>
#include "target-descriptions.h"
#include "arch/amd64.h"
#include "dwarf2utils.h"
#include "ax.h"
#include "ax-gdb.h"

View File

@@ -75,12 +75,15 @@
#include "common/underlying.h"
#include "common/byte-vector.h"
#include "filename-seen-cache.h"
#include "dwarf2utils.h"
#include <fcntl.h>
#include <sys/types.h>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
@@ -602,7 +605,7 @@ struct dwarf2_cu
unsigned int checked_producer : 1;
unsigned int producer_is_gxx_lt_4_6 : 1;
unsigned int producer_is_gcc_lt_4_3 : 1;
unsigned int producer_is_icc : 1;
unsigned int producer_is_icc_lt_14 : 1;
/* When set, the file that we're processing is known to have
debugging info for C++ namespaces. GCC 3.3.x did not produce
@@ -9347,6 +9350,19 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
&objfile->objfile_obstack);
}
/* For versions older than 14 ICC did not output the required DW_AT_declaration
on incomplete types, but gives them a size of zero. Starting on version 14
ICC is compatible with GCC. */
static int
producer_is_icc_lt_14 (struct dwarf2_cu *cu)
{
if (!cu->checked_producer)
check_producer (cu);
return cu->producer_is_icc_lt_14;
}
/* Check for possibly missing DW_AT_comp_dir with relative .debug_line
directory paths. GCC SVN r127613 (new option -fdebug-prefix-map) fixed
this, it was first present in GCC release 4.3.0. */
@@ -12828,6 +12844,9 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
}
}
/* Check whether the producer field indicates either of GCC < 4.6, or the
Intel C/C++ compiler, and cache the result in CU. */
@@ -12852,8 +12871,10 @@ check_producer (struct dwarf2_cu *cu)
cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
}
else if (startswith (cu->producer, "Intel(R) C"))
cu->producer_is_icc = 1;
else if (producer_is_icc (cu->producer, &major, &minor))
{
cu->producer_is_icc_lt_14 = major < 14 ;
}
else
{
/* For other non-GCC compilers, expect their behavior is DWARF version
@@ -13594,17 +13615,6 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
smash_to_methodptr_type (type, new_type);
}
/* Return non-zero if the CU's PRODUCER string matches the Intel C/C++ compiler
(icc). */
static int
producer_is_icc (struct dwarf2_cu *cu)
{
if (!cu->checked_producer)
check_producer (cu);
return cu->producer_is_icc;
}
/* Called when we find the DIE that starts a structure or union scope
(definition) to create a type for the structure or union. Fill in
@@ -13710,7 +13720,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
TYPE_LENGTH (type) = 0;
}
if (producer_is_icc (cu) && (TYPE_LENGTH (type) == 0))
if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
{
/* ICC does not output the required DW_AT_declaration
on incomplete types, but gives them a size of zero. */

235
gdb/dwarf2utils.c Normal file
View File

@@ -0,0 +1,235 @@
/* DWARF 2 debugging format utils for GDB.
This file is part of GDB.
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 of the License, 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, see <http://www.gnu.org/licenses/>. */
/* Check for GCC >= 4.x according to the symtab->producer string. Return minor
version (x) of 4.x in such case. If it is not GCC or it is GCC older than
4.x return -1. If it is GCC 5.x or higher return INT_MAX. */
#include "config.h"
#include "dwarf2utils.h"
#include "stdio.h"
#include "string.h"
#include "defs.h"
#include "dyn-string.h"
#include <ctype.h>
#include "common/common-types.h"
#include "common/common-exceptions.h"
#include "common/common-utils.h"
#if defined GDB_SELF_TEST
#include "selftest.h"
#endif
#include "utils.h"
int
producer_is_gcc_ge_4 (const char *producer)
{
int major, minor;
if (! producer_is_gcc (producer, &major, &minor))
return -1;
if (major < 4)
return -1;
if (major > 4)
return INT_MAX;
return minor;
}
/* Returns nonzero if the given PRODUCER string is GCC and sets the MAJOR
and MINOR versions when not NULL. Returns zero if the given PRODUCER
is NULL or it isn't GCC. */
int
producer_is_gcc (const char *producer, int *major, int *minor)
{
const char *cs;
if (producer != NULL && startswith (producer, "GNU "))
{
int maj, min;
if (major == NULL)
major = &maj;
if (minor == NULL)
minor = &min;
/* Skip any identifier after "GNU " - such as "C11" "C++" or "Java".
A full producer string might look like:
"GNU C 4.7.2"
"GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
"GNU C++14 5.0.0 20150123 (experimental)"
*/
cs = &producer[strlen ("GNU ")];
while (*cs && !isspace (*cs))
cs++;
if (*cs && isspace (*cs))
cs++;
if (sscanf (cs, "%d.%d", major, minor) == 2)
return 1;
}
/* Not recognized as GCC. */
return 0;
}
/* Returns nonzero if the given PRODUCER string is Intel or zero
otherwise. Sets the MAJOR and MINOR versions when not NULL.
Internal and external versions have to be taken into account.
Before a public release string for the PRODUCER is slightly
different than the public one. Internal releases have mainly
a major release number and 0 as minor release. External
releases have 4 fields, 3 of them are not 0 and only two
are of interest, major and update.
Examples are:
Public release:
"Intel(R) Fortran Intel(R) 64 Compiler XE for applications
running on Intel(R) 64, Version 14.0.1.074 Build 20130716";
"Intel(R) C++ Intel(R) 64 Compiler XE for applications
running on Intel(R) 64, Version 14.0.1.074 Build 20130716";
Internal releases:
"Intel(R) C++ Intel(R) 64 Compiler for applications
running on Intel(R) 64, Version 18.0 Beta ....". */
bool
producer_is_icc (const char *producer, int *major, int *minor)
{
if (producer == NULL || !startswith (producer, "Intel(R)"))
return 0;
/* Preparing the used fields. */
int maj, min;
if (major == NULL)
major = &maj;
if (minor == NULL)
minor = &min;
*minor = 0;
*major = 0;
/* Consumes the string till a "Version" is found. */
const char *cs = strstr(producer, "Version");
cs = skip_to_space (cs);
int intermediate = 0;
int nof = sscanf (cs, "%d.%d.%d.%*d", major, &intermediate, minor);
/* Internal versions are represented only as MAJOR.MINOR, whereas
minor is usually 0.
Public versions have 4 fields as described with the command above. */
if (nof == 3)
return TRUE;
if (nof == 2)
{
*minor = intermediate;
return TRUE;
}
static bool warning_printed = FALSE;
/* Not recognized as Intel, let user know. */
if (warning_printed == FALSE)
{
warning (_("Could not recognize version of Intel Compiler in:%s"), producer);
warning_printed = TRUE;
}
return FALSE;
}
#if defined GDB_SELF_TEST
namespace selftests {
namespace dwarf2utils {
static void
dwarf_producer_test ()
{
int major = 0, minor = 0;
const char *extern_f_14_1 = "Intel(R) Fortran Intel(R) 64 Compiler \
XE for applications running on Intel(R) 64, Version \
14.0.1.074 Build 20130716";
bool retval = producer_is_icc (extern_f_14_1, &major, &minor);
SELF_CHECK (retval == 1 && major == 14 && minor == 1);
retval = producer_is_gcc (extern_f_14_1, &major, &minor);
SELF_CHECK (retval == 0);
const char *intern_f_14 = "Intel(R) Fortran Intel(R) 64 Compiler \
XE for applications running on Intel(R) 64, Version \
14.0";
major = 0;
minor = 0;
retval = producer_is_icc (intern_f_14, &major, &minor);
SELF_CHECK (retval == 1 && major == 14 && minor == 0);
retval = producer_is_gcc (intern_f_14, &major, &minor);
SELF_CHECK (retval == 0);
const char *intern_c_14 = "Intel(R) C++ Intel(R) 64 Compiler \
XE for applications running on Intel(R) 64, Version \
14.0";
major = 0;
minor = 0;
retval = producer_is_icc (intern_c_14, &major, &minor);
SELF_CHECK (retval == 1 && major == 14 && minor == 0);
retval = producer_is_gcc (intern_c_14, &major, &minor);
SELF_CHECK (retval == 0);
const char *intern_c_18 = "Intel(R) C++ Intel(R) 64 Compiler \
for applications running on Intel(R) 64, Version 18.0 Beta";
major = 0;
minor = 0;
retval = producer_is_icc (intern_c_18, &major, &minor);
SELF_CHECK (retval == 1 && major == 18 && minor == 0);
const char *gnu = "GNU C 4.7.2";
major = 0;
minor = 0;
retval = producer_is_icc (gnu, &major, &minor);
SELF_CHECK (retval == 0);
retval = producer_is_gcc (gnu, &major, &minor);
SELF_CHECK (retval == 1 && major == 4 && minor == 7);
const char *gnu_exp ="GNU C++14 5.0.0 20150123 (experimental)";
major = 0;
minor = 0;
retval = producer_is_icc (gnu_exp, &major, &minor);
SELF_CHECK (retval == 0);
retval = producer_is_gcc (gnu_exp, &major, &minor);
SELF_CHECK (retval == 1 && major == 5 && minor == 0);
}
}
}
#endif
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_dwarf2utils;
void
_initialize_dwarf2utils (void)
{
#if defined GDB_SELF_TEST
selftests::register_test (selftests::dwarf2utils::dwarf_producer_test);
#endif
}

31
gdb/dwarf2utils.h Normal file
View File

@@ -0,0 +1,31 @@
/* DWARF 2 debugging format utils for GDB.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of GDB.
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 of the License, 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, see <http://www.gnu.org/licenses/>. */
#ifndef DWARF2UTILS_H
#define DWARF2UTILS_H
/* See documentation in the utils.c file. */
extern int producer_is_gcc_ge_4 (const char *producer);
/* See documentation in the utils.c file. */
extern int producer_is_gcc (const char *producer, int *major, int *minor);
/* See documentation in the utils.c file. */
extern bool producer_is_icc (const char *producer, int *major, int *minor);
#endif

View File

@@ -2944,60 +2944,7 @@ make_bpstat_clear_actions_cleanup (void)
return make_cleanup (do_bpstat_clear_actions_cleanup, NULL);
}
/* Check for GCC >= 4.x according to the symtab->producer string. Return minor
version (x) of 4.x in such case. If it is not GCC or it is GCC older than
4.x return -1. If it is GCC 5.x or higher return INT_MAX. */
int
producer_is_gcc_ge_4 (const char *producer)
{
int major, minor;
if (! producer_is_gcc (producer, &major, &minor))
return -1;
if (major < 4)
return -1;
if (major > 4)
return INT_MAX;
return minor;
}
/* Returns nonzero if the given PRODUCER string is GCC and sets the MAJOR
and MINOR versions when not NULL. Returns zero if the given PRODUCER
is NULL or it isn't GCC. */
int
producer_is_gcc (const char *producer, int *major, int *minor)
{
const char *cs;
if (producer != NULL && startswith (producer, "GNU "))
{
int maj, min;
if (major == NULL)
major = &maj;
if (minor == NULL)
minor = &min;
/* Skip any identifier after "GNU " - such as "C11" or "C++".
A full producer string might look like:
"GNU C 4.7.2"
"GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
"GNU C++14 5.0.0 20150123 (experimental)"
*/
cs = &producer[strlen ("GNU ")];
while (*cs && !isspace (*cs))
cs++;
if (*cs && isspace (*cs))
cs++;
if (sscanf (cs, "%d.%d", major, minor) == 2)
return 1;
}
/* Not recognized as GCC. */
return 0;
}
/* Helper for make_cleanup_free_char_ptr_vec. */

View File

@@ -442,9 +442,6 @@ void dummy_obstack_deallocate (void *object, void *data);
extern pid_t wait_to_die_with_timeout (pid_t pid, int *status, int timeout);
#endif
extern int producer_is_gcc_ge_4 (const char *producer);
extern int producer_is_gcc (const char *producer, int *major, int *minor);
extern int myread (int, char *, int);
/* Ensure that V is aligned to an N byte boundary (B's assumed to be a