diff --git a/.devtoolset-9-oprofile.metadata b/.devtoolset-9-oprofile.metadata new file mode 100644 index 0000000..51bfa9e --- /dev/null +++ b/.devtoolset-9-oprofile.metadata @@ -0,0 +1,2 @@ +913be8e806779f7c6ba394113cf75da67d3cf03e SOURCES/openjdk-include.tar.gz +7daa0cca8587e399cb3df9eb817c6a39ffea2082 SOURCES/oprofile-1.3.0.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..403a4d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/openjdk-include.tar.gz +SOURCES/oprofile-1.3.0.tar.gz diff --git a/SOURCES/oprofile-no_orphan.patch b/SOURCES/oprofile-no_orphan.patch new file mode 100644 index 0000000..c18ce6f --- /dev/null +++ b/SOURCES/oprofile-no_orphan.patch @@ -0,0 +1,56 @@ +From 8aacb573cd2c4a2f8160d99ff100ad0aa5e7859d Mon Sep 17 00:00:00 2001 +From: Carl Love +Date: Thu, 25 Jul 2019 10:24:16 -0400 +Subject: [PATCH] Only start the application if the perf events setup was + successful + +Changes the order of starting the application and performance events. + +Given this change we have a new issue. The issue is the routine +start_counting() calls fork, creating app_PID process. + +The parent then tries to setup the performance events, then if the +performance events were setup correctly, app_PID is then told to start +before exiting. If the performance counter setup fails, the app_PID is +left running. The app_PID is never told to start the workload, which is +correct but we don't record the fact that app_PID is running. The +error path then fails to kill app_PID in routine main(), in file +oprofile-git/pe_counting, at about lie 909 because the if statement + + if (startApp && app_started && (run_result != APP_ABNORMAL_END)) { + +is false because app_started is False. + +The fix, I believe, is to set app_started to True in the parent code if +the fork was successful. With this fix, there is no orphan processes +left after ocount exits. +--- + pe_counting/ocount.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/pe_counting/ocount.cpp b/pe_counting/ocount.cpp +index 77177176..2470745d 100644 +--- a/pe_counting/ocount.cpp ++++ b/pe_counting/ocount.cpp +@@ -242,6 +242,10 @@ bool start_counting(void) + + // parent + int startup; ++ if ( app_PID != -1) ++ // app_PID child process created successfully ++ app_started = true; ++ + if (startApp) { + if (read(app_ready_pipe[0], &startup, sizeof(startup)) == -1) { + perror("Internal error on app_ready_pipe"); +@@ -297,7 +301,6 @@ bool start_counting(void) + perror("Internal error on start_app_pipe"); + return false; + } +- app_started = true; + } + + return ret; +-- +2.21.0 + diff --git a/SOURCES/oprofile-offset.patch b/SOURCES/oprofile-offset.patch new file mode 100644 index 0000000..4ae8dd1 --- /dev/null +++ b/SOURCES/oprofile-offset.patch @@ -0,0 +1,87 @@ +From a3742ff269a8d81cb116ec3dd22ef4516de06399 Mon Sep 17 00:00:00 2001 +From: William Cohen +Date: Tue, 24 Sep 2019 09:59:12 -0400 +Subject: [PATCH] Use the mmap offset to correctly compute the IP location in a + file + +Newer versions of binutils are now now splitting the file into +multiple mmap loads. The assumption that the mmap for the executable +code in the file starts at the beginning of the file (that the file +offset is always zero) is no longer true. The computation to convert +the IP address into an offset needs to also use the offset. +--- + libperf_events/operf_sfile.h | 1 + + libperf_events/operf_utils.cpp | 10 +++++++--- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/libperf_events/operf_sfile.h b/libperf_events/operf_sfile.h +index bc003553..4d0576c6 100644 +--- a/libperf_events/operf_sfile.h ++++ b/libperf_events/operf_sfile.h +@@ -101,6 +101,7 @@ struct operf_transient { + u32 tgid; + vma_t start_addr; + vma_t end_addr; ++ u64 pgoff; + bool cg; + // TODO: handle extended + //void * ext; +diff --git a/libperf_events/operf_utils.cpp b/libperf_events/operf_utils.cpp +index 70253495..1e9d1e98 100644 +--- a/libperf_events/operf_utils.cpp ++++ b/libperf_events/operf_utils.cpp +@@ -320,7 +320,8 @@ static void __handle_mmap_event(event_t * event) + cout << "PERF_RECORD_MMAP for process " << hex << event->mmap.pid << "/" + << event->mmap.tid << ": " << event->mmap.filename << endl; + cout << "\tstart_addr: " << hex << mapping->start_addr +- << "; end addr: " << mapping->end_addr << endl; ++ << "; end addr: " << mapping->end_addr ++ << "; pgoff: " << mapping->pgoff << endl; + } + + if (event->header.misc & PERF_RECORD_MISC_USER) +@@ -465,6 +466,7 @@ static struct operf_transient * __get_operf_trans(struct sample_data * data, boo + trans.image_len = strlen(trans.image_name); + trans.start_addr = op_mmap->start_addr; + trans.end_addr = op_mmap->end_addr; ++ trans.pgoff = op_mmap->pgoff; + trans.tgid = data->pid; + trans.tid = data->tid; + trans.cur_procinfo = proc; +@@ -474,7 +476,7 @@ static struct operf_transient * __get_operf_trans(struct sample_data * data, boo + if (trans.in_kernel || trans.is_anon) + trans.pc = data->ip; + else +- trans.pc = data->ip - trans.start_addr; ++ trans.pc = data->ip + trans.pgoff - trans.start_addr; + + trans.sample_id = data->id; + retval = &trans; +@@ -767,7 +769,7 @@ static int __handle_sample_event(event_t * event, u64 sample_type) + if (trans.is_anon) + trans.pc = data.ip; + else +- trans.pc = data.ip - trans.start_addr; ++ trans.pc = data.ip + trans.pgoff - trans.start_addr; + found_trans = true; + } + +@@ -1062,6 +1064,7 @@ void OP_perf_utils::op_get_vsyscall_mapping(pid_t tgid, int output_fd, operf_rec + size = align_64bit(size); + mmap.start = start_addr; + mmap.len = end_addr - mmap.start; ++ mmap.pgoff = offset; + mmap.pid = tgid; + mmap.tid = tgid; + mmap.header.size = (sizeof(mmap) - +@@ -1133,6 +1136,7 @@ void OP_perf_utils::op_record_process_exec_mmaps(pid_t pid, pid_t tgid, int outp + size = align_64bit(size); + mmap.start = start_addr; + mmap.len = end_addr - mmap.start; ++ mmap.pgoff = offset; + mmap.pid = tgid; + mmap.tid = pid; + mmap.header.size = (sizeof(mmap) - +-- +2.21.0 + diff --git a/SOURCES/oprofile-ppc_null_event.patch b/SOURCES/oprofile-ppc_null_event.patch new file mode 100644 index 0000000..14b74f0 --- /dev/null +++ b/SOURCES/oprofile-ppc_null_event.patch @@ -0,0 +1,40 @@ +From 9d4345ab870c9990ae572eafc45fc999c23fa00b Mon Sep 17 00:00:00 2001 +From: William Cohen +Date: Fri, 3 Aug 2018 10:10:12 -0400 +Subject: [PATCH] Handle empty event name spec gracefully for PPC + +During testing Michael Petlan found that the giving an empty event +name in the event spec to operf on PPC machines would cause operf +crash. Running the following following command would demonstrate +this problem: + + operf -e : /bin/ls + +The problem was traced to event_name in _handle_powerpc_event_spec +function having a length of 0. The strncmp using event_name in +_handle_powerpc_event_spec would indicate a match and cause strncpy to +be called to copy zero bytes. The zero length strncpy would crash +operf. Added a check to make ensure that the string is non-zero +length. + +Signed-off-by: William Cohen +--- + libpe_utils/op_pe_utils.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libpe_utils/op_pe_utils.cpp b/libpe_utils/op_pe_utils.cpp +index f9638c77..2cae7840 100644 +--- a/libpe_utils/op_pe_utils.cpp ++++ b/libpe_utils/op_pe_utils.cpp +@@ -588,7 +588,7 @@ static string _handle_powerpc_event_spec(string event_spec) + } + if (line[0] == ' ' || line[0] == '\t') + continue; +- if (!strncmp(line, event_name, evt_name_len)) { ++ if (evt_name_len && !strncmp(line, event_name, evt_name_len)) { + // Found a potential match. Check if it's a perfect match. + string save_event_name = event_name; + size_t full_evt_len = index(line, ':') - line; +-- +2.17.1 + diff --git a/SPECS/oprofile.spec b/SPECS/oprofile.spec new file mode 100644 index 0000000..40e5f07 --- /dev/null +++ b/SPECS/oprofile.spec @@ -0,0 +1,235 @@ +%{?scl:%scl_package oprofile} + +Summary: System wide profiler +Name: %{?scl_prefix}oprofile +Version: 1.3.0 +Release: 4%{?dist} +License: GPLv2+ and LGPLv2+ +Group: Development/System +# +Source0: http://downloads.sourceforge.net/oprofile/oprofile-%{version}.tar.gz +#FIXME a workaround until java-1.6.0-openjdk-devel is available on all archs +Source1: openjdk-include.tar.gz +Patch1: oprofile-ppc_null_event.patch +Patch2: oprofile-no_orphan.patch +Patch3: oprofile-offset.patch +Requires: binutils +Requires: which +Requires(pre): shadow-utils +Requires(postun): shadow-utils +%{?scl:Requires:%scl_runtime} + +URL: http://oprofile.sf.net + +#If oprofile doesn't build on an arch, report it and will add ExcludeArch tag. +BuildRequires: qt-devel +BuildRequires: libxslt +BuildRequires: docbook-style-xsl +BuildRequires: docbook-utils +BuildRequires: elinks +BuildRequires: gtk2-devel +BuildRequires: automake +BuildRequires: libtool +%if 0%{?rhel} >= 7 || 0%{?fedora} >= 15 +BuildRequires: binutils-static +BuildRequires: libpfm-devel >= 4.3.0 +%else +BuildRequires: %{?scl_prefix}binutils-devel +BuildRequires: binutils-devel +%endif +%if 0%{?rhel} == 6 +%ifnarch s390x s390 +BuildRequires: papi-devel +%endif +%endif +%if 0%{?rhel} >= 6 +BuildRequires: popt-devel +%else +BuildRequires: popt +%endif + +#BuildRequires: java-devel +#BuildRequires: jpackage-utils +#BuildRequires: java-1.6.0-openjdk-devel + +BuildRoot: %{_tmppath}/%{name}-root + +%description +OProfile is a profiling system for systems running Linux. The +profiling runs transparently during the background, and profile data +can be collected at any time. OProfile makes use of the hardware performance +counters provided on Intel P6, and AMD Athlon family processors, and can use +the RTC for profiling on other x86 processor types. + +See the HTML documentation for further details. + +%package devel +Summary: Header files and libraries for developing apps which will use oprofile +Group: Development/Libraries +Requires: %{?scl_prefix}oprofile = %{version}-%{release} +Provides: %{?scl_prefix}oprofile-static = %{version}-%{release} + +%description devel + +Header files and libraries for developing apps which will use oprofile. + +%package jit +Summary: Libraries required for profiling Java and other JITed code +Group: Development/System +Requires: %{?scl_prefix}oprofile = %{version}-%{release} +#Requires: java >= 1.6 +#Requires: jpackage-utils +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +Requires: /etc/ld.so.conf.d + +%description jit +This package includes a base JIT support library, as well as a Java +agent library. + +%prep +%setup -q -n oprofile-%{version} -a1 +%patch1 -p1 -b .ppc_null_event +%patch2 -p1 -b .noorphan +%patch3 -p1 -b .offset + +./autogen.sh + +%build + +%configure \ +--with-java=`pwd`/java-1.6.0-openjdk-1.6.0.0 + +make CFLAGS="$RPM_OPT_FLAGS" + +#tweak the manual pages +find -path "*/doc/*.1" -exec \ + sed -i -e \ + 's,/doc/oprofile/,/doc/oprofile-%{version}/,g' {} \; + +%install +rm -rf %{buildroot} + +mkdir -p %{buildroot}%{_bindir} +mkdir -p %{buildroot}%{_mandir}/man1 + +make DESTDIR=%{buildroot} INSTALL="install -p" install + +# We want the manuals in the special doc dir, not the generic doc install dir. +# We build it in place and then move it away so it doesn't get installed +# twice. rpm can specify itself where the (versioned) docs go with the +# %%doc directive. +mkdir docs.installed +mv %{buildroot}%{_datadir}/doc/oprofile/* docs.installed/ + +%if 0%{?scl:1} +# if developer tools set need to put the agentlib in an appropriate place +mv %{buildroot}%{_libdir}/oprofile/* %{buildroot}%{_libdir} +rmdir %{buildroot}%{_libdir}/oprofile +%else +mkdir -p %{buildroot}%{_sysconfdir}/ld.so.conf.d +echo "%{_libdir}/oprofile" > %{buildroot}%{_sysconfdir}/ld.so.conf.d/oprofile-%{_arch}.conf +%endif + + +%pre +getent group oprofile >/dev/null || groupadd -r -g 16 oprofile +getent passwd oprofile >/dev/null || \ +useradd -g oprofile -d /var/lib/oprofile -M -r -u 16 -s /sbin/nologin \ + -c "Special user account to be used by OProfile" oprofile +exit 0 + +%postun +# do not try to remove existing oprofile user or group + +%files +%defattr(-,root,root) +%doc docs.installed/* +%doc COPYING + +%{_bindir}/* + +%{_mandir}/man1/* + +%{_datadir}/oprofile + +%files devel +%defattr(-,root,root) + +%{_includedir}/opagent.h + +%post jit -p /sbin/ldconfig + +%postun jit -p /sbin/ldconfig + +%files jit +%defattr(-,root,root) + +%if 0%{?scl:1} +%{_libdir}/* +%else +%{_libdir}/oprofile +%{_sysconfdir}/ld.so.conf.d/* +%endif + +%changelog +* Tue Sep 24 2019 William Cohen - 1.3.0-4 +- Use mmap offset in the computation of pc address. rhbz1745134 + +* Thu Jul 25 2019 William Cohen - 1.3.0-3 +- Correctly kill child process when error occurs during setup. + +* Fri Aug 3 2018 William Cohen - 1.3.0-2 +- Fix handling of null event name on ppc. rhbz1609797 + +* Mon Jul 16 2018 William Cohen - 1.3.0-1 +- Rebase to oprofile-1.3.0. + +* Wed Apr 25 2018 William Cohen - 1.2.0-2.1 +- Power9 cpu recognition. + +* Thu Feb 22 2018 William Cohen - 1.2.0-2 +- Rebuilt. + +* Wed Jul 26 2017 William Cohen - 1.2.0-1 +- Rebase to oprofile-1.2.0. + +* Fri Jun 16 2017 Will Cohen - 1.2.0-0.20170616git647ca9d0 +- Rebuild on oprofile git snapshot. + +* Wed Oct 12 2016 Will Cohen - 1.1.0-4 +- Update events non-x86 architectures (aarch64, power, zseries) +- Add support for newer Intel processors. + +* Thu Sep 15 2016 Will Cohen - 1.1.0-3 +- Avoid duplicate event names for Nehalem and Westmere processors. + +* Thu Aug 13 2015 Will Cohen - 1.1.0-2 +- Locate jvm agent libjvmti in a LD_LIBRARY_PATH directory. + +* Tue Jul 21 2015 Will Cohen - 1.1.0-1 +- Rebase to oprofile-1.1.0. + +* Thu Apr 23 2015 Will Cohen - 0.9.9-7 +- LLC_REFS and LLC_MISSES do not work on some CPUs. +- incorrect handling of default unit masks longer than 11 characters +- Oprofile updates for Avoton +- Unable to profile jited JVM code when using static huge pages +- operf causes rpmbuild to fail + +* Wed Sep 17 2014 Will Cohen - 0.9.9-6 +- Update support for Intel Silvermont (Avoton). +- Enable configure for ppc64le. + +* Mon Aug 18 2014 Will Cohen - 0.9.9-5 +- Update Intel Haswell events. +- Add support for Intel Silvermont (Avoton). +- Add support for Intel Broadwell. +- Add support for aarch64. +- Update IBM power8 events. + +* Wed May 28 2014 Will Cohen - 0.9.9-2.1 +- Correct xml output. + +* Fri May 16 2014 Will Cohen - 0.9.9-1.1 +- Rebase on oprofile-0.9.9.