aboutsummaryrefslogtreecommitdiff
path: root/gprofng
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng')
-rw-r--r--gprofng/common/config.h.in18
-rw-r--r--gprofng/common/core_pcbe.c4
-rw-r--r--gprofng/common/cpu_frequency.h8
-rw-r--r--gprofng/common/cpuid.c12
-rw-r--r--gprofng/common/gp-defs.h4
-rw-r--r--gprofng/common/gp-experiment.h62
-rw-r--r--gprofng/common/hwctable.c8
-rwxr-xr-xgprofng/configure240
-rw-r--r--gprofng/configure.ac5
-rw-r--r--gprofng/doc/gprofng_ug.texi5
-rw-r--r--gprofng/libcollector/collector.c59
-rw-r--r--gprofng/libcollector/descendants.h14
-rw-r--r--gprofng/libcollector/envmgmt.c3
-rw-r--r--gprofng/libcollector/libcol-i386-dis.c2
-rw-r--r--gprofng/libcollector/libcol_util.h2
-rw-r--r--gprofng/libcollector/linetrace.c4
-rw-r--r--gprofng/src/CallStack.cc10
-rw-r--r--gprofng/src/DbeSession.cc11
-rw-r--r--gprofng/src/DbeSession.h1
-rw-r--r--gprofng/src/Disasm.cc17
-rw-r--r--gprofng/src/Disasm.h3
-rw-r--r--gprofng/src/Dwarf.cc299
-rw-r--r--gprofng/src/Dwarf.h5
-rw-r--r--gprofng/src/DwarfLib.cc618
-rw-r--r--gprofng/src/DwarfLib.h67
-rw-r--r--gprofng/src/Elf.cc225
-rw-r--r--gprofng/src/Elf.h42
-rw-r--r--gprofng/src/Experiment.cc12
-rw-r--r--gprofng/src/Experiment.h5
-rw-r--r--gprofng/src/LoadObject.cc101
-rw-r--r--gprofng/src/LoadObject.h11
-rw-r--r--gprofng/src/Makefile.am1
-rw-r--r--gprofng/src/Makefile.in4
-rw-r--r--gprofng/src/Module.cc2
-rw-r--r--gprofng/src/Stabs.cc353
-rw-r--r--gprofng/src/Stabs.h10
-rw-r--r--gprofng/src/Symbol.cc218
-rw-r--r--gprofng/src/Symbol.h84
-rw-r--r--gprofng/src/collect.h1
-rw-r--r--gprofng/src/envsets.cc10
-rw-r--r--gprofng/src/gp-archive.cc68
-rw-r--r--gprofng/src/gp-archive.h1
-rw-r--r--gprofng/src/gp-collect-app.cc5
-rw-r--r--gprofng/src/gp-display-src.cc3
-rw-r--r--gprofng/src/gp-display-text.cc3
-rw-r--r--gprofng/src/gprofng.cc3
-rw-r--r--gprofng/src/ipcio.cc5
47 files changed, 1578 insertions, 1070 deletions
diff --git a/gprofng/common/config.h.in b/gprofng/common/config.h.in
index f8484f2..5f2c127 100644
--- a/gprofng/common/config.h.in
+++ b/gprofng/common/config.h.in
@@ -1,11 +1,17 @@
/* common/config.h.in. Generated from configure.ac by autoheader. */
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
/* Enable debugging output. */
#undef DEBUG
/* Enable java profiling */
#undef GPROFNG_JAVA_PROFILING
+/* Define to 1 if you have the <asm/hwprobe.h> header file. */
+#undef HAVE_ASM_HWPROBE_H
+
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
@@ -109,6 +115,18 @@
/* Version number of package */
#undef VERSION
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
/* Define to 1 if on MINIX. */
#undef _MINIX
diff --git a/gprofng/common/core_pcbe.c b/gprofng/common/core_pcbe.c
index 107a994..14080ab 100644
--- a/gprofng/common/core_pcbe.c
+++ b/gprofng/common/core_pcbe.c
@@ -2759,7 +2759,7 @@ core_pcbe_init (void)
return -1;
}
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
/* No Architectural Performance Monitoring Leaf returned by CPUID */
if (get_cpuid_info ()->cpi_maxeax < 0xa)
return (-1);
@@ -2918,7 +2918,7 @@ core_pcbe_cpuref (void)
{
#if defined(__aarch64__) || defined(__riscv)
return "";
-#elif defined(__i386__) || defined(__x86_64)
+#elif defined(__i386__) || defined(__x86_64__)
switch (cpuid_getmodel ())
{
case 60: /* Haswell */
diff --git a/gprofng/common/cpu_frequency.h b/gprofng/common/cpu_frequency.h
index 2371863..c6979c4 100644
--- a/gprofng/common/cpu_frequency.h
+++ b/gprofng/common/cpu_frequency.h
@@ -41,7 +41,7 @@ extern "C"
#define COL_CPUFREQ_SCALING 0x0001
#define COL_CPUFREQ_TURBO 0x0002
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
// XXXX This is a rough table to estimate frequency increment due to intel turbo boost.
// CPU with different stepping and different core number have different turbo increment.
// It is used internally here, and is not implemented on SPARC
@@ -129,7 +129,7 @@ extern "C"
{
char temp[1024];
int cpu = -1;
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
int model = -1;
int family = -1;
#endif
@@ -140,7 +140,7 @@ extern "C"
char *val = strchr (temp, ':');
cpu = val ? atoi (val + 1) : -1;
}
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
else if (strncmp (temp, "model", strlen ("model")) == 0
&& strstr (temp, "name") == 0)
{
@@ -241,7 +241,7 @@ extern "C"
frequency_scaling = 1;
if (tmpmhz > 1000)
{
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
if (family == 6)
{
// test turbo mode
diff --git a/gprofng/common/cpuid.c b/gprofng/common/cpuid.c
index 9e45233..f9f9046 100644
--- a/gprofng/common/cpuid.c
+++ b/gprofng/common/cpuid.c
@@ -18,7 +18,7 @@
Foundation, 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
#include <cpuid.h> /* GCC-provided */
#elif defined(__aarch64__)
#if !defined(ATTRIBUTE_UNUSED)
@@ -48,8 +48,10 @@ __get_cpuid (unsigned int op ATTRIBUTE_UNUSED, unsigned int *eax,
#include <sched.h>
#include <sys/syscall.h>
#include <unistd.h>
+#ifdef HAVE_ASM_HWPROBE_H
#include <asm/hwprobe.h>
#endif
+#endif
/*
* Various routines to handle identification
@@ -91,7 +93,7 @@ typedef struct
} cpuid_info_t;
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
static uint_t
cpuid_vendorstr_to_vendorcode (char *vendorstr)
{
@@ -151,7 +153,7 @@ get_cpuid_info ()
Tprintf (DBG_LT0, "cpuid.c:%d read_cpuid_id() MIDR_EL1==0x%016x cpi_vendor=%d cpi_model=%d\n",
__LINE__, (unsigned int) reg, cpi->cpi_vendor, cpi->cpi_model);
-#elif defined(__i386__) || defined(__x86_64)
+#elif defined(__i386__) || defined(__x86_64__)
cpuid_regs_t regs;
my_cpuid (0, &regs);
cpi->cpi_maxeax = regs.eax;
@@ -188,7 +190,7 @@ get_cpuid_info ()
break;
}
#elif defined(__riscv)
- #ifndef __riscv_hwprobe
+ #if !defined(__riscv_hwprobe) || !defined(HAVE_ASM_HWPROBE_H)
cpi->cpi_vendor = 0;
cpi->cpi_family = 0;
cpi->cpi_model = 0;
@@ -208,7 +210,7 @@ get_cpuid_info ()
cpi->cpi_vendor = res.value;
cpi->cpi_family = 0;
cpi->cpi_model = 0;
- #endif
+ #endif
#endif
return cpi;
}
diff --git a/gprofng/common/gp-defs.h b/gprofng/common/gp-defs.h
index d6c9445..4b5d6fa 100644
--- a/gprofng/common/gp-defs.h
+++ b/gprofng/common/gp-defs.h
@@ -42,7 +42,7 @@
#if defined(sparc) || defined(__sparcv9)
#define ARCH_SPARC 1
-#elif defined(__i386__) || defined(__x86_64)
+#elif defined(__i386__) || defined(__x86_64__)
#define ARCH_Intel 1
#elif defined(__aarch64__)
#define ARCH_Aarch64 1
@@ -52,7 +52,7 @@
#error "Undefined platform"
#endif
-#if defined(__sparcv9) || defined(__x86_64) || defined(__aarch64__) || defined(__riscv)
+#if defined(__sparcv9) || defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)
#define WSIZE_64 1
#else
#define WSIZE_32 1
diff --git a/gprofng/common/gp-experiment.h b/gprofng/common/gp-experiment.h
index fab08f1..7abccdf 100644
--- a/gprofng/common/gp-experiment.h
+++ b/gprofng/common/gp-experiment.h
@@ -39,6 +39,23 @@
#define IS_DESC_EXPT(exptname) (strstr(exptname,DESCENDANT_EXPT_KEY) != NULL)
#define IS_FNDR_EXPT(exptname) (strstr(exptname,DESCENDANT_EXPT_KEY) == NULL)
+// environment variables that must be forwarded to libcollector
+#define SP_COLLECTOR_PARAMS "SP_COLLECTOR_PARAMS"
+#define SP_COLLECTOR_EXPNAME "SP_COLLECTOR_EXPNAME"
+#define SP_COLLECTOR_FOLLOW_SPEC "SP_COLLECTOR_FOLLOW_SPEC"
+#define SP_COLLECTOR_FOUNDER "SP_COLLECTOR_FOUNDER"
+#define SP_PRELOAD_STRINGS "SP_COLLECTOR_PRELOAD"
+#define LD_PRELOAD_STRINGS "LD_PRELOAD"
+#define SP_LIBPATH_STRINGS "SP_COLLECTOR_LIBRARY_PATH"
+#define LD_LIBPATH_STRINGS "LD_LIBRARY_PATH"
+#define JAVA_TOOL_OPTIONS "JAVA_TOOL_OPTIONS"
+#define COLLECTOR_JVMTI_OPTION "-agentlib:gp-collector"
+#define LIBGP_COLLECTOR "libgp-collector.so"
+#define GPROFNG_PRELOAD_LIBDIRS "GPROFNG_PRELOAD_LIBDIRS"
+#define SP_COLLECTOR_ORIGIN_COLLECT "SP_COLLECTOR_ORIGIN_COLLECT"
+#define SP_COLLECTOR_DEBUG "SP_COLLECTOR_DEBUG"
+#define SP_COLLECTOR_TRACELEVEL "SP_COLLECTOR_TRACELEVEL"
+
/* File name definitions */
#define SP_ARCHIVES_DIR "archives"
#define SP_ARCHIVE_LOG_FILE "archive.log"
@@ -86,70 +103,31 @@
/* records for log and loadobjects files */
/* note that these are in alphabetical order */
-#define SP_JCMD_ARCH "architecture"
#define SP_JCMD_ARCHIVE "archive_run"
-#define SP_JCMD_ARGLIST "arglist"
#define SP_JCMD_BLKSZ "blksz"
#define SP_JCMD_CERROR "cerror"
-#define SP_JCMD_CLASS_LOAD "class_load"
-#define SP_JCMD_CLASS_UNLOAD "class_unload"
#define SP_JCMD_COLLENV "collenv"
#define SP_JCMD_COMMENT "comment"
-#define SP_JCMD_CPUID "cpuid"
#define SP_JCMD_CWARN "cwarn"
-#define SP_JCMD_CWD "cwd"
-#define SP_JCMD_CVERSION "cversion"
-#define SP_JCMD_DATARACE "datarace"
-#define SP_JCMD_DEADLOCK "deadlock"
#define SP_JCMD_DELAYSTART "delay_start"
#define SP_JCMD_DESC_START "desc_start"
#define SP_JCMD_DESC_STARTED "desc_started"
-#define SP_JCMD_DVERSION "dversion"
#define SP_JCMD_EXEC_START "exec_start"
#define SP_JCMD_EXEC_ERROR "exec_error"
#define SP_JCMD_EXIT "exit"
-#define SP_JCMD_EXPT_DURATION "exp_duration"
#define SP_JCMD_FAKETIME "faketime"
-#define SP_JCMD_FN_LOAD "fn_load"
-#define SP_JCMD_FN_UNLOAD "fn_unload"
-#define SP_JCMD_FUN_MAP "fun_map"
-#define SP_JCMD_FUN_UNMAP "fun_unmap"
#define SP_JCMD_HEAPTRACE "heaptrace"
-#define SP_JCMD_HOSTNAME "hostname"
#define SP_JCMD_HWC_DEFAULT "hwc_default"
#define SP_JCMD_HW_COUNTER "hwcounter"
-#define SP_JCMD_HW_SIM_CTR "hwsimctr"
#define SP_JCMD_IOTRACE "iotrace"
-#define SP_JCMD_JCM_LOAD "jcm_load"
-#define SP_JCMD_JCM_UNLOAD "jcm_unload"
-#define SP_JCMD_JCM_MAP "jcm_map"
-#define SP_JCMD_JCM_UNMAP "jcm_unmap"
#define SP_JCMD_JTHREND "jthread_end"
#define SP_JCMD_JTHRSTART "jthread_start"
#define SP_JCMD_GCEND "gc_end"
#define SP_JCMD_GCSTART "gc_start"
#define SP_JCMD_JVERSION "jversion"
-//#define SP_JCMD_KPROFILE "kprofile" /* TBR */
#define SP_JCMD_LIMIT "limit"
#define SP_JCMD_LINETRACE "linetrace"
-#define SP_JCMD_LO_OPEN "lo_open"
-#define SP_JCMD_LO_CLOSE "lo_close"
-#define SP_JCMD_MOD_OPEN "mod_open"
-#define SP_JCMD_MPIEXP "MPIexperiment"
-#define SP_JCMD_MPI_NO_TRACE "MPI_no_trace"
-#define SP_JCMD_MPIOMPVER "mpi_openmpi_version"
-#define SP_JCMD_MPITRACEVER "mpi_trace_version"
-#define SP_JCMD_MPIPP "mpipp"
-#define SP_JCMD_MPIPPERR "mpipp_err"
-#define SP_JCMD_MPIPPWARN "mpipp_warn"
-#define SP_JCMD_MPISTATE "mpistate"
-#define SP_JCMD_MPITRACE "mpitrace" /* backwards compat only */
-#define SP_JCMD_MPVIEW "mpview"
-#define SP_JCMD_MSGTRACE "msgtrace"
#define SP_JCMD_NOIDLE "noidle"
-#define SP_JCMD_OMPTRACE "omptrace"
-#define SP_JCMD_OS "os"
-#define SP_JCMD_PAGESIZE "pagesize"
#define SP_JCMD_PAUSE "pause"
#define SP_JCMD_PAUSE_SIG "pause_signal"
#define SP_JCMD_PROFILE "profile"
@@ -158,21 +136,15 @@
#define SP_JCMD_SAMPLE "sample"
#define SP_JCMD_SAMPLE_PERIOD "sample_period"
#define SP_JCMD_SAMPLE_SIG "sample_signal"
-#define SP_JCMD_SEGMENT_MAP "seg_map"
-#define SP_JCMD_SEGMENT_UNMAP "seg_unmap"
#define SP_JCMD_SRCHPATH "search_path"
#define SP_JCMD_STACKBASE "stackbase"
-#define SP_JCMD_SUNPERF "sunperf"
#define SP_JCMD_SYNCTRACE "synctrace"
#define SP_JCMD_TERMINATE "terminate"
#define SP_JCMD_THREAD_PAUSE "thread_pause"
#define SP_JCMD_THREAD_RESUME "thread_resume"
-#define SP_JCMD_USERNAME "username"
#define SP_JCMD_VERSION "version"
-#define SP_JCMD_WSIZE "wsize"
/* strings naming memory-segments */
-#define SP_MAP_ANON "Anon"
#define SP_MAP_HEAP "Heap"
#define SP_MAP_STACK "Stack"
#define SP_MAP_SHMEM "SHMid"
diff --git a/gprofng/common/hwctable.c b/gprofng/common/hwctable.c
index 4b6f2a9..1ce365a 100644
--- a/gprofng/common/hwctable.c
+++ b/gprofng/common/hwctable.c
@@ -243,7 +243,7 @@ static Hwcentry papi_generic_list[] = {
{NULL, NULL, 0, NULL, 0, 0, 0, 0, ABST_NONE}
};
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
/* Kernel profiling pseudo-chip, OBSOLETE (To support 12.3 and earlier, TBR) */
static Hwcentry kproflist[] = {
{"kcycles", "kcycles", 0, STXT ("KCPU Cycles"), PRELOADS_5, 1, ABST_NONE},
@@ -1216,7 +1216,7 @@ static Hwcentry amd_15h[] = {
{"insts1", "EX_retired_instr_w_excp_intr", 1, NULL, PRELOADS_8, 0, ABST_NONE},
{NULL, NULL, 0, NULL, 0, 0, 0, 0, ABST_NONE}
};
-#endif /* __i386__ or __x86_64 */
+#endif /* __i386__ or __x86_64__ */
#define INIT_HWC(nm, mtr, cfg, ty) .name = (nm), .metric = (mtr), \
.config = (cfg), .type = ty, .use_perf_event_type = 1, \
@@ -1303,7 +1303,7 @@ static Hwcentry generic_list[] = {
{NULL, NULL, 0, NULL, 0, 0, 0, 0, ABST_NONE}
};
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
#include "hwc_amd_zen3.h"
#include "hwc_amd_zen4.h"
#include "hwc_intel_icelake.h"
@@ -1332,7 +1332,7 @@ typedef struct
* If the string is not formatted that way, -h hi and -h lo will fail
*/
static cpu_list_t cputabs[] = {
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
{CPC_PENTIUM_PRO_MMX, pentiumIIlist, {"insts", 0}},
{CPC_PENTIUM_PRO, pentiumIIIlist, {"insts", 0}},
{CPC_PENTIUM_4, pentium4, {"insts", 0}},
diff --git a/gprofng/configure b/gprofng/configure
index 3f40863..2f4e18c 100755
--- a/gprofng/configure
+++ b/gprofng/configure
@@ -15623,6 +15623,230 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Only expand once:
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
GPROFNG_LIBADD="-L../../libiberty -liberty"
if test "$enable_shared" = "yes"; then
@@ -16941,6 +17165,21 @@ fi
done
+# For riscv builds inside incomplete environments such as during intermediate
+# steps of cross toolchain building, or with outdated Linux headers.
+for ac_header in asm/hwprobe.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "asm/hwprobe.h" "ac_cv_header_asm_hwprobe_h" "$ac_includes_default"
+if test "x$ac_cv_header_asm_hwprobe_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_ASM_HWPROBE_H 1
+_ACEOF
+
+fi
+
+done
+
+
clock_gettime_link=
# At least for glibc, clock_gettime is in librt. But don't
# pull that in if it still doesn't give us the function we want. This
@@ -17145,6 +17384,7 @@ if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+
if test -z "${BUILD_COLLECTOR_TRUE}" && test -z "${BUILD_COLLECTOR_FALSE}"; then
as_fn_error $? "conditional \"BUILD_COLLECTOR\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/gprofng/configure.ac b/gprofng/configure.ac
index d7a2c38..deb3ed5 100644
--- a/gprofng/configure.ac
+++ b/gprofng/configure.ac
@@ -33,6 +33,7 @@ gl_PROG_BISON([BISON],[3.0.4])
AC_DISABLE_SHARED
LT_INIT
+AC_C_BIGENDIAN
GPROFNG_LIBADD="-L../../libiberty -liberty"
if test "$enable_shared" = "yes"; then
@@ -244,6 +245,10 @@ AC_SUBST(GPROFNG_CPPFLAGS, [${gprofng_cppflags}])
AC_CHECK_DECLS([basename])
AC_CHECK_FUNCS(clock_gettime strsignal)
+# For riscv builds inside incomplete environments such as during intermediate
+# steps of cross toolchain building, or with outdated Linux headers.
+AC_CHECK_HEADERS(asm/hwprobe.h)
+
clock_gettime_link=
# At least for glibc, clock_gettime is in librt. But don't
# pull that in if it still doesn't give us the function we want. This
diff --git a/gprofng/doc/gprofng_ug.texi b/gprofng/doc/gprofng_ug.texi
index 7147090..f23f7b3 100644
--- a/gprofng/doc/gprofng_ug.texi
+++ b/gprofng/doc/gprofng_ug.texi
@@ -310,9 +310,8 @@ Since there is no need to recompile, existing executables can be used
and the profile measures the behaviour of exactly the same executable that is
used in production runs.
-With sampling, one inherently profiles a different executable, because
-the calls to the instrumentation library may affect the compiler optimizations
-and run time behaviour.
+With tracing, one inherently profiles a different executable, because
+the calls to the instrumentation library may affect runtime behaviour.
@item
With sampling, there are very few restrictions on what can be profiled and
diff --git a/gprofng/libcollector/collector.c b/gprofng/libcollector/collector.c
index 8d978a6..3bb3fc3 100644
--- a/gprofng/libcollector/collector.c
+++ b/gprofng/libcollector/collector.c
@@ -182,11 +182,12 @@ static void
init_tracelevel ()
{
#if DEBUG
- char *s = CALL_UTIL (getenv)("SP_COLLECTOR_TRACELEVEL");
+ char *s = CALL_UTIL (getenv)(SP_COLLECTOR_TRACELEVEL);
if (s != NULL)
__collector_tracelevel = CALL_UTIL (atoi)(s);
- TprintfT (DBG_LT0, "collector: SP_COLLECTOR_TRACELEVEL=%d\n", __collector_tracelevel);
- s = CALL_UTIL (getenv)("SP_COLLECTOR_DEBUG");
+ TprintfT (DBG_LT0, "collector: %s=%d\n", SP_COLLECTOR_TRACELEVEL,
+ __collector_tracelevel);
+ s = CALL_UTIL (getenv)(SP_COLLECTOR_DEBUG);
if (s != NULL)
collector_debug_opt = CALL_UTIL (atoi)(s) & ~(SP_DUMP_TIME | SP_DUMP_FLAG);
#endif
@@ -239,21 +240,24 @@ collector_init ()
collector_module_init (get_collector_interface ());
/* determine experiment name */
- char *exp = CALL_UTIL (getenv)("SP_COLLECTOR_EXPNAME");
+ char *exp = CALL_UTIL (getenv)(SP_COLLECTOR_EXPNAME);
if ((exp == NULL) || (CALL_UTIL (strlen)(exp) == 0))
{
- TprintfT (DBG_LT0, "collector_init: SP_COLLECTOR_EXPNAME undefined - no experiment to start\n");
+ TprintfT (DBG_LT0, "collector_init: %s undefined. no experiment to start\n",
+ SP_COLLECTOR_EXPNAME);
/* not set -- no experiment to run */
return;
}
else
- TprintfT (DBG_LT1, "collector_init: found SP_COLLECTOR_EXPNAME = %s\n", exp);
+ TprintfT (DBG_LT1, "collector_init: found %s = %s\n",
+ SP_COLLECTOR_EXPNAME, exp);
/* determine the data descriptor for the experiment */
- char *params = CALL_UTIL (getenv)("SP_COLLECTOR_PARAMS");
+ char *params = CALL_UTIL (getenv)(SP_COLLECTOR_PARAMS);
if (params == NULL)
{
- TprintfT (0, "collector_init: SP_COLLECTOR_PARAMS undefined - no experiment to start\n");
+ TprintfT (0, "collector_init: %s undefined - no experiment to start\n",
+ SP_COLLECTOR_EXPNAME);
return;
}
@@ -494,7 +498,8 @@ __collector_open_experiment (const char *exp, const char *params, sp_origin_t or
return COL_ERROR_EXPOPEN;
}
__collector_start_time = collector_interface.getHiResTime ();
- TprintfT (DBG_LT1, "\n\t\t__collector_open_experiment(SP_COLLECTOR_EXPNAME=%s, params=%s, origin=%d); setting start_time\n",
+ TprintfT (DBG_LT1, "\n\t\t__collector_open_experiment(%s=%s, params=%s, "
+ "origin=%d); setting start_time\n", SP_COLLECTOR_EXPNAME,
exp, params, origin);
if (environ)
__collector_env_printall ("__collector_open_experiment", environ);
@@ -548,23 +553,20 @@ __collector_open_experiment (const char *exp, const char *params, sp_origin_t or
is_founder = getpid ();
if (origin != SP_ORIGIN_DBX_ATTACH)
{
- envar = CALL_UTIL (getenv)("SP_COLLECTOR_FOUNDER");
+ envar = CALL_UTIL (getenv)(SP_COLLECTOR_FOUNDER);
if (envar)
is_founder = CALL_UTIL (atoi)(envar);
if (is_founder != 0)
{
if (is_founder != getpid ())
{
- TprintfT (0, "__collector_open_experiment SP_COLLECTOR_FOUNDER=%d != pid(%d)\n",
- is_founder, getpid ());
- //CALL_UTIL(fprintf)(stderr, "__collector_open_experiment SP_COLLECTOR_FOUNDER=%d != pid(%d); not recording experiment\n",
- //is_founder, getpid() );
- //return COL_ERROR_UNEXP_FOUNDER;
+ TprintfT (0, "__collector_open_experiment %s=%d != pid(%d)\n",
+ SP_COLLECTOR_FOUNDER, is_founder, getpid ());
is_founder = 0; // Special case (CR 22917352)
}
/* clear FOUNDER for descendant experiments */
- TprintfT (0, "__collector_open_experiment setting SP_COLLECTOR_FOUNDER=0\n");
- CALL_UTIL (strlcpy)(buffer, "SP_COLLECTOR_FOUNDER=0", sizeof (buffer));
+ TprintfT (0, "__collector_open_experiment setting %s=0\n", SP_COLLECTOR_FOUNDER);
+ CALL_UTIL (snprintf)(buffer, sizeof (buffer), "%s=0", SP_COLLECTOR_FOUNDER);
CALL_UTIL (putenv)(buffer);
}
}
@@ -617,8 +619,10 @@ __collector_open_experiment (const char *exp, const char *params, sp_origin_t or
return COL_ERROR_BADDIR;
}
static char exp_name_env[MAXPATHLEN + 1];
- TprintfT (DBG_LT1, "collector_open_experiment: setting SP_COLLECTOR_EXPNAME to %s\n", __collector_exp_dir_name);
- CALL_UTIL (snprintf)(exp_name_env, sizeof (exp_name_env), "SP_COLLECTOR_EXPNAME=%s", __collector_exp_dir_name);
+ TprintfT (DBG_LT1, "collector_open_experiment: setting %s to %s\n",
+ SP_COLLECTOR_EXPNAME, __collector_exp_dir_name);
+ CALL_UTIL (snprintf)(exp_name_env, sizeof (exp_name_env), "%s=%s",
+ SP_COLLECTOR_EXPNAME, __collector_exp_dir_name);
CALL_UTIL (putenv)(exp_name_env);
}
/* Check that the name is that of a directory (new structure) */
@@ -1049,8 +1053,10 @@ collector_tail_init (const char *parent_exp_name)
if (collector_exp_dir_append_x (linenum, parent_exp_name) != 0)
return COL_ERROR_BADDIR;
static char exp_name_env[MAXPATHLEN + 1];
- CALL_UTIL (snprintf)(exp_name_env, sizeof (exp_name_env), "SP_COLLECTOR_EXPNAME=%s", __collector_exp_dir_name);
- TprintfT (DBG_LT1, "collector_tail_init: setting SP_COLLECTOR_EXPNAME to %s\n", __collector_exp_dir_name);
+ CALL_UTIL (snprintf)(exp_name_env, sizeof (exp_name_env), "%s=%s",
+ SP_COLLECTOR_EXPNAME, __collector_exp_dir_name);
+ TprintfT (DBG_LT1, "collector_tail_init: setting %s to %s\n",
+ SP_COLLECTOR_EXPNAME, __collector_exp_dir_name);
CALL_UTIL (putenv)(exp_name_env);
}
/* initialize the segments map and mmap interposition */
@@ -2045,8 +2051,15 @@ log_header_write (sp_origin_t origin)
{
long page_size = CALL_UTIL (sysconf)(_SC_PAGESIZE);
long npages = CALL_UTIL (sysconf)(_SC_PHYS_PAGES);
- __collector_log_write ("<system hostname=\"%s\" arch=\"%s\" os=\"%s %s\" pagesz=\"%ld\" npages=\"%ld\">\n",
- sysinfo.nodename, sysinfo.machine, sysinfo.sysname, sysinfo.release, page_size, npages);
+#ifdef WORDS_BIGENDIAN
+ int bigendian = 1;
+#else
+ int bigendian = 0;
+#endif
+ __collector_log_write ("<system hostname=\"%s\" arch=\"%s\" os=\"%s %s\" "
+ "pagesz=\"%ld\" npages=\"%ld\" bigendian=\"%d\">\n",
+ sysinfo.nodename, sysinfo.machine, sysinfo.sysname,
+ sysinfo.release, page_size, npages, bigendian);
}
//YXXX Updating this section? Check similar cut/paste code in:
diff --git a/gprofng/libcollector/descendants.h b/gprofng/libcollector/descendants.h
index 0148410..7d594b3 100644
--- a/gprofng/libcollector/descendants.h
+++ b/gprofng/libcollector/descendants.h
@@ -44,7 +44,6 @@ typedef enum
LM_TRACK_LINEAGE = 1, /* env vars preserved, recording */
} line_mode_t;
-extern line_mode_t line_mode;
extern int user_follow_mode;
extern int java_mode;
extern int dbg_current_mode; /* for debug only */
@@ -56,19 +55,6 @@ extern char **sp_env_backup;
#define PUSH_REENTRANCE(x) ((*(x))++)
#define POP_REENTRANCE(x) ((*(x))--)
-/* environment variables that must be forwarded to descendents */
-#define SP_COLLECTOR_PARAMS "SP_COLLECTOR_PARAMS"
-#define SP_COLLECTOR_EXPNAME "SP_COLLECTOR_EXPNAME"
-#define SP_COLLECTOR_FOLLOW_SPEC "SP_COLLECTOR_FOLLOW_SPEC"
-#define SP_COLLECTOR_FOUNDER "SP_COLLECTOR_FOUNDER"
-#define SP_PRELOAD_STRINGS "SP_COLLECTOR_PRELOAD"
-#define LD_PRELOAD_STRINGS "LD_PRELOAD"
-#define SP_LIBPATH_STRINGS "SP_COLLECTOR_LIBRARY_PATH"
-#define LD_LIBPATH_STRINGS "LD_LIBRARY_PATH"
-#define JAVA_TOOL_OPTIONS "JAVA_TOOL_OPTIONS"
-#define COLLECTOR_JVMTI_OPTION "-agentlib:gp-collector"
-
-extern int __collector_linetrace_shutdown_hwcs_6830763_XXXX;
extern void __collector_env_unset (char *envp[]);
extern void __collector_env_save_preloads ();
extern char ** __collector_env_backup ();
diff --git a/gprofng/libcollector/envmgmt.c b/gprofng/libcollector/envmgmt.c
index 0c3bea1..0a2add9 100644
--- a/gprofng/libcollector/envmgmt.c
+++ b/gprofng/libcollector/envmgmt.c
@@ -285,9 +285,6 @@ env_ld_preload_strip (char *envv)
for (int v = 0; SP_PRELOAD[v]; v++)
if (env_strip (envv, sp_preloads[v]))
return 0;
- if (line_mode != LM_CLOSED)
- TprintfT (DBG_LT2, "env_ld_preload_strip(): WARNING - could not strip SP_PRELOADS from '%s'\n",
- envv);
return -2;
}
diff --git a/gprofng/libcollector/libcol-i386-dis.c b/gprofng/libcollector/libcol-i386-dis.c
index 81ca366..15c91f7 100644
--- a/gprofng/libcollector/libcol-i386-dis.c
+++ b/gprofng/libcollector/libcol-i386-dis.c
@@ -18,7 +18,7 @@
Foundation, 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#if defined(__i386__) || defined(__x86_64)
+#if defined(__i386__) || defined(__x86_64__)
#include "opcodes/i386-dis.c"
#undef _
diff --git a/gprofng/libcollector/libcol_util.h b/gprofng/libcollector/libcol_util.h
index afe75f8..08e34a1 100644
--- a/gprofng/libcollector/libcol_util.h
+++ b/gprofng/libcollector/libcol_util.h
@@ -183,7 +183,7 @@ static __attribute__ ((always_inline)) inline void *
__collector_getpc ()
{
void *r;
-#if defined(__x86_64)
+#if defined(__x86_64__)
__asm__ __volatile__("lea (%%rip), %0" : "=r" (r));
#else
__asm__ __volatile__("call 1f \n"
diff --git a/gprofng/libcollector/linetrace.c b/gprofng/libcollector/linetrace.c
index 86d9955..0e3e7cd 100644
--- a/gprofng/libcollector/linetrace.c
+++ b/gprofng/libcollector/linetrace.c
@@ -37,10 +37,10 @@
#define LT_MAXNAMELEN 1024
#define LT_MAXPATHLEN 1024
-int __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0;
+static int __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0;
int dbg_current_mode = FOLLOW_NONE; /* for debug only */
unsigned line_key = COLLECTOR_TSD_INVALID_KEY;
-line_mode_t line_mode = LM_DORMANT;
+static line_mode_t line_mode = LM_DORMANT;
int user_follow_mode = FOLLOW_ON;
int java_mode = 0;
diff --git a/gprofng/src/CallStack.cc b/gprofng/src/CallStack.cc
index 6df4112..9a3a15d 100644
--- a/gprofng/src/CallStack.cc
+++ b/gprofng/src/CallStack.cc
@@ -527,14 +527,10 @@ CallStackP::add_stack (DataDescriptor *dDscr, long idx, FramePacket *frp,
Vaddr va = frp->getFromStack (index);
DbeInstr *cur_instr = experiment->map_Vaddr_to_PC (va, tstamp);
-#if ARCH(Intel)// TBR? FIXUP_XXX_SPARC_LINUX: switch should be on experiment ARCH, not dbe ARCH
// We need to adjust return addresses on intel
- // in order to attribute inclusive metrics to
- // proper call instructions.
- if (experiment->exp_maj_version <= 9)
- if (!leaf && cur_instr->addr != 0)
- cur_instr = cur_instr->func->find_dbeinstr (0, cur_instr->addr - 1);
-#endif
+ // in order to attribute inclusive metrics to proper instructions.
+ if (experiment->platform == Intel && cur_instr->addr != 0)
+ cur_instr = cur_instr->func->find_dbeinstr (0, cur_instr->addr - 1);
// Skip PC's from PLT, update leaf and state accordingly
if ((cur_instr->func->flags & FUNC_FLAG_PLT)
diff --git a/gprofng/src/DbeSession.cc b/gprofng/src/DbeSession.cc
index f3426ce..b0aa745 100644
--- a/gprofng/src/DbeSession.cc
+++ b/gprofng/src/DbeSession.cc
@@ -2017,6 +2017,17 @@ DbeSession::is_omp_available ()
}
bool
+DbeSession::is_bigendian ()
+{
+#ifdef WORDS_BIGENDIAN
+ return true;
+#else
+ return false;
+#endif
+
+}
+
+bool
DbeSession::has_java ()
{
int status_has_java = 0;
diff --git a/gprofng/src/DbeSession.h b/gprofng/src/DbeSession.h
index 5cbddae..7db0998 100644
--- a/gprofng/src/DbeSession.h
+++ b/gprofng/src/DbeSession.h
@@ -120,6 +120,7 @@ public:
bool is_timeline_available ();
bool is_ifreq_available ();
bool is_omp_available ();
+ static bool is_bigendian ();
bool has_java ();
bool has_ompavail ();
diff --git a/gprofng/src/Disasm.cc b/gprofng/src/Disasm.cc
index 42fb777..3ee50d7 100644
--- a/gprofng/src/Disasm.cc
+++ b/gprofng/src/Disasm.cc
@@ -50,19 +50,6 @@ struct DisContext
static const int MAX_DISASM_STR = 2048;
-Disasm::Disasm (char *fname)
-{
- dwin = NULL;
- dis_str = NULL;
- need_swap_endian = false;
- my_stabs = Stabs::NewStabs (fname, fname);
- if (my_stabs == NULL)
- return;
- stabs = my_stabs;
- platform = stabs->get_platform ();
- disasm_open ();
-}
-
Disasm::Disasm (Platform_t _platform, Stabs *_stabs)
{
dwin = NULL;
@@ -70,7 +57,6 @@ Disasm::Disasm (Platform_t _platform, Stabs *_stabs)
need_swap_endian = false;
stabs = _stabs;
platform = _platform;
- my_stabs = NULL;
disasm_open ();
}
@@ -263,7 +249,6 @@ Disasm::disasm_open ()
Disasm::~Disasm ()
{
- delete my_stabs;
delete dwin;
delete dis_str;
}
@@ -370,7 +355,7 @@ Disasm::get_funcname_in_plt (uint64_t pc)
{
if (stabs)
{
- Elf *elf = stabs->openElf (true);
+ Elf *elf = stabs->openElf (false);
if (elf)
return elf->get_funcname_in_plt (pc);
}
diff --git a/gprofng/src/Disasm.h b/gprofng/src/Disasm.h
index 0326b5c..3d7159d 100644
--- a/gprofng/src/Disasm.h
+++ b/gprofng/src/Disasm.h
@@ -31,7 +31,6 @@ enum Platform_t;
class Disasm
{
public:
- Disasm (char *fname);
Disasm (Platform_t _platform, Stabs *_stabs);
~Disasm ();
void remove_disasm_hndl (void *hndl);
@@ -59,7 +58,7 @@ private:
disassemble_info dis_info;
Data_window *dwin;
- Stabs *stabs, *my_stabs;
+ Stabs *stabs;
Platform_t platform;
char addr_fmt[32];
int hex_visible;
diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc
index a613c63..934ae44 100644
--- a/gprofng/src/Dwarf.cc
+++ b/gprofng/src/Dwarf.cc
@@ -29,6 +29,7 @@
#include "LoadObject.h"
#include "Module.h"
#include "DefaultMap.h"
+#include "Symbol.h"
static int
datatypeCmp (const void *a, const void *b)
@@ -46,7 +47,6 @@ targetOffsetCmp (const void *a, const void *b)
return o1 == o2 ? 0 : (o1 < o2 ? -1 : 1);
}
-
//////////////////////////////////////////////////////////
// class Dwr_type
class Dwr_type
@@ -368,6 +368,7 @@ Dwarf::Dwarf (Stabs *_stabs)
debug_infoSec = NULL;
debug_abbrevSec = NULL;
debug_strSec = NULL;
+ debug_alt_strSec = NULL;
debug_lineSec = NULL;
debug_line_strSec = NULL;
debug_rangesSec = NULL;
@@ -378,18 +379,14 @@ Dwarf::Dwarf (Stabs *_stabs)
return;
}
debug_infoSec = dwrGetSec (NTXT (".debug_info"));
- if (debug_infoSec)
- {
- debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rela.debug_info"), NULL);
- debug_infoSec->reloc = ElfReloc::get_elf_reloc (elf, NTXT (".rel.debug_info"), debug_infoSec->reloc);
- if (debug_infoSec->reloc)
- debug_infoSec->reloc->dump ();
- }
debug_abbrevSec = dwrGetSec (NTXT (".debug_abbrev"));
debug_strSec = dwrGetSec (NTXT (".debug_str"));
debug_lineSec = dwrGetSec (NTXT (".debug_line"));
debug_rangesSec = dwrGetSec (NTXT (".debug_ranges"));
debug_line_strSec = dwrGetSec (".debug_line_str");
+ debug_rnglists = NULL;
+ if (elf->gnu_debugalt_file)
+ debug_alt_strSec = elf->gnu_debugalt_file->get_dwr_section (".debug_str");
if ((debug_infoSec == NULL) || (debug_abbrevSec == NULL) || (debug_lineSec == NULL))
{
@@ -400,27 +397,16 @@ Dwarf::Dwarf (Stabs *_stabs)
Dwarf::~Dwarf ()
{
- delete debug_infoSec;
- delete debug_abbrevSec;
- delete debug_strSec;
- delete debug_lineSec;
- delete debug_rangesSec;
Destroy (dwrCUs);
}
DwrSec *
Dwarf::dwrGetSec (const char *sec_name)
{
- int secN = elf->elf_get_sec_num (sec_name);
- if (secN > 0)
- {
- Elf_Data *elfData = elf->elf_getdata (secN);
- if (elfData)
- return new DwrSec ((unsigned char *) elfData->d_buf, elfData->d_size,
- elf->need_swap_endian,
- elf->elf_getclass () == ELFCLASS32);
- }
- return NULL;
+ DwrSec *p = elf->get_dwr_section (sec_name);
+ if (p)
+ p->offset = 0;
+ return p;
}
uint64_t
@@ -441,7 +427,12 @@ DwrCU::get_linkage_name ()
nm = Dwarf_string (DW_AT_SUN_link_name);
if (nm != NULL)
return nm;
- return Dwarf_string (DW_AT_MIPS_linkage_name);
+ if (nm != NULL)
+ return nm;
+ nm = Dwarf_string (DW_AT_MIPS_linkage_name);
+ if (nm != NULL)
+ return nm;
+ return Dwarf_string (DW_AT_name);
}
void
@@ -454,7 +445,7 @@ DwrCU::parseChild (Dwarf_cnt *ctx)
Dwarf_Die next_die;
if (read_ref_attr (DW_AT_sibling, &next_die) == DW_DLV_OK)
{
- next_die_offset = next_die + cu_offset;
+ next_die_offset = next_die;
if (next_die_offset <= debug_infoSec->offset)
{
Dprintf (DEBUG_ERR_MSG, NTXT ("DwrCU::parseChild: next_die(0x%llx) <= debug_infoSec->offset(%llx)\n"),
@@ -490,8 +481,25 @@ DwrCU::parseChild (Dwarf_cnt *ctx)
}
break;
case DW_TAG_subprogram:
- if (dwrTag.get_attr (DW_AT_abstract_origin))
- break;
+ {
+ Symbol *sym = NULL;
+ Vector<Symbol *> *syms = NULL;
+ Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_abstract_origin);
+ if (dwrAttr)
+ {
+ // Set up functions from DW_AT_{ranges,low_pc,linkage_name}
+ set_up_funcs (dwrAttr->u.offset);
+ break;
+ }
+
+ dwrAttr = dwrTag.get_attr (DW_AT_specification);
+ if (dwrAttr)
+ {
+ // Set up functions from DW_AT_{ranges,low_pc,linkage_name}
+ set_up_funcs (dwrAttr->u.offset);
+ break;
+ }
+
if (dwrTag.get_attr (DW_AT_declaration))
{
// Only declaration
@@ -499,26 +507,39 @@ DwrCU::parseChild (Dwarf_cnt *ctx)
{
char *link_name = Dwarf_string (DW_AT_name);
if (link_name && streq (link_name, NTXT ("MAIN")))
- ctx->fortranMAIN = Stabs::find_func (NTXT ("MAIN"), ctx->module->functions, true, true);
+ ctx->fortranMAIN = Stabs::find_func (NTXT ("MAIN"),
+ ctx->module->functions, true, true);
}
+ sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym != NULL)
+ func = append_Function (sym, ctx->name);
break;
}
- func = append_Function (ctx);
- if (func)
+
+ func = NULL;
+ syms = get_symbols (tmp_syms);
+ for (int i = 0, sz = VecSize (syms); i < sz; i++)
{
+ sym = syms->get (i);
+ func = append_Function (sym, ctx->name);
if (Stabs::is_fortran (ctx->module->lang_code) &&
- streq (func->get_match_name (), NTXT ("MAIN")))
+ streq (func->get_match_name (), "MAIN"))
ctx->fortranMAIN = func;
- old_name = ctx->name;
- Function *old_func = ctx->func;
- ctx->name = func->get_match_name ();
- ctx->func = func;
- parseChild (ctx);
- hasChild = 0;
- ctx->name = old_name;
- ctx->func = old_func;
}
+ if (func == NULL)
+ break;
+
+ old_name = ctx->name;
+ Function *old_func = ctx->func;
+ ctx->name = func->get_match_name ();
+ ctx->func = func;
+ parseChild (ctx);
+ hasChild = 0;
+ ctx->name = old_name;
+ ctx->func = old_func;
break;
+ }
case DW_TAG_module:
old_name = ctx->name;
ctx->name = Dwarf_string (DW_AT_SUN_link_name);
@@ -631,6 +652,21 @@ Dwarf::archive_Dwarf (LoadObject *lo)
STR (lo_name), STR (mod->get_name ()));
dwrCU->dwrInlinedSubrs->dump (msg);
}
+ for (int i = 0, sz = VecSize (dwrCU->symbols); i < sz; i++)
+ {
+ Symbol *sp = dwrCU->symbols->get (i);
+ Function *f = sp->func;
+ if (f == NULL)
+ {
+ f = sp->createFunction (mod);
+ if (sp->alias && sp->alias->func)
+ {
+ Function *func = sp->alias->func;
+ f->setLineFirst (func->line_first);
+ f->setDefSrc (func->def_source);
+ }
+ }
+ }
}
}
return true;
@@ -645,6 +681,29 @@ Dwarf::srcline_Dwarf (Module *module)
dwrCU->map_dwarf_lines (module);
}
+Vector<Range *> *
+Dwarf::get_ranges (uint64_t offset)
+{
+ if (debug_rangesSec == NULL)
+ return NULL;
+ if (offset >= debug_rangesSec->size)
+ {
+ Dprintf (DUMP_DWARFLIB, "ERROR: Dwarf::get_ranges(0x%llx). size=0x%llx\n",
+ (long long) offset, (long long) debug_rangesSec->size);
+ return NULL;
+ }
+ Vector<Range*> *ranges = new Vector<Range*>();
+ debug_rangesSec->offset = offset;
+ for (;;)
+ {
+ uint64_t low_pc = debug_rangesSec->GetADDR ();
+ uint64_t high_pc = debug_rangesSec->GetADDR ();
+ if (low_pc == 0 || low_pc > high_pc)
+ break;
+ ranges->append (new Range (low_pc, high_pc));
+ }
+ return ranges;
+}
// parse hwcprof info for given module in loadobject
@@ -723,7 +782,7 @@ DwrCU::read_hwcprof_info (Dwarf_cnt *ctx)
Dwarf_Die next_die;
if (read_ref_attr (DW_AT_sibling, &next_die) == DW_DLV_OK)
{
- next_die_offset = next_die + cu_offset;
+ next_die_offset = next_die;
if (next_die_offset <= debug_infoSec->offset)
next_die_offset = 0;
else if (debug_infoSec->size > next_die_offset)
@@ -797,11 +856,17 @@ DwrCU::read_hwcprof_info (Dwarf_cnt *ctx)
case DW_TAG_subprogram:
{
Function *old_func = ctx->func;
- if (dwrTag.get_attr (DW_AT_abstract_origin)
- || dwrTag.get_attr (DW_AT_declaration))
- ctx->func = NULL;
- else
- ctx->func = append_Function (ctx);
+ ctx->func = NULL;
+ if (dwrTag.get_attr (DW_AT_abstract_origin) == NULL
+ && dwrTag.get_attr (DW_AT_declaration) == NULL)
+ {
+ Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym == NULL)
+ sym = Symbol::get_symbol (symbols, get_low_pc ());
+ if (sym != NULL)
+ ctx->func = sym->func;
+ }
read_hwcprof_info (ctx);
ctx->func = old_func;
break;
@@ -955,49 +1020,31 @@ DwrCU::read_hwcprof_info (Dwarf_cnt *ctx)
// Append function to module
Function *
-DwrCU::append_Function (Dwarf_cnt *ctx)
+DwrCU::append_Function (Symbol *sym, const char *outerName)
{
- char *outerName = ctx->name, *name, tmpname[2048];
- Function *func;
+ if (sym->func != NULL)
+ return sym->func;
+ Function *func = sym->createFunction (module);
+
char *fname = Dwarf_string (DW_AT_name);
- if (fname && outerName && !strchr (fname, '.'))
+ if (fname)
{
- size_t outerlen = strlen (outerName);
- if (outerlen > 0 && outerName[outerlen - 1] == '_')
+ if (outerName && !strchr (fname, '.'))
{
- outerlen--;
- snprintf (tmpname, sizeof (tmpname), NTXT ("%s"), outerName);
- snprintf (tmpname + outerlen, sizeof (tmpname) - outerlen, NTXT (".%s_"), fname);
+ char *tmpname;
+ int outerlen = (int) strlen (outerName);
+ if (outerlen > 0 && outerName[outerlen - 1] == '_')
+ tmpname = dbe_sprintf ("%.*s.%s_", outerlen - 1, outerName, fname);
+ else
+ tmpname = dbe_sprintf ("%s.%s", outerName, fname);
+ func->set_match_name (tmpname);
+ Dprintf (DUMP_DWARFLIB, "Generated innerfunc name %s\n", tmpname);
+ free(tmpname);
}
else
- snprintf (tmpname, sizeof (tmpname), NTXT ("%s.%s"), outerName, fname);
- name = tmpname;
- Dprintf (DUMP_DWARFLIB, NTXT ("Generated innerfunc name %s\n"), name);
- }
- else
- name = fname;
-
- char *link_name = get_linkage_name ();
- if (link_name == NULL)
- link_name = name;
-
- uint64_t pc = get_low_pc ();
- func = dwarf->stabs->append_Function (module, link_name, pc);
- if (func != NULL)
- {
- int lineno = (int) Dwarf_data (DW_AT_decl_line);
- func->set_match_name (name);
- if (lineno > 0)
- {
- func->setLineFirst (lineno);
- int fileno = ((int) Dwarf_data (DW_AT_decl_file));
- SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ? srcFiles->get (fileno)
- : module->getMainSrc ();
- func->setDefSrc (sf);
- func->pushSrcFile (func->def_source, 0);
- func->popSrcFile ();
- }
+ func->set_match_name (fname);
}
+ set_source (func);
return func;
}
@@ -1040,3 +1087,93 @@ DwrCU::Dwarf_lang ()
return Sp_lang_unknown;
}
}
+
+Vector <Dwr_rng_entry *> *
+Dwarf::get_debug_rnglists ()
+{
+ if (debug_rnglists != NULL)
+ return debug_rnglists;
+ debug_rnglists = new Vector <Dwr_rng_entry *> ();
+
+ DwrSec *debug_rnglistsSec = dwrGetSec (".debug_rnglists");
+ if (debug_rnglistsSec == NULL)
+ {
+ Dprintf (1, "No section .debug_rnglists\n");
+ return debug_rnglists;
+ }
+ while (debug_rnglistsSec->offset < debug_rnglistsSec->sizeSec)
+ {
+ uint64_t base_address = 0;
+ uint64_t length = debug_rnglistsSec->ReadLength ();
+ Dwr_rng_entry *rng = new Dwr_rng_entry ();
+ debug_rnglists->append (rng);
+ rng->offset = debug_rnglistsSec->offset;
+ rng->length = length;
+ rng->fmt64 = debug_rnglistsSec->fmt64;
+ rng->version = debug_rnglistsSec->Get_16 ();
+ rng->address_size = debug_rnglistsSec->Get_8 ();
+ rng->segment_selector_size = debug_rnglistsSec->Get_8 ();
+ rng->offset_entry_count = debug_rnglistsSec->Get_32 ();
+ while (debug_rnglistsSec->offset < debug_rnglistsSec->size)
+ {
+ uint64_t off = debug_rnglistsSec->offset;
+ uint64_t low_pc;
+ uint64_t high_pc;
+ int re = debug_rnglistsSec->Get_8 ();
+ switch (re)
+ {
+ case DW_RLE_end_of_list:
+ low_pc = 0;
+ high_pc = 0;
+ break;
+ case DW_RLE_base_address:
+ base_address = debug_rnglistsSec->GetADDR ();
+ low_pc = base_address;
+ high_pc = 0;
+ continue;
+ case DW_RLE_start_length:
+ low_pc = debug_rnglistsSec->GetADDR ();
+ high_pc = low_pc + debug_rnglistsSec->GetULEB128 ();
+ break;
+ case DW_RLE_offset_pair:
+ low_pc = base_address + debug_rnglistsSec->GetULEB128 ();
+ high_pc = base_address + debug_rnglistsSec->GetULEB128 ();
+ break;
+ case DW_RLE_start_end:
+ low_pc = debug_rnglistsSec->GetADDR ();
+ high_pc = debug_rnglistsSec->GetADDR ();
+ break;
+ case DW_RLE_base_addressx:
+ base_address = debug_rnglistsSec->GetULEB128 ();
+ low_pc = base_address;
+ high_pc = 0;
+ continue;
+
+ // TODO x-variants need .debug_addr support used for split-dwarf
+ case DW_RLE_startx_endx:
+ low_pc = debug_rnglistsSec->GetRef ();
+ high_pc = debug_rnglistsSec->GetRef ();
+ Dprintf (1, "DW_RLE_startx_endx is not implemented\n");
+ continue;
+ case DW_RLE_startx_length:
+ low_pc = debug_rnglistsSec->GetRef ();
+ high_pc = low_pc + debug_rnglistsSec->GetULEB128 ();
+ Dprintf (1, "DW_RLE_startx_length is not implemented\n");
+ continue;
+ default:
+ Dprintf (1, "Unknown tag DW_RLE: %d, offset=0x%llx\n", re,
+ (long long) off);
+ debug_rnglistsSec->offset = debug_rnglistsSec->size;
+ continue;
+ }
+ Dprintf (DUMP_DWARFLIB, "0x%08llx %d-%-20s [0x%08llx - 0x%08llx)\n",
+ (long long) off, re, Dwr_rng_entry::rng_entry2str (re),
+ (long long) low_pc, (long long) high_pc);
+ rng->ranges->append (new ExtRange (off, low_pc, high_pc));
+ }
+ debug_rnglistsSec->size = debug_rnglistsSec->sizeSec;
+ debug_rnglistsSec->offset = length;
+ }
+ debug_rnglists->dump ("Dwarf::get_debug_rnglists");
+ return debug_rnglists;
+}
diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h
index 8e3ee7a..14d9878 100644
--- a/gprofng/src/Dwarf.h
+++ b/gprofng/src/Dwarf.h
@@ -60,6 +60,7 @@ class LoadObject;
class Module;
class DwrCU;
class DwrSec;
+class Range;
class Dwarf
{
@@ -69,12 +70,15 @@ public:
bool archive_Dwarf (LoadObject *lo);
void srcline_Dwarf (Module *module);
void read_hwcprof_info (Module *module);
+ Vector<Range *> *get_ranges (uint64_t offset);
+ Vector <Dwr_rng_entry *> *get_debug_rnglists ();
Stabs::Stab_status status;
Vector<DwrCU *> *dwrCUs;
DwrSec *debug_infoSec;
DwrSec *debug_abbrevSec;
DwrSec *debug_strSec;
+ DwrSec *debug_alt_strSec;
DwrSec *debug_lineSec;
DwrSec *debug_line_strSec;
DwrSec *debug_rangesSec;
@@ -82,6 +86,7 @@ public:
Stabs *stabs;
private:
+ Vector <Dwr_rng_entry *> *debug_rnglists;
DwrSec *dwrGetSec (const char *sec_name);
};
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc
index d399c33..4720ef1 100644
--- a/gprofng/src/DwarfLib.cc
+++ b/gprofng/src/DwarfLib.cc
@@ -27,39 +27,14 @@
#include "Elf.h"
#include "Function.h"
#include "Module.h"
-#include "StringBuilder.h"
#include "DbeArray.h"
#include "DbeSession.h"
+#include "Symbol.h"
#define NO_STMT_LIST ((uint64_t) -1)
#define CASE_S(x) case x: s = (char *) #x; break
static char *
-gelf_st_type2str (int type)
-{
- static char buf[128];
- char *s;
- switch (type)
- {
- CASE_S (STT_NOTYPE);
- CASE_S (STT_OBJECT);
- CASE_S (STT_FUNC);
- CASE_S (STT_SECTION);
- CASE_S (STT_FILE);
- CASE_S (STT_COMMON);
- CASE_S (STT_TLS);
- // CASE_S(STT_NUM);
- CASE_S (STT_LOPROC);
- CASE_S (STT_HIPROC);
- default: s = NTXT ("???");
- break;
- }
- snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type);
- buf[sizeof (buf) - 1] = 0;
- return buf;
-}
-
-static char *
special_opcode2str (int opcode)
{
static char buf[128];
@@ -78,6 +53,7 @@ extended_opcode2str (int opcode)
CASE_S (DW_LNE_end_sequence);
CASE_S (DW_LNE_set_address);
CASE_S (DW_LNE_define_file);
+ CASE_S (DW_LNS_set_file);
default:
snprintf (buf, sizeof (buf), NTXT ("??? (%d)"), opcode);
buf[sizeof (buf) - 1] = 0;
@@ -166,234 +142,6 @@ get_string (DwrSec *sec, uint64_t off)
return NULL;
}
-
-//////////////////////////////////////////////////////////
-// class ElfReloc
-
-ElfReloc::ElfReloc (Elf *_elf)
-{
- elf = _elf;
- reloc = NULL;
- cur_reloc_ind = 0;
-}
-
-ElfReloc::~ElfReloc ()
-{
- if (reloc)
- {
- reloc->destroy ();
- delete reloc;
- }
-}
-
-void
-ElfReloc::dump_rela_debug_sec (int sec)
-{
- if (!DUMP_RELA_SEC)
- return;
- Elf_Internal_Shdr *shdr = elf->get_shdr (sec);
- if (shdr == NULL)
- return;
-
- Elf_Data *data = elf->elf_getdata (sec);
- if (data == NULL)
- return;
-
- uint64_t ScnSize = data->d_size;
- uint64_t EntSize = shdr->sh_entsize;
- if (ScnSize == 0 || EntSize == 0)
- return;
-
- Elf_Internal_Rela rela;
- int n, cnt = (int) (ScnSize / EntSize);
-
- char *sec_name = elf->get_sec_name (sec);
- if (sec_name == NULL) // It can not be, but let's check
- return;
- Dprintf (DUMP_RELA_SEC,
- "======= DwarfLib::dump_rela_debug_sec Section:%2d '%s'\n",
- sec, sec_name);
- Dprintf (DUMP_RELA_SEC,
- " N |addend| offset | r_info | stt_type |\n");
- for (n = 0; n < cnt; n++)
- {
- if (strncmp (sec_name, NTXT (".rela."), 6) == 0)
- elf->elf_getrela (data, n, &rela);
- else
- {
- elf->elf_getrel (data, n, &rela);
- rela.r_addend = 0;
- }
- int ndx = (int) GELF_R_SYM (rela.r_info);
- Elf_Internal_Shdr *secHdr;
- Elf_Internal_Sym sym;
- asymbol *asym;
- asym = elf->elf_getsym (ndx, &sym, false);
- Dprintf (DUMP_RELA_SEC, NTXT ("%3d:%5d |%11lld |0x%016llx | %-15s|"),
- n, (int) rela.r_addend,
- (long long) rela.r_offset, (long long) rela.r_info,
- gelf_st_type2str ((int) GELF_ST_TYPE (sym.st_info)));
- switch (GELF_ST_TYPE (sym.st_info))
- {
- case STT_FUNC:
- case STT_OBJECT:
- case STT_NOTYPE:
- Dprintf (DUMP_RELA_SEC, NTXT (" img_offset=0x%llx"),
- (long long) (bfd_asymbol_value (asym)));
- Dprintf (DUMP_RELA_SEC, NTXT (" %s"), bfd_asymbol_name (asym));
- break;
- case STT_SECTION:
- secHdr = elf->get_shdr (sym.st_shndx);
- if (secHdr)
- {
- Dprintf (DUMP_RELA_SEC, NTXT (" value=0x%016llx (%lld)"),
- (long long) (secHdr->sh_offset + rela.r_addend),
- (long long) (secHdr->sh_offset + rela.r_addend));
- }
- break;
- default:
- break;
- }
- Dprintf (DUMP_RELA_SEC, NTXT ("\n"));
- }
- Dprintf (DUMP_RELA_SEC, NTXT ("\n"));
-}
-
-void
-ElfReloc::dump ()
-{
- if (!DUMP_ELF_RELOC || (reloc == NULL) || (reloc->size () == 0))
- return;
- Dprintf (DUMP_ELF_RELOC, NTXT ("======= ElfReloc::dump\n"));
- Dprintf (DUMP_ELF_RELOC, NTXT (" N | offset | value | STT_TYPE\n"));
- for (int i = 0; i < reloc->size (); i++)
- {
- Sreloc *srlc = reloc->fetch (i);
- Dprintf (DUMP_ELF_RELOC, NTXT ("%3d:%11lld |%11lld | %s\n"),
- i, (long long) srlc->offset, (long long) srlc->value,
- gelf_st_type2str (srlc->stt_type));
- }
- Dprintf (DUMP_ELF_RELOC, NTXT ("\n"));
-}
-
-static int
-DwrRelocOffsetCmp (const void *a, const void *b)
-{
- ElfReloc::Sreloc *item1 = *((ElfReloc::Sreloc **) a);
- ElfReloc::Sreloc *item2 = *((ElfReloc::Sreloc **) b);
- return item1->offset < item2->offset ? -1 :
- item1->offset == item2->offset ? 0 : 1;
-}
-
-ElfReloc *
-ElfReloc::get_elf_reloc (Elf *elfp, char *sec_name, ElfReloc *rlc)
-{
- int et = elfp->elf_getehdr ()->e_type;
- if (et == ET_EXEC || et == ET_DYN)
- return rlc;
- int sec = elfp->elf_get_sec_num (sec_name);
- if (sec == 0)
- return rlc;
- Elf_Internal_Shdr *shdr = elfp->get_shdr (sec);
- if (shdr == NULL || shdr->sh_entsize == 0)
- return rlc;
-
- Elf_Data *data = elfp->elf_getdata (sec);
- if (data == NULL || data->d_size == 0)
- return rlc;
-
- int cnt = (int) (data->d_size / shdr->sh_entsize);
- Vector<Sreloc *> *vp = NULL;
-
- for (int n = 0; n < cnt; n++)
- {
- Elf_Internal_Shdr *secHdr;
- Sreloc *srlc;
- Elf_Internal_Rela rela;
- if (strncmp (sec_name, NTXT (".rela."), 6) == 0)
- elfp->elf_getrela (data, n, &rela);
- else
- {
- elfp->elf_getrel (data, n, &rela);
- rela.r_addend = 0;
- }
- int ndx = (int) GELF_R_SYM (rela.r_info);
- Elf_Internal_Sym sym;
- elfp->elf_getsym (ndx, &sym, false);
-
- srlc = new Sreloc;
- srlc->offset = rela.r_offset;
- srlc->value = 0;
- srlc->stt_type = (int) GELF_ST_TYPE (sym.st_info);
- switch (GELF_ST_TYPE (sym.st_info))
- {
- case STT_FUNC:
- secHdr = elfp->get_shdr (sym.st_shndx);
- if (secHdr)
- srlc->value = secHdr->sh_offset + sym.st_value;
- break;
- case STT_OBJECT:
- case STT_NOTYPE:
- secHdr = elfp->get_shdr (shdr->sh_info);
- if (secHdr)
- {
- srlc->offset = rela.r_info;
- srlc->value = secHdr->sh_offset + rela.r_addend;
- }
- break;
- case STT_SECTION:
- secHdr = elfp->get_shdr (sym.st_shndx);
- if (secHdr)
- srlc->value = rela.r_addend;
- break;
- default:
- srlc->value = 0;
- break;
- }
- if (rlc == NULL)
- {
- rlc = new ElfReloc (elfp);
- vp = rlc->reloc;
- }
- if (vp == NULL)
- {
- vp = new Vector<Sreloc*>;
- rlc->reloc = vp;
- }
- vp->append (srlc);
- }
- if (vp)
- vp->sort (DwrRelocOffsetCmp);
- if (rlc)
- {
- rlc->dump_rela_debug_sec (sec);
- rlc->dump ();
- }
- return rlc;
-}
-
-long long
-ElfReloc::get_reloc_addr (long long offset)
-{
- Sreloc *srlc;
- int i = cur_reloc_ind - 1;
- if (i >= 0 && i < reloc->size ())
- {
- srlc = reloc->fetch (i);
- if (srlc->offset > offset) // need to reset
- cur_reloc_ind = 0;
- }
- for (; cur_reloc_ind < reloc->size (); cur_reloc_ind++)
- {
- srlc = reloc->fetch (cur_reloc_ind);
- if (srlc->offset == offset)
- return srlc->value;
- if (srlc->offset > offset)
- return 0;
- }
- return 0;
-}
-
DwrLocation *
DwrCU::dwr_get_location (DwrSec *secp, DwrLocation *lp)
{
@@ -936,6 +684,8 @@ DwrCU::form2str (int tag)
CASE_S (DW_FORM_strp);
CASE_S (DW_FORM_udata);
CASE_S (DW_FORM_ref_addr);
+ CASE_S (DW_FORM_GNU_ref_alt);
+ CASE_S (DW_FORM_GNU_strp_alt);
CASE_S (DW_FORM_ref1);
CASE_S (DW_FORM_ref2);
CASE_S (DW_FORM_ref4);
@@ -993,12 +743,12 @@ Dwr_Tag::dump ()
case DW_FORM_strp:
case DW_FORM_string:
case DW_FORM_line_strp:
+ case DW_FORM_GNU_strp_alt:
case DW_FORM_strp_sup:
case DW_FORM_strx1:
case DW_FORM_strx2:
case DW_FORM_strx3:
case DW_FORM_strx4:
- case DW_FORM_implicit_const:
Dprintf (DUMP_DWARFLIB, " \"%s\"", atrp->u.str ? atrp->u.str : "<NULL>");
break;
case DW_FORM_block:
@@ -1034,9 +784,11 @@ Dwr_Tag::dump ()
case DW_FORM_ref_udata:
case DW_FORM_indirect:
case DW_FORM_sec_offset:
+ case DW_FORM_GNU_ref_alt:
case DW_FORM_exprloc:
case DW_FORM_ref_sig8:
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
Dprintf (DUMP_DWARFLIB, " 0x%llx (%lld)", (long long) atrp->u.val,
(long long) atrp->u.val);
break;
@@ -1058,34 +810,28 @@ Dwr_Tag::dump ()
DwrSec::DwrSec (unsigned char *_data, uint64_t _size, bool _need_swap_endian, bool _addr32)
{
- isCopy = false;
data = _data;
sizeSec = _size;
size = (data ? _size : 0);
offset = 0;
fmt64 = false;
- reloc = NULL;
need_swap_endian = _need_swap_endian;
addr32 = _addr32;
}
DwrSec::DwrSec (DwrSec *secp, uint64_t _offset)
{
- isCopy = true;
data = secp->data;
sizeSec = secp->sizeSec;
size = secp->size;
offset = _offset;
fmt64 = secp->fmt64;
- reloc = secp->reloc;
need_swap_endian = secp->need_swap_endian;
addr32 = secp->addr32;
}
DwrSec::~DwrSec ()
{
- if (!isCopy)
- delete reloc;
}
bool
@@ -1095,6 +841,7 @@ DwrSec::bounds_violation (uint64_t sz)
{
Dprintf (DEBUG_ERR_MSG, "DwrSec::bounds_violation: offset=%lld + sz=%lld > size=%lld\n",
(long long) offset, (long long) sz, (long long) size);
+ offset = size;
return true;
}
return false;
@@ -1212,17 +959,13 @@ DwrSec::GetLong ()
uint64_t
DwrSec::GetADDR_32 ()
{
- uint64_t res = reloc ? reloc->get_reloc_addr (offset) : 0;
- res += Get_32 ();
- return res;
+ return Get_32 ();
}
uint64_t
DwrSec::GetADDR_64 ()
{
- uint64_t res = reloc ? reloc->get_reloc_addr (offset) : 0;
- res += Get_64 ();
- return res;
+ return Get_64 ();
}
uint64_t
@@ -1282,6 +1025,7 @@ DwrSec::get_value (int dw_form)
case DW_FORM_line_strp:
case DW_FORM_strp:
case DW_FORM_strp_sup:
+ case DW_FORM_GNU_strp_alt:
return GetRef ();
case DW_FORM_data1:
return Get_8 ();
@@ -1545,6 +1289,8 @@ DwrLineRegs::read_file_names_dwarf5 ()
nm = get_string (dwarf->debug_line_strSec, off);
else if (efmt[k].form_code == DW_FORM_strp)
nm = get_string (dwarf->debug_strSec, off);
+ else if (efmt[k].form_code == DW_FORM_GNU_strp_alt)
+ nm = get_string (dwarf->debug_alt_strSec, off);
}
break;
case DW_LNCT_directory_index:
@@ -1795,6 +1541,12 @@ DwrLineRegs::getPath (int fn)
DwrCU::DwrCU (Dwarf *_dwarf)
{
dwarf = _dwarf;
+ tmp_syms = new Vector<Symbol*>();
+ rng_list = NULL;
+ rng_list_inited = false;
+ base_address = 0;
+ symbols = NULL;
+ symbols_sorted_by_name = NULL;
cu_offset = dwarf->debug_infoSec->offset;
debug_infoSec = new DwrSec (dwarf->debug_infoSec, cu_offset);
next_cu_offset = debug_infoSec->ReadLength ();
@@ -1836,7 +1588,7 @@ DwrCU::DwrCU (Dwarf *_dwarf)
if (DUMP_DWARFLIB)
{
Dprintf (DUMP_DWARFLIB,
- "CU_HEADER: header_offset = 0x%08llx %lld"
+ "File: %s\nCU_HEADER: header_offset = 0x%08llx %lld"
" next_header_offset=0x%08llx %lld\n"
" abbrev_offset = 0x%08llx %lld\n"
" unit_length = %lld\n"
@@ -1844,10 +1596,11 @@ DwrCU::DwrCU (Dwarf *_dwarf)
" address_size = %d\n"
" fmt64 = %s\n"
"debug_info: need_swap_endian=%s fmt64=%s addr32=%s\n",
+ dwarf->elf->get_location (),
(long long) cu_offset, (long long) cu_offset,
(long long) next_cu_offset, (long long) next_cu_offset,
(long long) debug_abbrev_offset, (long long) debug_abbrev_offset,
- (long long) (next_cu_offset - cu_offset),
+ (long long) (next_cu_offset),
(int) version, (int) address_size,
debug_infoSec->fmt64 ? "true" : "false",
debug_infoSec->need_swap_endian ? "true" : "false",
@@ -1883,6 +1636,9 @@ DwrCU::~DwrCU ()
Destroy (dwrInlinedSubrs);
delete srcFiles;
delete dwrLineReg;
+ delete symbols;
+ delete symbols_sorted_by_name;
+ delete tmp_syms;
free (comp_dir);
}
@@ -1925,7 +1681,7 @@ DwrCU::build_abbrevTable (DwrSec *_debug_abbrevSec, uint64_t _offset)
switch (atf.at_form)
{
case DW_FORM_implicit_const:
- atf.len = debug_abbrevSec->GetSLEB128 ();
+ atf.u.val = debug_abbrevSec->GetSLEB128 ();
break;
}
abbrevAtForm->append (atf);
@@ -1945,7 +1701,7 @@ DwrCU::set_die (Dwarf_Die die)
|| debug_infoSec->offset >= debug_infoSec->size)
return DW_DLV_ERROR;
dwrTag.offset = debug_infoSec->offset;
- dwrTag.die = debug_infoSec->offset - cu_offset;
+ dwrTag.die = debug_infoSec->offset;
dwrTag.num = debug_infoSec->GetULEB128_32 ();
if (dwrTag.num == 0)
return DW_DLV_NO_ENTRY;
@@ -1994,19 +1750,19 @@ DwrCU::set_die (Dwarf_Die die)
atf->u.str = debug_infoSec->GetData (atf->len);
break;
case DW_FORM_ref1:
- atf->u.offset = debug_infoSec->Get_8 ();
+ atf->u.offset = debug_infoSec->Get_8 () + cu_offset;
break;
case DW_FORM_ref2:
- atf->u.offset = debug_infoSec->Get_16 ();
+ atf->u.offset = debug_infoSec->Get_16 () + cu_offset;
break;
case DW_FORM_ref4:
- atf->u.offset = debug_infoSec->Get_32 ();
+ atf->u.offset = debug_infoSec->Get_32 () + cu_offset;
break;
case DW_FORM_ref8:
- atf->u.offset = debug_infoSec->Get_64 ();
+ atf->u.offset = debug_infoSec->Get_64 () + cu_offset;
break;
case DW_FORM_ref_udata:
- atf->u.offset = debug_infoSec->GetULEB128 ();
+ atf->u.offset = debug_infoSec->GetULEB128 () + cu_offset;
break;
case DW_FORM_data1:
atf->u.offset = debug_infoSec->Get_8 ();
@@ -2040,6 +1796,9 @@ DwrCU::set_die (Dwarf_Die die)
else
atf->u.offset = debug_infoSec->GetADDR ();
break;
+ case DW_FORM_GNU_ref_alt:
+ atf->u.offset = debug_infoSec->GetRef ();
+ break;
case DW_FORM_sec_offset:
atf->u.offset = debug_infoSec->GetRef ();
break;
@@ -2063,6 +1822,10 @@ DwrCU::set_die (Dwarf_Die die)
case DW_FORM_rnglistx:
atf->u.offset = debug_infoSec->GetULEB128 ();
break;
+ case DW_FORM_GNU_strp_alt:
+ atf->u.offset = debug_infoSec->GetRef ();
+ atf->u.str = get_string (dwarf->debug_alt_strSec, atf->u.offset);
+ break;
case DW_FORM_strx:
atf->u.offset = debug_infoSec->GetULEB128 ();
atf->u.str = get_string (dwarf->debug_strSec, atf->u.offset);
@@ -2109,7 +1872,7 @@ DwrCU::set_die (Dwarf_Die die)
atf->len = 0;
break;
case DW_FORM_implicit_const:
- atf->u.str = NULL;
+ // atf->u.val is already set
break;
default:
DEBUG_CODE
@@ -2187,9 +1950,241 @@ DwrCU::parse_cu_header (LoadObject *lo)
else
path = dbe_strdup (dwarf->stabs->path);
module->set_name (path);
+
+ // create a list of functions in this CU
+ base_address = get_low_pc ();
+ Vector <Range *> *ranges = get_ranges ();
+ if (ranges)
+ {
+ Vector <Symbol *> *syms = dwarf->stabs->get_symbols ();
+ symbols = Symbol::find_symbols (syms, ranges, new Vector <Symbol *> ());
+ symbols_sorted_by_name = Symbol::sort_by_name (symbols);
+ if (DUMP_ELF_SYM)
+ symbols->dump ("DwrCU::parse_cu_header: symbols");
+ Destroy (ranges);
+ }
return module;
}
+
+static int
+cmp_ExtRange (const void *a, const void *b)
+{
+ uint64_t a1 = *((uint64_t *) a);
+ ExtRange *rng = *((ExtRange **) b);
+ uint64_t b1 = rng->offset;
+ return a1 < b1 ? -1 : (a1 == b1 ? 0 : 1);
+}
+
+static int
+cmp_offset (const void *a, const void *b)
+{
+ uint64_t off = *((uint64_t *) a);
+ Dwr_rng_entry *rng = *((Dwr_rng_entry **) b);
+ return off < rng->offset ? -1 : (off < rng->length ? 0 : 1);
+}
+
+static int
+rangeCmp (const void *a, const void *b)
+{
+ Range *item1 = *((Range **) a);
+ Range *item2 = *((Range **) b);
+ return item1->low < item2->low ? -1 : (item1->low == item2->low ? 0 : 1);
+}
+
+Vector <Range *> *
+DwrCU::get_ranges ()
+{
+ Vector <Range *> *ranges = NULL;
+ Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_ranges);
+ if (dwrAttr)
+ {
+ uint64_t offset = dwrAttr->u.offset;
+ Dprintf (DUMP_DWARFLIB, "DwrCU::get_ranges: 0x%llx\n", (long long) offset);
+ if (version < 5)
+ ranges = dwarf->get_ranges (offset);
+ else
+ {
+ if (rng_list == NULL && !rng_list_inited)
+ {
+ rng_list_inited = true;
+ // Find the corresponding section in .debug_rnglists
+ Vector <Dwr_rng_entry *> *rng_entrys = dwarf->get_debug_rnglists ();
+ if (rng_entrys == NULL)
+ return NULL;
+ int ind = rng_entrys->bisearch (0, -1, &offset, cmp_offset);
+ if (ind != -1)
+ rng_list = rng_entrys->get (ind);
+ else
+ {
+ Dprintf (1, "Cannot find rnglist. DW_AT_ranges=0x%llx\n",
+ (long long) offset);
+ return NULL;
+ }
+ }
+ if (rng_list == NULL)
+ return NULL;
+ int ind = rng_list->ranges->bisearch (0, -1, &offset, cmp_ExtRange);
+ if (ind == -1)
+ {
+ Dprintf (1, "Cannot find rnglist. DW_AT_ranges=0x%llx\n",
+ (long long) offset);
+ return NULL;
+ }
+ ranges = new Vector <Range *> ();
+ for (long i = ind, sz = VecSize (rng_list->ranges); i < sz; i++)
+ {
+ ExtRange *r = rng_list->ranges->get (i);
+ if (r->high == 0)
+ break;
+ ranges->append (new Range (r->low + base_address,
+ r->high + base_address));
+ }
+ }
+ }
+ else
+ {
+ uint64_t low_pc = Dwarf_addr (DW_AT_low_pc);
+ if (low_pc > 0)
+ {
+ uint64_t high_pc = get_high_pc (low_pc);
+ ranges = new Vector <Range *> (1);
+ ranges->append (new Range (low_pc, high_pc));
+ Dprintf (DUMP_DWARFLIB, "DwrCU::get_ranges: pc=0x%llx\n",
+ (long long) low_pc);
+ }
+ }
+ if (ranges)
+ {
+ ranges->sort (rangeCmp);
+ if (DUMP_DWARFLIB)
+ ranges->dump ("DwrCU::get_ranges:");
+ }
+ return ranges;
+}
+
+Vector<Symbol *> *
+DwrCU::get_symbols (Vector<Symbol *> *syms)
+{
+ if (syms)
+ syms->reset ();
+ Vector <Range *> *ranges = get_ranges ();
+ if (ranges)
+ {
+ syms = Symbol::find_symbols (symbols, ranges, syms);
+ Destroy (ranges);
+ }
+ if (syms)
+ {
+ Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym)
+ syms->append (sym);
+ }
+ if (syms && DUMP_ELF_SYM)
+ syms->dump ("DwrCU::get_symbols:");
+ return syms;
+}
+
+void
+DwrCU::set_source (Function *func)
+{
+ int lineno = (int) Dwarf_data (DW_AT_decl_line);
+ func->setLineFirst (lineno);
+
+ int fileno = (int) Dwarf_data (DW_AT_decl_file);
+ func->setDefSrc (get_source (fileno));
+}
+
+SourceFile *
+DwrCU::get_source (int fileno)
+{
+ if (fileno > 0 && fileno < VecSize (srcFiles))
+ return srcFiles->get (fileno);
+ return NULL;
+}
+
+void
+DwrCU::inherit_prop (int64_t offset, source_t *src)
+{
+ if (src->lineno == 0)
+ src->lineno = (int) Dwarf_data (DW_AT_decl_line);
+ if (src->sf == NULL)
+ src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file));
+
+ int64_t old_offset = dwrTag.offset;
+ if (set_die (offset) == DW_DLV_OK)
+ {
+ if (src->lineno == 0)
+ src->lineno = (int) Dwarf_data (DW_AT_decl_line);
+ if (src->sf == NULL)
+ src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file));
+
+ Dwr_Attr *dwrAttr = dwrTag.get_attr (DW_AT_specification);
+ if (dwrAttr)
+ inherit_prop (dwrAttr->u.offset, src);
+ else
+ {
+ Symbol *sym = Symbol::get_symbol (symbols_sorted_by_name,
+ get_linkage_name ());
+ if (sym)
+ update_source (sym, src);
+ }
+ }
+ set_die (old_offset);
+}
+
+void
+DwrCU::set_up_funcs (int64_t offset)
+{
+ // get symbols from DW_AT_ranges, DW_AT_low_pc, DW_AT_linkage_name
+ Vector<Symbol *> *syms = get_symbols (tmp_syms);
+ if (VecSize (syms) == 0)
+ return;
+
+ // Find previous declaration to inherit settings.
+ source_t src = {.lineno = 0, .sf = NULL};
+ inherit_prop (offset, &src);
+
+ for (int i = 0, sz = VecSize (syms); i < sz; i++)
+ {
+ Symbol *sym = syms->get (i);
+ update_source (sym, &src);
+ if (sym->alias)
+ update_source (sym->alias, &src);
+ }
+}
+
+/* Create a function if necessary.
+ * Update the source information */
+void
+DwrCU::update_source (Symbol *sym, source_t *src)
+{
+ Function *f = sym->createFunction (module);
+ f->setLineFirst (src->lineno);
+ f->setDefSrc (src->sf);
+}
+
+Symbol *
+DwrCU::find_declaration (int64_t offset, source_t *src)
+{
+ int64_t old_offset = dwrTag.offset;
+ Symbol *sym = NULL;
+ if (set_die (offset) == DW_DLV_OK)
+ {
+ if (src->lineno == 0)
+ src->lineno = (int) Dwarf_data (DW_AT_decl_line);
+ if (src->sf == NULL)
+ src->sf = get_source ((int) Dwarf_data (DW_AT_decl_file));
+
+ sym = Symbol::get_symbol (symbols_sorted_by_name, get_linkage_name ());
+ if (sym && sym->func == NULL)
+ update_source (sym, src);
+ }
+ set_die (old_offset);
+ return sym;
+}
+
Dwr_Attr *
Dwr_Tag::get_attr (Dwarf_Half attr)
{
@@ -2269,6 +2264,7 @@ DwrCU::read_data_attr (Dwarf_Half attr, int64_t *retVal)
case DW_FORM_data16:
case DW_FORM_udata:
case DW_FORM_sec_offset:
+ case DW_FORM_implicit_const:
*retVal = dwrAttr->u.val;
return DW_DLV_OK;
@@ -2357,7 +2353,7 @@ DwrCU::map_dwarf_lines (Module *mod)
InlinedSubr *p = func->inlinedSubr + func->inlinedSubrCnt;
func->inlinedSubrCnt++;
int fileno = inlinedSubr->file - 1;
- SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ?
+ SourceFile *sf = ((fileno > 0) && (fileno < VecSize (srcFiles))) ?
srcFiles->get (fileno) : dbeSession->get_Unknown_Source ();
p->dbeLine = sf->find_dbeline (inlinedSubr->line);
p->high_pc = inlinedSubr->high_pc - low_pc;
@@ -2502,3 +2498,69 @@ DwrInlinedSubr::dump ()
(int) level, (long long) abstract_origin, (long long) low_pc,
(long long) high_pc, (int) file, (int) line);
}
+
+
+//////////////////////////////////////////////////////////
+// class Dwr_rng_entry
+Dwr_rng_entry::Dwr_rng_entry ()
+{
+ ranges = new Vector <ExtRange *>();
+}
+
+Dwr_rng_entry::~Dwr_rng_entry ()
+{
+ delete ranges;
+}
+
+void
+Dwr_rng_entry::dump ()
+{
+ Dprintf (DUMP_DWARFLIB, "offset=0x%08llx length=0x%08llx fmt=%d version=%d "
+ "addr_size=%d seg_size=%d offset_entry_count=0x%llx\n",
+ (long long) offset, (long long) (length - offset), fmt64 ? 64 : 32,
+ (int) version, (int) address_size, (int) segment_selector_size,
+ (long long) offset_entry_count);
+ for (long i = 0, sz = VecSize (ranges); i < sz; i++)
+ {
+ ExtRange *p = ranges->get (i);
+ Dprintf (DUMP_DWARFLIB, " %8ld: 0x%08llx 0x%08llx-0x%08llx [%lld-%lld)\n",
+ i, (long long) p->offset, (long long) p->low, (long long) p->high,
+ (long long) p->low, (long long) p->high);
+ }
+}
+
+char *
+Dwr_rng_entry::rng_entry2str (int val)
+{
+ char *s;
+ switch (val)
+ {
+ CASE_S (DW_RLE_end_of_list);
+ CASE_S (DW_RLE_base_address);
+ CASE_S (DW_RLE_start_length);
+ CASE_S (DW_RLE_offset_pair);
+ CASE_S (DW_RLE_start_end);
+ CASE_S (DW_RLE_base_addressx);
+ CASE_S (DW_RLE_startx_endx);
+ CASE_S (DW_RLE_startx_length);
+ default: s = (char *) "???";
+ break;
+ }
+ return s;
+}
+
+template<> void Vector<Dwr_rng_entry *>::dump (const char *msg)
+{
+ if (!DUMP_DWARFLIB)
+ return;
+ if (msg == NULL)
+ msg = "#";
+ Dprintf (1, NTXT ("\n%s Vector<Dwr_rng_entry *> [%lld]\n"), msg, (long long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ Dwr_rng_entry *p = get (i);
+ Dprintf (1, " %3ld ", i);
+ p->dump ();
+ }
+}
+
diff --git a/gprofng/src/DwarfLib.h b/gprofng/src/DwarfLib.h
index 178801d..49ecb41 100644
--- a/gprofng/src/DwarfLib.h
+++ b/gprofng/src/DwarfLib.h
@@ -23,9 +23,11 @@
#include "dwarf2.h"
-class ElfReloc;
class Dwr_type;
+class Function;
+class Range;
class SourceFile;
+class Symbol;
template <class ITEM> class Vector;
template <class ITEM> class DbeArray;
@@ -73,13 +75,6 @@ public:
return (uint32_t) GetULEB128 ();
}
- bool
- inRange (uint64_t left, uint64_t right)
- {
- return (offset >= left) && (offset < right);
- };
-
- ElfReloc *reloc;
uint64_t sizeSec;
uint64_t size;
uint64_t offset;
@@ -90,7 +85,6 @@ public:
int segment_selector_size; // DWARF 5
private:
- bool isCopy;
unsigned char *data;
bool bounds_violation (uint64_t sz);
};
@@ -260,6 +254,45 @@ public:
Dwr_type *put_dwr_type (Dwr_Tag *dwrTag);
};
+class ExtRange
+{
+public:
+ ExtRange (uint64_t _off, uint64_t _low, uint64_t _high)
+ {
+ offset = _off;
+ low = _low;
+ high = _high;
+ };
+
+ uint64_t offset;
+ uint64_t low;
+ uint64_t high;
+};
+
+class Dwr_rng_entry
+{
+public:
+ Dwr_rng_entry ();
+ ~Dwr_rng_entry ();
+ void dump();
+ static char *rng_entry2str(int val);
+
+ Dwarf_Half version;
+ Dwarf_Small address_size;
+ Dwarf_Small segment_selector_size;
+ int offset_entry_count;
+ uint64_t length;
+ uint64_t offset;
+ bool fmt64;
+ Vector <ExtRange *> *ranges;
+};
+
+typedef struct Source
+{
+ int lineno;
+ SourceFile *sf;
+} source_t;
+
class DwrCU
{
public:
@@ -280,6 +313,8 @@ public:
uint64_t cu_header_offset;
uint64_t cu_offset;
uint64_t next_cu_offset;
+ Vector<Symbol*> *symbols; // all symbols in this CU are sorted by pc
+ Vector<Symbol*> *symbols_sorted_by_name;
Vector<DwrInlinedSubr*> *dwrInlinedSubrs;
Vector<SourceFile *> *srcFiles;
bool isMemop;
@@ -287,7 +322,15 @@ public:
private:
void build_abbrevTable (DwrSec *debug_abbrevSec, uint64_t stmt_list_offset);
- Function *append_Function (Dwarf_cnt *ctx);
+ Function *append_Function (Symbol *sym, const char *outerName);
+ void set_up_funcs (int64_t offset);
+ void inherit_prop (int64_t offset, source_t *src);
+ void update_source (Symbol *sym, source_t *prop);
+ Symbol *find_declaration (int64_t offset, source_t *prop);
+ SourceFile *get_source (int fileno);
+ Vector<Symbol *> *get_symbols (Vector<Symbol *> *syms = NULL);
+ Vector <Range *> *get_ranges();
+ void set_source (Function *func);
void parse_inlined_subroutine (Dwarf_cnt *ctx);
uint64_t get_low_pc ();
uint64_t get_high_pc (uint64_t low_pc);
@@ -316,6 +359,10 @@ private:
DwrLineRegs *dwrLineReg;
DbeArray<DwrAbbrevTable> *abbrevTable;
DbeArray<Dwr_Attr> *abbrevAtForm;
+ Vector<Symbol*> *tmp_syms; // reused vector for get_symbols()
+ Dwr_rng_entry *rng_list; // entry in the .debug_rnglists section
+ bool rng_list_inited;
+ uint64_t base_address; // low_pc in compile_unit
};
#endif /* _DWARFLIB_H_ */
diff --git a/gprofng/src/Elf.cc b/gprofng/src/Elf.cc
index f0fd121..e63e3c3 100644
--- a/gprofng/src/Elf.cc
+++ b/gprofng/src/Elf.cc
@@ -28,6 +28,8 @@
#include "Map.h"
#include "StringBuilder.h"
#include "DbeFile.h"
+#include "DbeSession.h"
+#include "Dwarf.h"
typedef uint32_t Elf32_Word;
typedef uint32_t Elf64_Word;
@@ -83,55 +85,30 @@ struct S_Elf64_Dyn
} d_un;
};
+#ifndef DEBUGDIR
+#define DEBUGDIR "/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT1
+#define EXTRA_DEBUG_ROOT1 "/usr/lib/debug"
+#endif
+#ifndef EXTRA_DEBUG_ROOT2
+#define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
+#endif
-// Symbol table
-typedef struct
-{
- Elf32_Word st_name;
- Elf32_Addr st_value;
- Elf32_Word st_size;
- unsigned char st_info; /* bind, type: ELF_32_ST_... */
- unsigned char st_other;
- Elf32_Half st_shndx; /* SHN_... */
-} Elf32_Sym;
-
-typedef struct
-{
- Elf64_Word st_name;
- unsigned char st_info; /* bind, type: ELF_64_ST_... */
- unsigned char st_other;
- Elf64_Half st_shndx; /* SHN_... */
- Elf64_Addr st_value;
- Elf64_Xword st_size;
-} Elf64_Sym;
-
-
-// Relocation
-typedef struct
-{
- Elf32_Addr r_offset;
- Elf32_Word r_info; /* sym, type: ELF32_R_... */
-} Elf32_Rel;
-
-typedef struct
-{
- Elf32_Addr r_offset;
- Elf32_Word r_info; /* sym, type: ELF32_R_... */
- Elf32_Sword r_addend;
-} Elf32_Rela;
-
-typedef struct
-{
- Elf64_Addr r_offset;
- Elf64_Xword r_info; /* sym, type: ELF64_R_... */
-} Elf64_Rel;
+static const char *debug_dirs[] = {
+ DEBUGDIR, EXTRA_DEBUG_ROOT1, EXTRA_DEBUG_ROOT2, "."
+};
-typedef struct
+template<> void Vector<asymbol *>::dump (const char *msg)
{
- Elf64_Addr r_offset;
- Elf64_Xword r_info; /* sym, type: ELF64_R_... */
- Elf64_Sxword r_addend;
-} Elf64_Rela;
+ Dprintf (1, NTXT ("\nFile: %s Vector<asymbol *> [%ld]\n"),
+ msg ? msg : "NULL", (long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ asymbol *sym = get (i);
+ Dprintf (1, " %3ld %s\n", i, sym->name);
+ }
+}
int Elf::bfd_status = -1;
@@ -149,6 +126,8 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
ancillary_files = NULL;
elfSymbols = NULL;
gnu_debug_file = NULL;
+ gnu_debugalt_file = NULL;
+ sections = NULL;
dbeFile = NULL;
abfd = NULL;
bfd_symcnt = -1;
@@ -196,23 +175,13 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
}
status = ELF_ERR_NONE;
-#if ARCH(SPARC)
- need_swap_endian = is_Intel ();
-#else
- need_swap_endian = !is_Intel ();
-#endif
-
+ need_swap_endian = DbeSession::is_bigendian () != bfd_big_endian (abfd);
analyzerInfo = 0;
- SUNW_ldynsym = 0;
- gnuLink = 0;
stab = 0;
- stabStr = 0;
stabIndex = 0;
stabIndexStr = 0;
stabExcl = 0;
stabExclStr = 0;
- symtab = 0;
- dynsym = 0;
info = 0;
plt = 0;
dwarf = false;
@@ -234,20 +203,12 @@ Elf::Elf (char *filename) : DbeMessages (), Data_window (filename)
stabExcl = sec;
else if (streq (name, NTXT (".stab.exclstr")))
stabExclStr = sec;
- else if (streq (name, NTXT (".gnu_debuglink")))
- gnuLink = sec;
else if (streq (name, NTXT (".__analyzer_info")))
analyzerInfo = sec;
else if (streq (name, NTXT (".info")))
info = true;
else if (streq (name, NTXT (".plt")))
plt = sec;
- else if (streq (name, NTXT (".SUNW_ldynsym")))
- SUNW_ldynsym = sec;
- else if (streq (name, NTXT (".dynsym")))
- dynsym = sec;
- else if (streq (name, NTXT (".symtab")))
- symtab = sec;
else if (strncmp (name, NTXT (".debug"), 6) == 0)
dwarf = true;
}
@@ -276,6 +237,12 @@ Elf::~Elf ()
}
free (data);
}
+ if (sections)
+ {
+ for (int i = 0; i < (int) ehdrp->e_shnum; i++)
+ delete sections[i];
+ free (sections);
+ }
if (ancillary_files)
{
ancillary_files->destroy ();
@@ -283,6 +250,7 @@ Elf::~Elf ()
}
delete elfSymbols;
delete gnu_debug_file;
+ delete gnu_debugalt_file;
delete dbeFile;
delete synthsym;
free (bfd_sym);
@@ -405,9 +373,36 @@ Elf::get_sec_name (unsigned int sec)
return elf_strptr (ehdrp->e_shstrndx, shdr->sh_name);
}
+DwrSec *
+Elf::get_dwr_section (const char *sec_name)
+{
+ int sec_num = elf_get_sec_num (sec_name);
+ if (sec_num > 0)
+ {
+ if (sections == NULL)
+ {
+ sections = (DwrSec **) xmalloc (ehdrp->e_shnum * sizeof (DwrSec *));
+ for (int i = 0; i < (int) ehdrp->e_shnum; i++)
+ sections[i] = NULL;
+ }
+ if (sections[sec_num] == NULL)
+ {
+ Elf_Data *elfData = elf_getdata (sec_num);
+ if (elfData)
+ sections[sec_num] = new DwrSec ((unsigned char *) elfData->d_buf,
+ elfData->d_size, need_swap_endian,
+ elf_getclass () == ELFCLASS32);
+ }
+ return sections[sec_num];
+ }
+ return NULL;
+}
+
Elf_Data *
Elf::elf_getdata (unsigned int sec)
{
+ if (sec == 0)
+ return NULL;
if (data == NULL)
{
data = (Elf_Data **) xmalloc (ehdrp->e_shnum * sizeof (Elf_Data *));
@@ -572,50 +567,6 @@ Elf::elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic)
return asym;
}
-Elf_Internal_Rela *
-Elf::elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst)
-{
- if (dst == NULL || edta == NULL || edta->d_buf == NULL)
- return NULL;
- if (elf_getclass () == ELFCLASS32)
- {
- Elf32_Rel *rel = ((Elf32_Rel *) edta->d_buf) + ndx;
- dst->r_offset = decode (rel->r_offset);
- dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rel->r_info)),
- ELF32_R_TYPE (decode (rel->r_info)));
- }
- else
- {
- Elf64_Rel *rel = ((Elf64_Rel *) edta->d_buf) + ndx;
- dst->r_offset = decode (rel->r_offset);
- dst->r_info = decode (rel->r_info);
- }
- return dst;
-}
-
-Elf_Internal_Rela *
-Elf::elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst)
-{
- if (dst == NULL || edta == NULL || edta->d_buf == NULL)
- return NULL;
- if (elf_getclass () == ELFCLASS32)
- {
- Elf32_Rela *rela = ((Elf32_Rela *) edta->d_buf) + ndx;
- dst->r_offset = decode (rela->r_offset);
- dst->r_addend = decode (rela->r_addend);
- dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rela->r_info)),
- ELF32_R_TYPE (decode (rela->r_info)));
- }
- else
- {
- Elf64_Rela *rela = ((Elf64_Rela *) edta->d_buf) + ndx;
- dst->r_offset = decode (rela->r_offset);
- dst->r_addend = decode (rela->r_addend);
- dst->r_info = decode (rela->r_info);
- }
- return dst;
-}
-
Elf64_Ancillary *
Elf::elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst)
{
@@ -676,25 +627,54 @@ Elf::get_related_file (const char *lo_name, const char *nm)
return NULL;
}
-Elf *
-Elf::find_ancillary_files (char *lo_name)
+static char *
+find_file (char *(bfd_func) (bfd *, const char *), bfd *abfd)
{
- // read the .gnu_debuglink and .SUNW_ancillary seections
- if (gnu_debug_file)
- return gnu_debug_file;
- unsigned int sec = elf_get_sec_num (NTXT (".gnu_debuglink"));
- if (sec > 0)
+ char *fnm = NULL;
+ for (size_t i = 0; i < ARR_SIZE (debug_dirs); i++)
+ {
+ fnm = bfd_func (abfd, debug_dirs[i]);
+ if (fnm)
+ break;
+ }
+ Dprintf (DUMP_DWARFLIB, "FOUND: gnu_debug_file: %s --> %s\n",
+ abfd->filename, fnm);
+ return fnm;
+}
+
+void
+Elf::find_gnu_debug_files ()
+{
+ char *fnm;
+ if (gnu_debug_file == NULL)
{
- Elf_Data *dp = elf_getdata (sec);
- if (dp)
+ fnm = find_file (bfd_follow_gnu_debuglink, abfd);
+ if (fnm)
{
- gnu_debug_file = get_related_file (lo_name, (char *) (dp->d_buf));
+ gnu_debug_file = Elf::elf_begin (fnm);
+ free (fnm);
if (gnu_debug_file)
- return gnu_debug_file;
+ gnu_debug_file->find_gnu_debug_files ();
+ }
+ }
+ if (gnu_debugalt_file == NULL)
+ {
+ fnm = find_file (bfd_follow_gnu_debugaltlink, abfd);
+ if (fnm)
+ {
+ gnu_debugalt_file = Elf::elf_begin (fnm);
+ free (fnm);
}
}
+}
- sec = elf_get_sec_num (NTXT (".SUNW_ancillary"));
+void
+Elf::find_ancillary_files (const char *lo_name)
+{
+ // read the .SUNW_ancillary section
+ if (ancillary_files != NULL)
+ return;
+ unsigned int sec = elf_get_sec_num (".SUNW_ancillary");
if (sec > 0)
{
Elf_Internal_Shdr *shdr = get_shdr (sec);
@@ -755,7 +735,6 @@ Elf::find_ancillary_files (char *lo_name)
}
}
}
- return NULL;
}
void
@@ -828,6 +807,8 @@ Elf::get_funcname_in_plt (uint64_t pc)
for (long i = 0; i < bfd_synthcnt; i++)
synthsym->append (bfd_synthsym + i);
synthsym->sort (cmp_sym_addr);
+ if (DUMP_ELF_SYM)
+ synthsym->dump (get_location ());
}
asymbol sym, *symp = &sym;
diff --git a/gprofng/src/Elf.h b/gprofng/src/Elf.h
index b324c39..2d227f7 100644
--- a/gprofng/src/Elf.h
+++ b/gprofng/src/Elf.h
@@ -32,13 +32,12 @@
class Symbol;
class DbeFile;
+class DwrSec;
template <class ITEM> class Vector;
template <typename Key_t, typename Value_t> class Map;
-#define GELF_R_SYM(info) ((info)>>32)
#define GELF_ST_TYPE(info) ((info) & 0xf)
#define GELF_ST_BIND(info) ((info) >> 4)
-#define GELF_R_TYPE(info) ((((uint64_t)(info))<<56)>>56)
#define SHF_SUNW_ABSENT 0x00200000 /* section data not present */
#define SEC_DECOMPRESSED 0x00400000 /* bfd allocated this memory */
@@ -94,10 +93,15 @@ public:
char *elf_strptr (unsigned int sec, uint64_t off);
long elf_getSymCount (bool is_dynamic);
asymbol *elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic);
- Elf_Internal_Rela *elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst);
- Elf_Internal_Rela *elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst);
Elf64_Ancillary *elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst);
- Elf *find_ancillary_files (char *lo_name); // read the .gnu_debuglink and .SUNW_ancillary seections
+
+ // read the .SUNW_ancillary section
+ void find_ancillary_files (const char *lo_name);
+
+ // read the .gnu_debuglink and .gnu_debugaltlink sections
+ void find_gnu_debug_files ();
+
+ DwrSec *get_dwr_section (const char *sec_name); // Used in Dwarf reader
const char *get_funcname_in_plt (uint64_t pc);
char *get_location ();
char *dump ();
@@ -130,9 +134,10 @@ public:
Elf_status status;
Vector<Elf*> *ancillary_files;
Elf *gnu_debug_file;
+ Elf *gnu_debugalt_file; // if the .gun_debugaltlink section presents
DbeFile *dbeFile;
Map<const char*, Symbol*> *elfSymbols;
- unsigned int gnuLink, analyzerInfo, SUNW_ldynsym, stab, stabStr, symtab, dynsym;
+ unsigned int analyzerInfo, stab, stabStr;
unsigned int stabIndex, stabIndexStr, stabExcl, stabExclStr, info, plt;
bool dwarf;
@@ -143,6 +148,7 @@ protected:
int elf_datatype;
Elf_Internal_Ehdr *ehdrp;
Elf_Data **data;
+ DwrSec **sections;
bfd *abfd;
static int bfd_status;
long bfd_symcnt;
@@ -154,28 +160,4 @@ protected:
Vector <asymbol *> *synthsym;
};
-
-class ElfReloc
-{
-public:
- struct Sreloc
- {
- long long offset;
- long long value;
- int stt_type;
- };
-
- static ElfReloc *get_elf_reloc (Elf *elf, char *sec_name, ElfReloc *rlc);
- ElfReloc (Elf *_elf);
- ~ElfReloc ();
- long long get_reloc_addr (long long offset);
- void dump ();
- void dump_rela_debug_sec (int sec);
-
-private:
- Elf *elf;
- Vector<Sreloc *> *reloc;
- int cur_reloc_ind;
-};
-
#endif
diff --git a/gprofng/src/Experiment.cc b/gprofng/src/Experiment.cc
index 45550e8..2768927 100644
--- a/gprofng/src/Experiment.cc
+++ b/gprofng/src/Experiment.cc
@@ -541,10 +541,14 @@ Experiment::ExperimentHandler::startElement (char*, char*, char *qName, Attribut
exp->platform = RISCV;
else
exp->platform = Sparc;
- exp->need_swap_endian = (DbeSession::platform == Sparc) ?
- (exp->platform != Sparc) : (exp->platform == Sparc);
exp->architecture = xstrdup (str);
}
+ str = attrs->getValue (NTXT ("bigendian"));
+ if (str != NULL)
+ {
+ exp->bigendian = *str == '1';
+ exp->need_swap_endian = DbeSession::is_bigendian () != exp->bigendian;
+ }
str = attrs->getValue (NTXT ("pagesz"));
if (str != NULL)
exp->page_size = atoi (str);
@@ -1314,6 +1318,7 @@ Experiment::Experiment ()
exp_maj_version = 0;
exp_min_version = 0;
platform = Unknown;
+ bigendian = DbeSession::is_bigendian(); // can be changed in log.xml reading
wsize = Wnone;
page_size = 4096;
npages = 0;
@@ -6806,7 +6811,8 @@ Experiment::copy_file_to_common_archive (const char *name, const char *aname,
* @return 0 - success
*/
int
-Experiment::copy_file (char *name, char *aname, int hide_msg, char *common_archive, int relative_path)
+Experiment::copy_file (const char *name, const char *aname, int hide_msg,
+ const char *common_archive, int relative_path)
{
if (common_archive)
{
diff --git a/gprofng/src/Experiment.h b/gprofng/src/Experiment.h
index 2047a15..9a3d226 100644
--- a/gprofng/src/Experiment.h
+++ b/gprofng/src/Experiment.h
@@ -135,6 +135,7 @@ public:
// for current experiment, i.e. 8 for 32bit addresses
int broken; // If SP_JCMD_RUN line not seen
int obsolete; // If pointer file experiment detected
+ bool bigendian; // the experiment was created on a big_endian machine
bool hwc_default; // True if HW counters were enabled by default
int hwc_bogus; // Count of bogus HWC packets
int hwc_lost_int; // Count of packets reflecting lost interrupt
@@ -266,8 +267,8 @@ public:
static int copy_file_to_archive (const char *name, const char *aname, int hide_msg);
static int copy_file_to_common_archive (const char *name, const char *aname,
int hide_msg, const char *common_archive, int relative_path = 0);
- static int copy_file (char *name, char *aname, int hide_msg,
- char *common_archive = NULL, int relative_path = 0);
+ static int copy_file (const char *name, const char *aname, int hide_msg,
+ const char *common_archive = NULL, int relative_path = 0);
// get_raw_events()
// action: get unfiltered packets, loading them if required
diff --git a/gprofng/src/LoadObject.cc b/gprofng/src/LoadObject.cc
index 1ca6ab6..7b4bef2 100644
--- a/gprofng/src/LoadObject.cc
+++ b/gprofng/src/LoadObject.cc
@@ -20,6 +20,7 @@
#include "config.h"
#include <errno.h>
+#include <libgen.h>
#include "util.h"
#include "StringBuilder.h"
@@ -86,7 +87,6 @@ LoadObject::LoadObject (const char *loname)
size = 0;
type = SEG_UNKNOWN;
isReadStabs = false;
- need_swap_endian = false;
instHTable = new DbeInstr*[LO_InstHTableSize];
for (int i = 0; i < LO_InstHTableSize; i++)
instHTable[i] = NULL;
@@ -102,7 +102,6 @@ LoadObject::LoadObject (const char *loname)
noname = dbeSession->createUnknownModule (this);
modules->put (noname->get_name (), noname);
pathname = NULL;
- arch_name = NULL;
runTimePath = NULL;
objStabs = NULL;
firstExp = NULL;
@@ -135,7 +134,6 @@ LoadObject::~LoadObject ()
delete modules;
delete elf_lo;
free (pathname);
- free (arch_name);
free (runTimePath);
delete objStabs;
delete warnq;
@@ -167,45 +165,66 @@ LoadObject::get_elf ()
{
case Elf::ELF_ERR_CANT_OPEN_FILE:
append_msg (CMSG_ERROR, GTXT ("Cannot open ELF file `%s'"), fnm);
- break;
+ return NULL;
case Elf::ELF_ERR_BAD_ELF_FORMAT:
default:
append_msg (CMSG_ERROR, GTXT ("Cannot read ELF header of `%s'"),
fnm);
- break;
+ return NULL;
}
+ if (dbeFile->inArchive)
+ {
+ // Try to find gnu_debug and gnu debug_alt files in archive
+ char *nm = dbe_sprintf ("%s_debug", fnm);
+ elf_lo->gnu_debug_file = Elf::elf_begin (nm);
+ free (nm);
+ if (elf_lo->gnu_debug_file)
+ {
+ nm = dbe_sprintf ("%s_debug_alt", fnm);
+ elf_lo->gnu_debug_file->gnu_debugalt_file = Elf::elf_begin (nm);
+ free (nm);
+ }
+ nm = dbe_sprintf ("%s_alt", fnm);
+ elf_lo->gnu_debugalt_file = Elf::elf_begin (nm);
+ free (nm);
+ }
+ else if (checksum != 0 && elf_lo->elf_checksum () != 0 &&
+ checksum != elf_lo->elf_checksum ())
+ {
+ char *msg = dbe_sprintf (GTXT ("%s has an unexpected checksum value;"
+ "perhaps it was rebuilt. File ignored"),
+ dbeFile->get_location ());
+ commentq->append (new Emsg (CMSG_ERROR, msg));
+ delete msg;
+ delete elf_lo;
+ elf_lo = NULL;
+ return NULL;
+ }
+ elf_lo->find_gnu_debug_files ();
+ elf_lo->find_ancillary_files (get_pathname ());
}
return elf_lo;
}
Stabs *
-LoadObject::openDebugInfo (char *fname, Stabs::Stab_status *stp)
+LoadObject::openDebugInfo (Stabs::Stab_status *stp)
{
if (objStabs == NULL)
{
- if (fname == NULL)
- return NULL;
- objStabs = new Stabs (fname, get_pathname ());
- Stabs::Stab_status st = objStabs->get_status ();
- if ((st == Stabs::DBGD_ERR_NONE) && (checksum != 0))
+ Stabs::Stab_status st = Stabs::DBGD_ERR_BAD_ELF_LIB;
+ Elf *elf = get_elf ();
+ if (elf)
{
- Elf *elf = get_elf ();
- if (elf && (checksum != elf->elf_checksum ()))
+ objStabs = new Stabs (elf, get_pathname ());
+ st = objStabs->get_status ();
+ if (st != Stabs::DBGD_ERR_NONE)
{
- char *buf = dbe_sprintf (GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"),
- fname);
- commentq->append (new Emsg (CMSG_ERROR, buf));
- delete buf;
- st = Stabs::DBGD_ERR_CHK_SUM;
+ delete objStabs;
+ objStabs = NULL;
}
}
if (stp)
*stp = st;
- if (st != Stabs::DBGD_ERR_NONE)
- {
- delete objStabs;
- objStabs = NULL;
- }
}
return objStabs;
}
@@ -298,18 +317,21 @@ LoadObject::dump_functions (FILE *out)
if (fitem->alias && fitem->alias != fitem)
fprintf (out, "id %6llu, @0x%llx - %s == alias of '%s'\n",
(ull_t) fitem->id, (ull_t) fitem->img_offset,
- fitem->get_name (), fitem->alias->get_name ());
+ fitem->get_mangled_name (), fitem->alias->get_mangled_name ());
else
{
mname = fitem->module ? fitem->module->file_name : noname->file_name;
sname = fitem->getDefSrcName ();
- fprintf (out,
- "id %6llu, @0x%llx - 0x%llx [save 0x%llx] o-%lld sz-%lld %s (module = %s)",
- (ull_t) fitem->id, (ull_t) fitem->img_offset,
- (ull_t) (fitem->img_offset + fitem->size),
- (ull_t) fitem->save_addr, (ull_t) fitem->img_offset,
- (ll_t) fitem->size, fitem->get_name (), mname);
- if (sname && !streq (sname, mname))
+ fprintf (out, "id %6llu, @0x%llx-0x%llx sz-%lld", (ull_t) fitem->id,
+ (ull_t) fitem->img_offset,
+ (ull_t) (fitem->img_offset + fitem->size),
+ (ll_t) fitem->size);
+ if (fitem->save_addr != 0)
+ fprintf (out, " [save 0x%llx]", (ull_t) fitem->save_addr);
+ if (strcmp (fitem->get_mangled_name (), fitem->get_name ()) != 0)
+ fprintf (out, " [%s]", fitem->get_mangled_name ());
+ fprintf (out, " %s (module = %s)", fitem->get_name (), mname);
+ if (sname && strcmp (basename (sname), basename (mname)) != 0)
fprintf (out, " (Source = %s)", sname);
fprintf (out, "\n");
}
@@ -557,7 +579,7 @@ fixFuncAlias (Vector<Function*> *SymLst)
void
LoadObject::post_process_functions ()
{
- if (flags & SEG_FLAG_DYNAMIC || platform == Java)
+ if ((flags & SEG_FLAG_DYNAMIC) != 0 || platform == Java)
return;
char *msg = GTXT ("Processing Load Object Data");
@@ -723,21 +745,8 @@ LoadObject::read_stabs ()
delete msg;
return ARCHIVE_ERR_OPEN;
}
- else if (checksum != 0 && checksum != elf->elf_checksum ())
- {
- char *msg = dbe_sprintf (GTXT ("%s has an unexpected checksum value;"
- "perhaps it was rebuilt. File ignored"),
- dbeFile->get_location ());
- commentq->append (new Emsg (CMSG_ERROR, msg));
- delete msg;
- return ARCHIVE_ERR_OPEN;
- }
Stabs::Stab_status status = Stabs::DBGD_ERR_CANT_OPEN_FILE;
- char *location = dbeFile->get_location (true);
- if (location == NULL)
- return ARCHIVE_ERR_OPEN;
-
- if (openDebugInfo (location, &status))
+ if (openDebugInfo (&status))
{
status = objStabs->read_archive (this);
isRelocatable = objStabs->is_relocatable ();
diff --git a/gprofng/src/LoadObject.h b/gprofng/src/LoadObject.h
index 14dfe26..c93594b 100644
--- a/gprofng/src/LoadObject.h
+++ b/gprofng/src/LoadObject.h
@@ -117,13 +117,6 @@ public:
return pathname;
}
- void
- set_archname (char *aname)
- {
- free (arch_name);
- arch_name = aname;
- }
-
bool
is_relocatable ()
{
@@ -144,7 +137,7 @@ public:
Module *get_comparable_Module (Module *mod);
void append_module (Module *mod);
Elf *get_elf ();
- Stabs *openDebugInfo (char *fname, Stabs::Stab_status *stp = NULL);
+ Stabs *openDebugInfo (Stabs::Stab_status *stp = NULL);
Arch_status read_stabs ();
Arch_status sync_read_stabs ();
void post_process_functions ();
@@ -167,7 +160,6 @@ public:
unsigned int flags; // SEG_FLAG_*
bool isReadStabs;
- bool need_swap_endian;
int seg_idx; // for compatibility (ADDRESS)
seg_type type;
int64_t size; // size of loadobject in bytes
@@ -193,7 +185,6 @@ private:
char *pathname; // User name of object file
ino64_t inode; // inode number of segment file
bool isRelocatable; // is relocatable .o
- char *arch_name; // .archive name
Emsgqueue *warnq;
Emsgqueue *commentq;
Function **funcHTable; // hash table for functions
diff --git a/gprofng/src/Makefile.am b/gprofng/src/Makefile.am
index 0465cdb..f6d3f5d 100644
--- a/gprofng/src/Makefile.am
+++ b/gprofng/src/Makefile.am
@@ -78,6 +78,7 @@ CCSOURCES = \
Stabs.cc \
Stats_data.cc \
StringBuilder.cc \
+ Symbol.cc \
Table.cc \
QLParser.tab.cc \
dbe_collctrl.cc \
diff --git a/gprofng/src/Makefile.in b/gprofng/src/Makefile.in
index 9f07986..0cdd444 100644
--- a/gprofng/src/Makefile.in
+++ b/gprofng/src/Makefile.in
@@ -174,7 +174,7 @@ am__objects_1 = Application.lo BaseMetric.lo BaseMetricTreeNode.lo \
MemorySpace.lo Metric.lo MetricList.lo Module.lo Ovw_data.lo \
PRBTree.lo PathTree.lo PreviewExp.lo Print.lo \
SAXParserFactory.lo Sample.lo Settings.lo SourceFile.lo \
- Stabs.lo Stats_data.lo StringBuilder.lo Table.lo \
+ Stabs.lo Stats_data.lo StringBuilder.lo Symbol.lo Table.lo \
QLParser.tab.lo dbe_collctrl.lo i18n.lo parse.lo UserLabel.lo \
util.lo Dbe.lo
am__objects_2 = dbe_hwcdrv.lo dbe_hwcfuncs.lo dbe_hwctable.lo \
@@ -505,6 +505,7 @@ CCSOURCES = \
Stabs.cc \
Stats_data.cc \
StringBuilder.cc \
+ Symbol.cc \
Table.cc \
QLParser.tab.cc \
dbe_collctrl.cc \
@@ -777,6 +778,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Stabs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Stats_data.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StringBuilder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Symbol.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Table.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UserLabel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checks.Po@am__quote@
diff --git a/gprofng/src/Module.cc b/gprofng/src/Module.cc
index a62d3e8..55091ad 100644
--- a/gprofng/src/Module.cc
+++ b/gprofng/src/Module.cc
@@ -131,7 +131,7 @@ Stabs *
Module::openDebugInfo ()
{
setFile ();
- objStabs = loadobject->openDebugInfo (disPath);
+ objStabs = loadobject->openDebugInfo ();
return objStabs;
}
diff --git a/gprofng/src/Stabs.cc b/gprofng/src/Stabs.cc
index b98ac28..116316e 100644
--- a/gprofng/src/Stabs.cc
+++ b/gprofng/src/Stabs.cc
@@ -35,10 +35,7 @@
#include "StringBuilder.h"
#include "DbeFile.h"
#include "StringMap.h"
-
-#define DISASM_REL_NONE 0 /* symtab search only */
-#define DISASM_REL_ONLY 1 /* relocation search only */
-#define DISASM_REL_TARG 2 /* relocatoin then symtab */
+#include "Symbol.h"
///////////////////////////////////////////////////////////////////////////////
// class StabReader
@@ -62,105 +59,6 @@ private:
int StabEntSize;
};
-///////////////////////////////////////////////////////////////////////////////
-// class Symbol
-
-class Symbol
-{
-public:
- Symbol (Vector<Symbol*> *vec = NULL);
-
- ~Symbol ()
- {
- free (name);
- }
-
- inline Symbol *
- cardinal ()
- {
- return alias ? alias : this;
- }
-
- static void dump (Vector<Symbol*> *vec, char*msg);
-
- Function *func;
- Sp_lang_code lang_code;
- uint64_t value; // st_value used in sym_name()
- uint64_t save;
- int64_t size;
- uint64_t img_offset; // image offset in the ELF file
- char *name;
- Symbol *alias;
- int local_ind;
- int flags;
- bool defined;
-};
-
-Symbol::Symbol (Vector<Symbol*> *vec)
-{
- func = NULL;
- lang_code = Sp_lang_unknown;
- value = 0;
- save = 0;
- size = 0;
- img_offset = 0;
- name = NULL;
- alias = NULL;
- local_ind = -1;
- flags = 0;
- defined = false;
- if (vec)
- vec->append (this);
-}
-
-void
-Symbol::dump (Vector<Symbol*> *vec, char*msg)
-{
- if (!DUMP_ELF_SYM || vec == NULL || vec->size () == 0)
- return;
- printf (NTXT ("======= Symbol::dump: %s =========\n"
- " value | img_offset | flags|local_ind|\n"), msg);
- for (int i = 0; i < vec->size (); i++)
- {
- Symbol *sp = vec->fetch (i);
- printf (NTXT (" %3d %8lld |0x%016llx |%5d |%8d |%s\n"),
- i, (long long) sp->value, (long long) sp->img_offset, sp->flags,
- sp->local_ind, sp->name ? sp->name : NTXT ("NULL"));
- }
- printf (NTXT ("\n===== END of Symbol::dump: %s =========\n\n"), msg);
-}
-
-// end of class Symbol
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// class Reloc
-class Reloc
-{
-public:
- Reloc ();
- ~Reloc ();
- uint64_t type;
- uint64_t value;
- uint64_t addend;
- char *name;
-};
-
-Reloc::Reloc ()
-{
- type = 0;
- value = 0;
- addend = 0;
- name = NULL;
-}
-
-Reloc::~Reloc ()
-{
- free (name);
-}
-// end of class Reloc
-///////////////////////////////////////////////////////////////////////////////
-
enum
{
SYM_PLT = 1 << 0,
@@ -232,15 +130,6 @@ SymImgOffsetCmp (const void *a, const void *b)
(item1->img_offset == item2->img_offset) ? SymNameCmp (a, b) : -1;
}
-static int
-RelValueCmp (const void *a, const void *b)
-{
- Reloc *item1 = *((Reloc **) a);
- Reloc *item2 = *((Reloc **) b);
- return (item1->value > item2->value) ? 1 :
- (item1->value == item2->value) ? 0 : -1;
-}
-
/* Remove all duplicate symbols which can be in SymLst. The
duplication is due to processing of both static and dynamic
symbols. This function is called before computing symbol
@@ -252,7 +141,6 @@ Stabs::removeDupSyms ()
long ind, i, last;
Symbol *symA, *symB;
SymLst->sort (SymImgOffsetCmp);
- dump ();
last = 0;
ind = SymLst->size ();
@@ -275,42 +163,26 @@ Stabs::removeDupSyms ()
SymLst->truncate (last);
}
-Stabs *
-Stabs::NewStabs (char *_path, char *lo_name)
-{
- Stabs *stabs = new Stabs (_path, lo_name);
- if (stabs->status != Stabs::DBGD_ERR_NONE)
- {
- delete stabs;
- return NULL;
- }
- return stabs;
-}
-
-Stabs::Stabs (char *_path, char *_lo_name)
+Stabs::Stabs (Elf *elf, char *_lo_name)
{
- path = dbe_strdup (_path);
+ elfDis = elf;
+ elfDbg = elf->gnu_debug_file ? elf->gnu_debug_file : elf;
+ path = dbe_strdup (elf->get_location ());
lo_name = dbe_strdup (_lo_name);
SymLstByName = NULL;
pltSym = NULL;
SymLst = new Vector<Symbol*>;
- RelLst = new Vector<Reloc*>;
- RelPLTLst = new Vector<Reloc*>;
LocalLst = new Vector<Symbol*>;
LocalFile = new Vector<char*>;
LocalFileIdx = new Vector<int>;
last_PC_to_sym = NULL;
dwarf = NULL;
- elfDbg = NULL;
- elfDis = NULL;
stabsModules = NULL;
textsz = 0;
wsize = Wnone;
st_check_symtab = false;
status = DBGD_ERR_NONE;
- if (openElf (false) == NULL)
- return;
switch (elfDis->elf_getclass ())
{
case ELFCLASS32:
@@ -320,6 +192,31 @@ Stabs::Stabs (char *_path, char *_lo_name)
wsize = W64;
break;
}
+ switch (elfDis->elf_getehdr ()->e_machine)
+ {
+ case EM_SPARC:
+ platform = Sparc;
+ break;
+ case EM_SPARC32PLUS:
+ platform = Sparcv8plus;
+ break;
+ case EM_SPARCV9:
+ platform = Sparcv9;
+ break;
+ case EM_386:
+ // case EM_486:
+ platform = Intel;
+ break;
+ case EM_X86_64:
+ platform = Amd64;
+ break;
+ case EM_AARCH64:
+ platform = Aarch64;
+ break;
+ default:
+ platform = Unknown;
+ break;
+ }
isRelocatable = elfDis->elf_getehdr ()->e_type == ET_REL;
for (unsigned int pnum = 0; pnum < elfDis->elf_getehdr ()->e_phnum; pnum++)
{
@@ -341,10 +238,7 @@ Stabs::~Stabs ()
{
delete SymLstByName;
Destroy (SymLst);
- Destroy (RelLst);
- Destroy (RelPLTLst);
Destroy (LocalFile);
- delete elfDis;
delete dwarf;
delete LocalLst;
delete LocalFileIdx;
@@ -354,90 +248,11 @@ Stabs::~Stabs ()
}
Elf *
-Stabs::openElf (char *fname, Stab_status &st)
-{
- Elf::Elf_status elf_status;
- Elf *elf = Elf::elf_begin (fname, &elf_status);
- if (elf == NULL)
- {
- switch (elf_status)
- {
- case Elf::ELF_ERR_CANT_OPEN_FILE:
- case Elf::ELF_ERR_CANT_MMAP:
- case Elf::ELF_ERR_BIG_FILE:
- st = DBGD_ERR_CANT_OPEN_FILE;
- break;
- case Elf::ELF_ERR_BAD_ELF_FORMAT:
- default:
- st = DBGD_ERR_BAD_ELF_FORMAT;
- break;
- }
- return NULL;
- }
- if (elf->elf_version (EV_CURRENT) == EV_NONE)
- {
- // ELF library out of date
- delete elf;
- st = DBGD_ERR_BAD_ELF_LIB;
- return NULL;
- }
-
- Elf_Internal_Ehdr *ehdrp = elf->elf_getehdr ();
- if (ehdrp == NULL)
- {
- // check machine
- delete elf;
- st = DBGD_ERR_BAD_ELF_FORMAT;
- return NULL;
- }
- switch (ehdrp->e_machine)
- {
- case EM_SPARC:
- platform = Sparc;
- break;
- case EM_SPARC32PLUS:
- platform = Sparcv8plus;
- break;
- case EM_SPARCV9:
- platform = Sparcv9;
- break;
- case EM_386:
- // case EM_486:
- platform = Intel;
- break;
- case EM_X86_64:
- platform = Amd64;
- break;
- case EM_AARCH64:
- platform = Aarch64;
- break;
- default:
- platform = Unknown;
- break;
- }
- return elf;
-}
-
-Elf *
Stabs::openElf (bool dbg_info)
{
- if (status != DBGD_ERR_NONE)
- return NULL;
- if (elfDis == NULL)
- {
- elfDis = openElf (path, status);
- if (elfDis == NULL)
- return NULL;
- }
- if (!dbg_info)
- return elfDis;
- if (elfDbg == NULL)
- {
- elfDbg = elfDis->find_ancillary_files (lo_name);
- if (elfDbg == NULL)
- elfDbg = elfDis;
- }
- return elfDbg;
+ if (dbg_info)
+ return elfDbg;
+ return elfDis;
}
bool
@@ -458,42 +273,6 @@ Stabs::read_symbols (Vector<Function*> *functions)
return true;
}
-char *
-Stabs::sym_name (uint64_t target, uint64_t instr, int flag)
-{
- long index;
- if (flag == DISASM_REL_ONLY || flag == DISASM_REL_TARG)
- {
- Reloc *relptr = new Reloc;
- relptr->value = instr;
- index = RelLst->bisearch (0, -1, &relptr, RelValueCmp);
- if (index >= 0)
- {
- delete relptr;
- return RelLst->fetch (index)->name;
- }
- if (!is_relocatable ())
- {
- relptr->value = target;
- index = RelPLTLst->bisearch (0, -1, &relptr, RelValueCmp);
- if (index >= 0)
- {
- delete relptr;
- return RelPLTLst->fetch (index)->name;
- }
- }
- delete relptr;
- }
- if (flag == DISASM_REL_NONE || flag == DISASM_REL_TARG || !is_relocatable ())
- {
- Symbol *sptr;
- sptr = map_PC_to_sym (target);
- if (sptr && sptr->value == target)
- return sptr->name;
- }
- return NULL;
-}
-
Symbol *
Stabs::map_PC_to_sym (uint64_t pc)
{
@@ -1706,7 +1485,8 @@ Stabs::fixSymtabAlias ()
for (; i < k; i++)
{
sym = SymLst->fetch (i);
- sym->alias = bestAlias;
+ if (sym != bestAlias)
+ sym->alias = bestAlias;
sym->size = maxSize;
}
i--;
@@ -1761,10 +1541,12 @@ Stabs::readSymSec (Elf *elf, bool is_dynamic)
if (asym == NULL)
break;
const char *st_name = bfd_asymbol_name (asym);
+ if (st_name == NULL)
+ continue;
switch (GELF_ST_TYPE (Sym.st_info))
{
case STT_FUNC:
- if (Sym.st_size == 0)
+ if (Sym.st_size == 0 || ELF_ST_BIND (Sym.st_info) == STB_WEAK)
break;
if (Sym.st_shndx == 0)
{
@@ -1839,8 +1621,7 @@ Stabs::readSymSec (Elf *elf, bool is_dynamic)
fixSymtabAlias ();
SymLst->sort (SymValueCmp);
get_save_addr (elf->need_swap_endian);
- dump ();
-}//check_Symtab
+}
void
Stabs::get_save_addr (bool need_swap_endian)
@@ -2281,57 +2062,6 @@ Stabs::append_Function (Module *module, char *fname)
return func;
}
-Function *
-Stabs::append_Function (Module *module, char *linkerName, uint64_t pc)
-{
- Dprintf (DEBUG_STABS, NTXT ("Stabs::append_Function: module=%s linkerName=%s pc=0x%llx\n"),
- STR (module->get_name ()), STR (linkerName), (unsigned long long) pc);
- long i;
- Symbol *sitem = NULL, *sp;
- Function *func;
- sp = new Symbol;
- if (pc)
- {
- sp->value = pc;
- i = SymLst->bisearch (0, -1, &sp, SymFindCmp);
- if (i != -1)
- sitem = SymLst->fetch (i);
- }
-
- if (!sitem && linkerName)
- {
- if (SymLstByName == NULL)
- {
- SymLstByName = SymLst->copy ();
- SymLstByName->sort (SymNameCmp);
- }
- sp->name = linkerName;
- i = SymLstByName->bisearch (0, -1, &sp, SymNameCmp);
- sp->name = NULL;
- if (i != -1)
- sitem = SymLstByName->fetch (i);
- }
- delete sp;
-
- if (!sitem)
- return NULL;
- if (sitem->alias)
- sitem = sitem->alias;
- if (sitem->func)
- return sitem->func;
-
- sitem->func = func = dbeSession->createFunction ();
- func->img_fname = path;
- func->img_offset = sitem->img_offset;
- func->save_addr = sitem->save;
- func->size = sitem->size;
- func->module = module;
- func->set_name (sitem->name); //XXXX ?? Now call it to set obj->name
- module->functions->append (func);
- module->loadobject->functions->append (func);
- return func;
-}// Stabs::append_Function
-
Dwarf *
Stabs::openDwarf ()
{
@@ -2339,6 +2069,7 @@ Stabs::openDwarf ()
{
dwarf = new Dwarf (this);
check_Symtab ();
+ dump();
}
return dwarf;
}
@@ -2363,8 +2094,8 @@ Stabs::dump ()
printf (" %3d: %5d '%s'\n", i, LocalFileIdx->fetch (i),
LocalFile->fetch (i));
}
- Symbol::dump (SymLst, NTXT ("SymLst"));
- Symbol::dump (LocalLst, NTXT ("LocalLst"));
+ SymLst->dump ("SymLst");
+ LocalLst->dump ("LocalLst");
printf (NTXT ("\n===== END of Stabs::dump: %s =========\n\n"),
path ? path : NTXT ("NULL"));
}
diff --git a/gprofng/src/Stabs.h b/gprofng/src/Stabs.h
index d34741f..cd10c25 100644
--- a/gprofng/src/Stabs.h
+++ b/gprofng/src/Stabs.h
@@ -40,7 +40,6 @@ class ComC;
class Elf;
class Dwarf;
class Symbol;
-class Reloc;
struct cpf_stabs_t;
class SourceFile;
template <typename Key_t, typename Value_t> class Map;
@@ -77,8 +76,7 @@ class Stabs {
DBGD_ERR_CHK_SUM
};
- static Stabs *NewStabs(char *_path, char *lo_name);
- Stabs(char *_path, char *_lo_name);
+ Stabs(Elf *elf, char *_lo_name);
~Stabs();
bool is_relocatable(){ return isRelocatable; }
@@ -86,12 +84,12 @@ class Stabs {
Platform_t get_platform() { return platform; }
WSize_t get_class() { return wsize;}
Stab_status get_status() { return status;}
+ Vector<Symbol *> *get_symbols() { return SymLst; }
Stab_status read_stabs(ino64_t srcInode, Module *module, Vector<ComC*> *comComs, bool readDwarf = false);
Stab_status read_archive(LoadObject *lo);
bool read_symbols(Vector<Function*> *functions);
uint64_t mapOffsetToAddress(uint64_t img_offset);
- char *sym_name(uint64_t target, uint64_t instr, int flag);
Elf *openElf (bool dbg_info = false);
void read_hwcprof_info(Module *module);
void dump();
@@ -101,7 +99,6 @@ class Stabs {
static Function *find_func(char *fname, Vector<Function*> *functions, bool fortran, bool inner_names=false);
Module *append_Module(LoadObject *lo, char *name, int lastMod = 0);
Function *append_Function(Module *module, char *fname);
- Function *append_Function(Module *module, char *linkerName, uint64_t pc);
Function *map_PC_to_func(uint64_t pc, uint64_t &low_pc, Vector<Function*> *functions);
char *path; // path to the object file
char *lo_name; // User name of load object
@@ -135,13 +132,10 @@ class Stabs {
Symbol *pltSym;
Vector<Symbol*> *SymLst; // list of func symbols
Vector<Symbol*> *SymLstByName; // list of func symbols sorted by Name
- Vector<Reloc*> *RelLst; // list of text relocations
- Vector<Reloc*> *RelPLTLst; // list of PLT relocations
Vector<Symbol*> *LocalLst; // list of local func symbols
Vector<char*> *LocalFile; // list of local files
Vector<int> *LocalFileIdx; // start index in LocalLst
- Elf *openElf(char *fname, Stab_status &st);
Map<const char*, Symbol*> *get_elf_symbols();
Dwarf *dwarf;
diff --git a/gprofng/src/Symbol.cc b/gprofng/src/Symbol.cc
new file mode 100644
index 0000000..8cc578f
--- /dev/null
+++ b/gprofng/src/Symbol.cc
@@ -0,0 +1,218 @@
+/* Copyright (C) 2025 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 "DbeSession.h"
+#include "Function.h"
+#include "LoadObject.h"
+#include "Module.h"
+#include "Symbol.h"
+
+
+template<> void Vector<Symbol *>::dump (const char *msg)
+{
+ if (msg == NULL)
+ msg = "#";
+ Dprintf (1, NTXT ("\n%s Vector<Symbol *> [%lld]\n"), msg, (long long) size ());
+ if (size () > 0)
+ Dprintf (1, " value | img_offset | size | flags|local_ind|\n");
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ Symbol *sp = get (i);
+ Dprintf (1, " %3ld ", i);
+ sp->dump ();
+ }
+ if (size () > 0)
+ Dprintf (1, "===== END of Symbol::dump: %s =========\n\n", msg);
+}
+
+void
+Symbol::dump (const char *msg)
+{
+ if (msg)
+ Dprintf (1, "%s\n", msg);
+ Dprintf (1, "%8lld |%11lld |%6d |%5d |%8d |%s\n", (long long) value,
+ (long long) img_offset, (int) size, flags, local_ind,
+ name ? name : "NULL");
+}
+
+Symbol::Symbol (Vector<Symbol*> *vec)
+{
+ func = NULL;
+ lang_code = Sp_lang_unknown;
+ value = 0;
+ save = 0;
+ size = 0;
+ img_offset = 0;
+ name = NULL;
+ alias = NULL;
+ local_ind = -1;
+ flags = 0;
+ defined = false;
+ if (vec)
+ vec->append (this);
+}
+
+Symbol::~Symbol ()
+{
+ free (name);
+}
+
+static int
+cmpSym (const void *a, const void *b)
+{
+ Symbol *item1 = *((Symbol **) a);
+ Symbol *item2 = *((Symbol **) b);
+ return (item1->value > item2->value) ? 1 :
+ (item1->value == item2->value) ? 0 : -1;
+}
+
+static int
+cmpSymName (const void *a, const void *b)
+{
+ Symbol *item1 = *((Symbol **) a);
+ Symbol *item2 = *((Symbol **) b);
+ return strcmp (item1->name, item2->name);
+}
+
+Symbol *
+Symbol::get_symbol (Vector<Symbol*> *syms, uint64_t pc)
+{
+ if (syms != NULL && pc != 0)
+ {
+ Symbol *sp = new Symbol;
+ sp->value = pc;
+ long i = syms->bisearch (0, -1, &sp, cmpSym);
+ delete sp;
+ if (i != -1)
+ return syms->get (i)->cardinal ();
+ }
+ return NULL;
+}
+
+Symbol *
+Symbol::get_symbol (Vector<Symbol*> *syms, char *linker_name)
+{
+ if (syms != NULL && linker_name != NULL)
+ {
+ Symbol *sp = new Symbol;
+ sp->name = linker_name;
+ long i = syms->bisearch (0, -1, &sp, cmpSymName);
+ sp->name = NULL;
+ delete sp;
+ if (i != -1)
+ return syms->get (i)->cardinal ();
+ }
+ return NULL;
+}
+
+Vector<Symbol *> *
+Symbol::sort_by_name (Vector<Symbol *> *syms)
+{
+ if (VecSize (syms) == 0)
+ return NULL;
+ Vector<Symbol *> *symbols = syms->copy ();
+ symbols->sort (cmpSymName);
+ return symbols;
+}
+
+Vector<Symbol *> *
+Symbol::find_symbols (Vector<Symbol*> *syms, Vector<Range *> *ranges,
+ Vector<Symbol *> *symbols)
+{
+ // 'syms' and 'ranges' must already be sorted.
+ // return symbols matched by 'ranges'
+ if (VecSize (syms) == 0 || VecSize (ranges) == 0)
+ return NULL;
+
+ // Use binary search to find a suitable index in 'syms'
+ int ind = 0;
+ uint64_t addr = ranges->get (0)->low;
+ for (int lo = 0, hi = syms->size (); lo < hi;)
+ {
+ int mid = (hi + lo) >> 1;
+ Symbol *sym = syms->get (mid);
+ if (sym->value == addr)
+ {
+ ind = mid;
+ break;
+ }
+ else if (sym->value > addr)
+ hi = mid - 1;
+ else
+ {
+ ind = mid;
+ lo = mid + 1;
+ }
+ }
+
+ for (int i = 0, r_sz = ranges->size (), sz = syms->size (); ind < sz; ind++)
+ {
+ Symbol *sym = syms->get (ind);
+ while (i < r_sz)
+ {
+ Range *r = ranges->get (i);
+ if (sym->value < r->low)
+ break;
+ if (sym->value <= r->high)
+ {
+ symbols->append (sym);
+ break;
+ }
+ i++;
+ }
+ if (i >= r_sz)
+ break;
+ }
+ return symbols;
+}
+
+/* Create and append a new function to the 'module'.
+ * Copy attributes (size, name, etc) from Simbol, */
+Function *
+Symbol::createFunction (Module *module)
+{
+ if (func)
+ return func;
+ func = dbeSession->createFunction ();
+ func->img_fname = module->file_name;
+ func->img_offset = img_offset;
+ func->save_addr = save;
+ func->size = size;
+ func->module = module;
+ func->set_name (name);
+ module->functions->append (func);
+ module->loadobject->functions->append (func);
+ return func;
+}
+
+template<> void Vector<Range *>::dump (const char *msg)
+{
+ Dprintf (1, NTXT ("%s Vector<Range *> [%lld]\n"),
+ msg ? msg : "#", (long long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ Range *p = get (i);
+ Dprintf (1, "%3ld 0x%08llx 0x%08llx (%lld - %lld)\n", i,
+ (long long) p->low, (long long) p->high,
+ (long long) p->low, (long long) p->high);
+ }
+} \ No newline at end of file
diff --git a/gprofng/src/Symbol.h b/gprofng/src/Symbol.h
new file mode 100644
index 0000000..e9e0060
--- /dev/null
+++ b/gprofng/src/Symbol.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2025 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. */
+
+#ifndef _Symbol_h_
+#define _Symbol_h_
+
+class Function;
+class Module;
+
+class Range
+{
+public:
+ Range (uint64_t _low, uint64_t _high)
+ {
+ low = _low;
+ high = _high;
+ }
+
+ inline bool
+ inside (uint64_t val)
+ {
+ return val >= low && val < high;
+ };
+
+ uint64_t low;
+ uint64_t high;
+};
+
+class Symbol
+{
+public:
+ Symbol (Vector<Symbol *> *vec = NULL);
+ ~Symbol ();
+
+ Symbol *
+ cardinal ()
+ {
+ return alias ? alias : this;
+ }
+
+ // Find symbols in 'syms' matched by 'ranges'.
+ static Vector<Symbol *> *find_symbols (Vector<Symbol *> *syms,
+ Vector<Range *> *ranges, Vector<Symbol *> *symbols = NULL);
+ static Vector<Symbol *> *sort_by_name (Vector<Symbol *> *syms);
+
+ // Find symbol in CU corresponding to pc or linker_name.
+ static Symbol *get_symbol (Vector<Symbol *> *syms, uint64_t pc);
+ static Symbol *get_symbol (Vector<Symbol *> *syms, char *linker_name);
+
+ // Create and append a new function to the 'module'.
+ // Copy attributes (size, name, etc) from Symbol,
+ Function *createFunction(Module *module);
+ void dump (const char *msg = NULL);
+
+ Function *func;
+ Sp_lang_code lang_code;
+ uint64_t value;
+ uint64_t save;
+ int64_t size;
+ uint64_t img_offset; // image offset in the ELF file
+ char *name;
+ Symbol *alias;
+ int local_ind;
+ int flags;
+ bool defined;
+};
+#endif
diff --git a/gprofng/src/collect.h b/gprofng/src/collect.h
index 18ab564..3ce6b28 100644
--- a/gprofng/src/collect.h
+++ b/gprofng/src/collect.h
@@ -32,7 +32,6 @@ class Coll_Ctrl;
class Elf;
#define MAXLABELS 10 /* maximum number of -C arguments */
-#define STDEBUFSIZE 24000
enum { MAX_LD_PRELOAD_TYPES = 3 };
diff --git a/gprofng/src/envsets.cc b/gprofng/src/envsets.cc
index 30803aa..e92c017 100644
--- a/gprofng/src/envsets.cc
+++ b/gprofng/src/envsets.cc
@@ -31,16 +31,6 @@
#include "StringBuilder.h"
#include "Settings.h"
-#define STDEBUFSIZE 24000
-
-#define LIBGP_COLLECTOR "libgp-collector.so"
-#define GPROFNG_PRELOAD_LIBDIRS "GPROFNG_PRELOAD_LIBDIRS"
-#define SP_COLLECTOR_EXPNAME "SP_COLLECTOR_EXPNAME"
-#define SP_COLLECTOR_FOLLOW_SPEC "SP_COLLECTOR_FOLLOW_SPEC"
-#define SP_COLLECTOR_PARAMS "SP_COLLECTOR_PARAMS"
-#define SP_COLLECTOR_FOUNDER "SP_COLLECTOR_FOUNDER"
-#define SP_COLLECTOR_ORIGIN_COLLECT "SP_COLLECTOR_ORIGIN_COLLECT"
-
static const char *LD_AUDIT[] = {
// "LD_AUDIT", Do not set LD_AUDIT on Linux
NULL
diff --git a/gprofng/src/gp-archive.cc b/gprofng/src/gp-archive.cc
index 4e68336..2c15da8 100644
--- a/gprofng/src/gp-archive.cc
+++ b/gprofng/src/gp-archive.cc
@@ -140,7 +140,8 @@ er_archive::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-collect-app(1), gprofng-display-html(1), "
- "gprofng-display-src(1), gprofng-display-text(1)\n"));
+ "gprofng-display-src(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
exit (1);
}
@@ -356,25 +357,59 @@ er_archive::start (int argc, char *argv[])
}
lo->sync_read_stabs ();
Elf *elf = lo->get_elf ();
- if (elf && (lo->checksum != 0) && (lo->checksum != elf->elf_checksum ()))
+ if (elf == NULL)
{
if (!quiet)
- fprintf (stderr, GTXT ("gp-archive: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored\n"),
+ fprintf (stderr, GTXT ("gp-archive: Cannot open \"%s\"\n"),
df->get_location ());
+ Dprintf (DEBUG_ARCHIVE,
+ " loadObjs[%ld]: not found '%s'\n", i, df->get_location ());
+ continue;
+ }
+ else if (df->inArchive)
+ {
+ Dprintf (DEBUG_ARCHIVE,
+ " loadObjs[%ld]: inArchive=1 '%s'\n", i, df->get_name ());
continue;
}
- copy_files->append (df);
- if (elf)
+ else if (!mask_is_on (df->get_name ()))
+ {
+ Dprintf (DEBUG_ARCHIVE,
+ " loadObjs[%ld]: mask_is_on=0 '%s'\n", i, df->get_name ());
+ continue;
+ }
+ char *fnm = elf->get_location ();
+ char *anm = founder_exp->getNameInArchive (fnm);
+ archive_file (fnm, anm);
+
+ // archive gnu_debug and gnu_debugalt files
+ if (elf->gnu_debug_file)
{
- Elf *f = elf->find_ancillary_files (lo->get_pathname ());
- if (f)
- copy_files->append (f->dbeFile);
- for (long i1 = 0, sz1 = VecSize(elf->ancillary_files); i1 < sz1; i1++)
+ char *arch_nm = dbe_sprintf ("%s_debug", anm);
+ archive_file (elf->gnu_debug_file->get_location (), arch_nm);
+ free (arch_nm);
+ if (elf->gnu_debug_file->gnu_debugalt_file)
{
- Elf *ancElf = elf->ancillary_files->get (i1);
- copy_files->append (ancElf->dbeFile);
+ arch_nm = dbe_sprintf ("%s_debug_alt", anm);
+ archive_file (elf->gnu_debug_file->gnu_debugalt_file->get_location (), arch_nm);
+ free (arch_nm);
}
}
+ if (elf->gnu_debugalt_file)
+ {
+ char *arch_nm = dbe_sprintf ("%s_alt", anm);
+ archive_file (elf->gnu_debugalt_file->get_location (), arch_nm);
+ free (arch_nm);
+ }
+ free (anm);
+
+ elf->find_ancillary_files (lo->get_pathname ());
+ for (long i1 = 0, sz1 = VecSize (elf->ancillary_files); i1 < sz1; i1++)
+ {
+ Elf *ancElf = elf->ancillary_files->get (i1);
+ copy_files->append (ancElf->dbeFile);
+ }
+
Vector<Module*> *modules = lo->seg_modules;
for (long i1 = 0, sz1 = VecSize(modules); i1 < sz1; i1++)
{
@@ -468,7 +503,7 @@ er_archive::start (int argc, char *argv[])
int res = founder_exp->copy_file (fnm, anm, quiet, common_archive_dir, use_relative_path);
if (0 == res) // file successfully archived
df->inArchive = 1;
- delete anm;
+ free (anm);
}
delete copy_files;
@@ -489,6 +524,15 @@ er_archive::start (int argc, char *argv[])
}
int
+er_archive::archive_file (const char *from, const char *to)
+{
+ if (force)
+ unlink (to);
+ return Experiment::copy_file (from, to, quiet, common_archive_dir,
+ use_relative_path);
+}
+
+int
er_archive::check_args (int argc, char *argv[])
{
int opt;
diff --git a/gprofng/src/gp-archive.h b/gprofng/src/gp-archive.h
index 41fb4b2..3b9d0ee 100644
--- a/gprofng/src/gp-archive.h
+++ b/gprofng/src/gp-archive.h
@@ -47,6 +47,7 @@ public:
private:
void usage ();
int check_args (int argc, char *argv[]);
+ int archive_file (const char *from, const char *to);
int clean_old_archive (char *expname, ArchiveExp *founder_exp);
int mask_is_on (const char *str);
void check_env_var ();
diff --git a/gprofng/src/gp-collect-app.cc b/gprofng/src/gp-collect-app.cc
index bf146d9..695c4af 100644
--- a/gprofng/src/gp-collect-app.cc
+++ b/gprofng/src/gp-collect-app.cc
@@ -44,8 +44,6 @@
#include "collect.h"
#include "StringBuilder.h"
-#define SP_COLLECTOR_FOUNDER "SP_COLLECTOR_FOUNDER"
-
extern char **environ;
static volatile int interrupt = 0;
@@ -1481,7 +1479,8 @@ collect::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-archive(1), gprofng-display-html(1), "
- "gpgprofng-display-src(1), gprofng-display-text(1)\n"));
+ "gpgprofng-display-src(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
}
void
diff --git a/gprofng/src/gp-display-src.cc b/gprofng/src/gp-display-src.cc
index 7eb6b33..5475f27 100644
--- a/gprofng/src/gp-display-src.cc
+++ b/gprofng/src/gp-display-src.cc
@@ -172,7 +172,8 @@ er_src::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-archive(1), gprofng-collect-app(1), "
- "gprofng-display-html(1), gprofng-display-text(1)\n"));
+ "gprofng-display-html(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
/*
printf (GTXT ("Usage: %s [OPTION] a.out/.so/.o/.class\n\n"), whoami);
printf (GTXT (" -func List all the functions from the given object\n"
diff --git a/gprofng/src/gp-display-text.cc b/gprofng/src/gp-display-text.cc
index 4fcd639..32bda49 100644
--- a/gprofng/src/gp-display-text.cc
+++ b/gprofng/src/gp-display-text.cc
@@ -254,7 +254,8 @@ er_print::usage ()
"See also:\n"
"\n"
"gprofng(1), gprofng-archive(1), gprofng-collect-app(1), "
- "gprofng-display-html(1), gprofng-display-src(1)\n"));
+ "gprofng-display-html(1), gprofng-display-src(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
}
int // returns count of experiments read
diff --git a/gprofng/src/gprofng.cc b/gprofng/src/gprofng.cc
index 99f904a..4364d97 100644
--- a/gprofng/src/gprofng.cc
+++ b/gprofng/src/gprofng.cc
@@ -155,7 +155,8 @@ Gprofng::usage ()
"See also:\n"
"\n"
"gprofng-archive(1), gprofng-collect-app(1), gprofng-display-html(1), "
- "gprofng-display-src(1), gprofng-display-text(1)\n"));
+ "gprofng-display-src(1), gprofng-display-text(1)\n"
+ "\nReport bugs to <https://sourceware.org/bugzilla/>\n"));
/*
printf ( GTXT (
diff --git a/gprofng/src/ipcio.cc b/gprofng/src/ipcio.cc
index 36d2ba5..2890c6a 100644
--- a/gprofng/src/ipcio.cc
+++ b/gprofng/src/ipcio.cc
@@ -23,10 +23,7 @@
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-#include <queue>
+
#include "vec.h"
#include "util.h"
#include "ipcio.h"