forked from Imagelibrary/binutils-gdb
Compare commits
2 Commits
binutils-2
...
users/wted
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f772b1830 | ||
|
|
8bf5d94471 |
@@ -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 \
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <algorithm>
|
||||
#include "target-descriptions.h"
|
||||
#include "arch/amd64.h"
|
||||
#include "dwarf2utils.h"
|
||||
#include "ax.h"
|
||||
#include "ax-gdb.h"
|
||||
|
||||
|
||||
@@ -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
235
gdb/dwarf2utils.c
Normal 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
31
gdb/dwarf2utils.h
Normal 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
|
||||
53
gdb/utils.c
53
gdb/utils.c
@@ -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. */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user