gprofng: a new GNU profiler
top-level * Makefile.def: Add gprofng module. * configure.ac: Add --enable-gprofng option. * src-release.sh: Add gprofng. * Makefile.in: Regenerate. * configure: Regenerate. * gprofng: New directory. binutils * MAINTAINERS: Add gprofng maintainer. * README-how-to-make-a-release: Add gprofng. include. * collectorAPI.h: New file. * libcollector.h: New file. * libfcollector.h: New file.
This commit is contained in:
parent
a655f19af9
commit
bb368aad29
319 changed files with 222979 additions and 8 deletions
|
@ -1,3 +1,12 @@
|
|||
2022-03-11 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
|
||||
|
||||
* Makefile.def: Add gprofng module.
|
||||
* configure.ac: Add --enable-gprofng option.
|
||||
* src-release.sh: Add gprofng.
|
||||
* Makefile.in: Regenerate.
|
||||
* configure: Regenerate.
|
||||
* gprofng: New directory.
|
||||
|
||||
2022-01-22 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* 2.38 release branch created.
|
||||
|
|
11
Makefile.def
11
Makefile.def
|
@ -75,6 +75,7 @@ host_modules= { module= libelf; lib_path=.libs; bootstrap=true;
|
|||
no_install= true; };
|
||||
host_modules= { module= gold; bootstrap=true; };
|
||||
host_modules= { module= gprof; };
|
||||
host_modules= { module= gprofng; };
|
||||
host_modules= { module= intl; bootstrap=true; };
|
||||
host_modules= { module= tcl;
|
||||
missing=mostlyclean; };
|
||||
|
@ -508,6 +509,16 @@ dependencies = { module=all-gprof; on=all-bfd; };
|
|||
dependencies = { module=all-gprof; on=all-opcodes; };
|
||||
dependencies = { module=all-gprof; on=all-intl; };
|
||||
dependencies = { module=all-gprof; on=all-gas; };
|
||||
|
||||
dependencies = { module=configure-gprofng; on=configure-intl; };
|
||||
dependencies = { module=all-gprofng; on=all-libiberty; };
|
||||
dependencies = { module=all-gprofng; on=all-bfd; };
|
||||
dependencies = { module=all-gprofng; on=all-opcodes; };
|
||||
dependencies = { module=all-gprofng; on=all-intl; };
|
||||
dependencies = { module=all-gprofng; on=all-gas; };
|
||||
dependencies = { module=install-gprofng; on=install-opcodes; };
|
||||
dependencies = { module=install-gprofng; on=install-bfd; };
|
||||
|
||||
dependencies = { module=configure-ld; on=configure-intl; };
|
||||
dependencies = { module=all-ld; on=all-libiberty; };
|
||||
dependencies = { module=all-ld; on=all-bfd; };
|
||||
|
|
497
Makefile.in
497
Makefile.in
|
@ -1073,6 +1073,7 @@ configure-host: \
|
|||
maybe-configure-libelf \
|
||||
maybe-configure-gold \
|
||||
maybe-configure-gprof \
|
||||
maybe-configure-gprofng \
|
||||
maybe-configure-intl \
|
||||
maybe-configure-tcl \
|
||||
maybe-configure-itcl \
|
||||
|
@ -1228,6 +1229,7 @@ all-host: maybe-all-libelf
|
|||
all-host: maybe-all-gold
|
||||
@endif gold-no-bootstrap
|
||||
all-host: maybe-all-gprof
|
||||
all-host: maybe-all-gprofng
|
||||
@if intl-no-bootstrap
|
||||
all-host: maybe-all-intl
|
||||
@endif intl-no-bootstrap
|
||||
|
@ -1357,6 +1359,7 @@ info-host: maybe-info-isl
|
|||
info-host: maybe-info-libelf
|
||||
info-host: maybe-info-gold
|
||||
info-host: maybe-info-gprof
|
||||
info-host: maybe-info-gprofng
|
||||
info-host: maybe-info-intl
|
||||
info-host: maybe-info-tcl
|
||||
info-host: maybe-info-itcl
|
||||
|
@ -1447,6 +1450,7 @@ dvi-host: maybe-dvi-isl
|
|||
dvi-host: maybe-dvi-libelf
|
||||
dvi-host: maybe-dvi-gold
|
||||
dvi-host: maybe-dvi-gprof
|
||||
dvi-host: maybe-dvi-gprofng
|
||||
dvi-host: maybe-dvi-intl
|
||||
dvi-host: maybe-dvi-tcl
|
||||
dvi-host: maybe-dvi-itcl
|
||||
|
@ -1537,6 +1541,7 @@ pdf-host: maybe-pdf-isl
|
|||
pdf-host: maybe-pdf-libelf
|
||||
pdf-host: maybe-pdf-gold
|
||||
pdf-host: maybe-pdf-gprof
|
||||
pdf-host: maybe-pdf-gprofng
|
||||
pdf-host: maybe-pdf-intl
|
||||
pdf-host: maybe-pdf-tcl
|
||||
pdf-host: maybe-pdf-itcl
|
||||
|
@ -1627,6 +1632,7 @@ html-host: maybe-html-isl
|
|||
html-host: maybe-html-libelf
|
||||
html-host: maybe-html-gold
|
||||
html-host: maybe-html-gprof
|
||||
html-host: maybe-html-gprofng
|
||||
html-host: maybe-html-intl
|
||||
html-host: maybe-html-tcl
|
||||
html-host: maybe-html-itcl
|
||||
|
@ -1717,6 +1723,7 @@ TAGS-host: maybe-TAGS-isl
|
|||
TAGS-host: maybe-TAGS-libelf
|
||||
TAGS-host: maybe-TAGS-gold
|
||||
TAGS-host: maybe-TAGS-gprof
|
||||
TAGS-host: maybe-TAGS-gprofng
|
||||
TAGS-host: maybe-TAGS-intl
|
||||
TAGS-host: maybe-TAGS-tcl
|
||||
TAGS-host: maybe-TAGS-itcl
|
||||
|
@ -1807,6 +1814,7 @@ install-info-host: maybe-install-info-isl
|
|||
install-info-host: maybe-install-info-libelf
|
||||
install-info-host: maybe-install-info-gold
|
||||
install-info-host: maybe-install-info-gprof
|
||||
install-info-host: maybe-install-info-gprofng
|
||||
install-info-host: maybe-install-info-intl
|
||||
install-info-host: maybe-install-info-tcl
|
||||
install-info-host: maybe-install-info-itcl
|
||||
|
@ -1897,6 +1905,7 @@ install-dvi-host: maybe-install-dvi-isl
|
|||
install-dvi-host: maybe-install-dvi-libelf
|
||||
install-dvi-host: maybe-install-dvi-gold
|
||||
install-dvi-host: maybe-install-dvi-gprof
|
||||
install-dvi-host: maybe-install-dvi-gprofng
|
||||
install-dvi-host: maybe-install-dvi-intl
|
||||
install-dvi-host: maybe-install-dvi-tcl
|
||||
install-dvi-host: maybe-install-dvi-itcl
|
||||
|
@ -1987,6 +1996,7 @@ install-pdf-host: maybe-install-pdf-isl
|
|||
install-pdf-host: maybe-install-pdf-libelf
|
||||
install-pdf-host: maybe-install-pdf-gold
|
||||
install-pdf-host: maybe-install-pdf-gprof
|
||||
install-pdf-host: maybe-install-pdf-gprofng
|
||||
install-pdf-host: maybe-install-pdf-intl
|
||||
install-pdf-host: maybe-install-pdf-tcl
|
||||
install-pdf-host: maybe-install-pdf-itcl
|
||||
|
@ -2077,6 +2087,7 @@ install-html-host: maybe-install-html-isl
|
|||
install-html-host: maybe-install-html-libelf
|
||||
install-html-host: maybe-install-html-gold
|
||||
install-html-host: maybe-install-html-gprof
|
||||
install-html-host: maybe-install-html-gprofng
|
||||
install-html-host: maybe-install-html-intl
|
||||
install-html-host: maybe-install-html-tcl
|
||||
install-html-host: maybe-install-html-itcl
|
||||
|
@ -2167,6 +2178,7 @@ installcheck-host: maybe-installcheck-isl
|
|||
installcheck-host: maybe-installcheck-libelf
|
||||
installcheck-host: maybe-installcheck-gold
|
||||
installcheck-host: maybe-installcheck-gprof
|
||||
installcheck-host: maybe-installcheck-gprofng
|
||||
installcheck-host: maybe-installcheck-intl
|
||||
installcheck-host: maybe-installcheck-tcl
|
||||
installcheck-host: maybe-installcheck-itcl
|
||||
|
@ -2257,6 +2269,7 @@ mostlyclean-host: maybe-mostlyclean-isl
|
|||
mostlyclean-host: maybe-mostlyclean-libelf
|
||||
mostlyclean-host: maybe-mostlyclean-gold
|
||||
mostlyclean-host: maybe-mostlyclean-gprof
|
||||
mostlyclean-host: maybe-mostlyclean-gprofng
|
||||
mostlyclean-host: maybe-mostlyclean-intl
|
||||
mostlyclean-host: maybe-mostlyclean-tcl
|
||||
mostlyclean-host: maybe-mostlyclean-itcl
|
||||
|
@ -2347,6 +2360,7 @@ clean-host: maybe-clean-isl
|
|||
clean-host: maybe-clean-libelf
|
||||
clean-host: maybe-clean-gold
|
||||
clean-host: maybe-clean-gprof
|
||||
clean-host: maybe-clean-gprofng
|
||||
clean-host: maybe-clean-intl
|
||||
clean-host: maybe-clean-tcl
|
||||
clean-host: maybe-clean-itcl
|
||||
|
@ -2437,6 +2451,7 @@ distclean-host: maybe-distclean-isl
|
|||
distclean-host: maybe-distclean-libelf
|
||||
distclean-host: maybe-distclean-gold
|
||||
distclean-host: maybe-distclean-gprof
|
||||
distclean-host: maybe-distclean-gprofng
|
||||
distclean-host: maybe-distclean-intl
|
||||
distclean-host: maybe-distclean-tcl
|
||||
distclean-host: maybe-distclean-itcl
|
||||
|
@ -2527,6 +2542,7 @@ maintainer-clean-host: maybe-maintainer-clean-isl
|
|||
maintainer-clean-host: maybe-maintainer-clean-libelf
|
||||
maintainer-clean-host: maybe-maintainer-clean-gold
|
||||
maintainer-clean-host: maybe-maintainer-clean-gprof
|
||||
maintainer-clean-host: maybe-maintainer-clean-gprofng
|
||||
maintainer-clean-host: maybe-maintainer-clean-intl
|
||||
maintainer-clean-host: maybe-maintainer-clean-tcl
|
||||
maintainer-clean-host: maybe-maintainer-clean-itcl
|
||||
|
@ -2675,6 +2691,7 @@ check-host: \
|
|||
maybe-check-libelf \
|
||||
maybe-check-gold \
|
||||
maybe-check-gprof \
|
||||
maybe-check-gprofng \
|
||||
maybe-check-intl \
|
||||
maybe-check-tcl \
|
||||
maybe-check-itcl \
|
||||
|
@ -2812,6 +2829,7 @@ install-host-nogcc: \
|
|||
maybe-install-libelf \
|
||||
maybe-install-gold \
|
||||
maybe-install-gprof \
|
||||
maybe-install-gprofng \
|
||||
maybe-install-intl \
|
||||
maybe-install-tcl \
|
||||
maybe-install-itcl \
|
||||
|
@ -2867,6 +2885,7 @@ install-host: \
|
|||
maybe-install-libelf \
|
||||
maybe-install-gold \
|
||||
maybe-install-gprof \
|
||||
maybe-install-gprofng \
|
||||
maybe-install-intl \
|
||||
maybe-install-tcl \
|
||||
maybe-install-itcl \
|
||||
|
@ -2977,6 +2996,7 @@ install-strip-host: \
|
|||
maybe-install-strip-libelf \
|
||||
maybe-install-strip-gold \
|
||||
maybe-install-strip-gprof \
|
||||
maybe-install-strip-gprofng \
|
||||
maybe-install-strip-intl \
|
||||
maybe-install-strip-tcl \
|
||||
maybe-install-strip-itcl \
|
||||
|
@ -20404,6 +20424,474 @@ maintainer-clean-gprof:
|
|||
|
||||
|
||||
|
||||
.PHONY: configure-gprofng maybe-configure-gprofng
|
||||
maybe-configure-gprofng:
|
||||
@if gcc-bootstrap
|
||||
configure-gprofng: stage_current
|
||||
@endif gcc-bootstrap
|
||||
@if gprofng
|
||||
maybe-configure-gprofng: configure-gprofng
|
||||
configure-gprofng:
|
||||
@: $(MAKE); $(unstage)
|
||||
@r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
test ! -f $(HOST_SUBDIR)/gprofng/Makefile || exit 0; \
|
||||
$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/gprofng; \
|
||||
$(HOST_EXPORTS) \
|
||||
echo Configuring in $(HOST_SUBDIR)/gprofng; \
|
||||
cd "$(HOST_SUBDIR)/gprofng" || exit 1; \
|
||||
case $(srcdir) in \
|
||||
/* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
|
||||
*) topdir=`echo $(HOST_SUBDIR)/gprofng/ | \
|
||||
sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
|
||||
esac; \
|
||||
module_srcdir=gprofng; \
|
||||
$(SHELL) \
|
||||
$$s/$$module_srcdir/configure \
|
||||
--srcdir=$${topdir}/$$module_srcdir \
|
||||
$(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
|
||||
--target=${target_alias} \
|
||||
|| exit 1
|
||||
@endif gprofng
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.PHONY: all-gprofng maybe-all-gprofng
|
||||
maybe-all-gprofng:
|
||||
@if gcc-bootstrap
|
||||
all-gprofng: stage_current
|
||||
@endif gcc-bootstrap
|
||||
@if gprofng
|
||||
TARGET-gprofng=all
|
||||
maybe-all-gprofng: all-gprofng
|
||||
all-gprofng: configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS) $(STAGE1_FLAGS_TO_PASS) \
|
||||
$(TARGET-gprofng))
|
||||
@endif gprofng
|
||||
|
||||
|
||||
|
||||
|
||||
.PHONY: check-gprofng maybe-check-gprofng
|
||||
maybe-check-gprofng:
|
||||
@if gprofng
|
||||
maybe-check-gprofng: check-gprofng
|
||||
|
||||
check-gprofng:
|
||||
@: $(MAKE); $(unstage)
|
||||
@r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(FLAGS_TO_PASS) check)
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: install-gprofng maybe-install-gprofng
|
||||
maybe-install-gprofng:
|
||||
@if gprofng
|
||||
maybe-install-gprofng: install-gprofng
|
||||
|
||||
install-gprofng: installdirs
|
||||
@: $(MAKE); $(unstage)
|
||||
@r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(FLAGS_TO_PASS) install)
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: install-strip-gprofng maybe-install-strip-gprofng
|
||||
maybe-install-strip-gprofng:
|
||||
@if gprofng
|
||||
maybe-install-strip-gprofng: install-strip-gprofng
|
||||
|
||||
install-strip-gprofng: installdirs
|
||||
@: $(MAKE); $(unstage)
|
||||
@r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(FLAGS_TO_PASS) install-strip)
|
||||
|
||||
@endif gprofng
|
||||
|
||||
# Other targets (info, dvi, pdf, etc.)
|
||||
|
||||
.PHONY: maybe-info-gprofng info-gprofng
|
||||
maybe-info-gprofng:
|
||||
@if gprofng
|
||||
maybe-info-gprofng: info-gprofng
|
||||
|
||||
info-gprofng: \
|
||||
configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing info in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
info) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-dvi-gprofng dvi-gprofng
|
||||
maybe-dvi-gprofng:
|
||||
@if gprofng
|
||||
maybe-dvi-gprofng: dvi-gprofng
|
||||
|
||||
dvi-gprofng: \
|
||||
configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing dvi in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
dvi) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-pdf-gprofng pdf-gprofng
|
||||
maybe-pdf-gprofng:
|
||||
@if gprofng
|
||||
maybe-pdf-gprofng: pdf-gprofng
|
||||
|
||||
pdf-gprofng: \
|
||||
configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing pdf in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
pdf) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-html-gprofng html-gprofng
|
||||
maybe-html-gprofng:
|
||||
@if gprofng
|
||||
maybe-html-gprofng: html-gprofng
|
||||
|
||||
html-gprofng: \
|
||||
configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing html in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
html) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-TAGS-gprofng TAGS-gprofng
|
||||
maybe-TAGS-gprofng:
|
||||
@if gprofng
|
||||
maybe-TAGS-gprofng: TAGS-gprofng
|
||||
|
||||
TAGS-gprofng: \
|
||||
configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing TAGS in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
TAGS) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-install-info-gprofng install-info-gprofng
|
||||
maybe-install-info-gprofng:
|
||||
@if gprofng
|
||||
maybe-install-info-gprofng: install-info-gprofng
|
||||
|
||||
install-info-gprofng: \
|
||||
configure-gprofng \
|
||||
info-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing install-info in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
install-info) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-install-dvi-gprofng install-dvi-gprofng
|
||||
maybe-install-dvi-gprofng:
|
||||
@if gprofng
|
||||
maybe-install-dvi-gprofng: install-dvi-gprofng
|
||||
|
||||
install-dvi-gprofng: \
|
||||
configure-gprofng \
|
||||
dvi-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing install-dvi in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
install-dvi) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-install-pdf-gprofng install-pdf-gprofng
|
||||
maybe-install-pdf-gprofng:
|
||||
@if gprofng
|
||||
maybe-install-pdf-gprofng: install-pdf-gprofng
|
||||
|
||||
install-pdf-gprofng: \
|
||||
configure-gprofng \
|
||||
pdf-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing install-pdf in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
install-pdf) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-install-html-gprofng install-html-gprofng
|
||||
maybe-install-html-gprofng:
|
||||
@if gprofng
|
||||
maybe-install-html-gprofng: install-html-gprofng
|
||||
|
||||
install-html-gprofng: \
|
||||
configure-gprofng \
|
||||
html-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing install-html in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
install-html) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-installcheck-gprofng installcheck-gprofng
|
||||
maybe-installcheck-gprofng:
|
||||
@if gprofng
|
||||
maybe-installcheck-gprofng: installcheck-gprofng
|
||||
|
||||
installcheck-gprofng: \
|
||||
configure-gprofng
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing installcheck in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
installcheck) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-mostlyclean-gprofng mostlyclean-gprofng
|
||||
maybe-mostlyclean-gprofng:
|
||||
@if gprofng
|
||||
maybe-mostlyclean-gprofng: mostlyclean-gprofng
|
||||
|
||||
mostlyclean-gprofng:
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing mostlyclean in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
mostlyclean) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-clean-gprofng clean-gprofng
|
||||
maybe-clean-gprofng:
|
||||
@if gprofng
|
||||
maybe-clean-gprofng: clean-gprofng
|
||||
|
||||
clean-gprofng:
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing clean in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
clean) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-distclean-gprofng distclean-gprofng
|
||||
maybe-distclean-gprofng:
|
||||
@if gprofng
|
||||
maybe-distclean-gprofng: distclean-gprofng
|
||||
|
||||
distclean-gprofng:
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing distclean in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
distclean) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
.PHONY: maybe-maintainer-clean-gprofng maintainer-clean-gprofng
|
||||
maybe-maintainer-clean-gprofng:
|
||||
@if gprofng
|
||||
maybe-maintainer-clean-gprofng: maintainer-clean-gprofng
|
||||
|
||||
maintainer-clean-gprofng:
|
||||
@: $(MAKE); $(unstage)
|
||||
@[ -f ./gprofng/Makefile ] || exit 0; \
|
||||
r=`${PWD_COMMAND}`; export r; \
|
||||
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
|
||||
$(HOST_EXPORTS) \
|
||||
for flag in $(EXTRA_HOST_FLAGS) ; do \
|
||||
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
|
||||
done; \
|
||||
echo "Doing maintainer-clean in gprofng"; \
|
||||
(cd $(HOST_SUBDIR)/gprofng && \
|
||||
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
|
||||
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
|
||||
"RANLIB=$${RANLIB}" \
|
||||
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
|
||||
maintainer-clean) \
|
||||
|| exit 1
|
||||
|
||||
@endif gprofng
|
||||
|
||||
|
||||
|
||||
.PHONY: configure-intl maybe-configure-intl
|
||||
maybe-configure-intl:
|
||||
@if gcc-bootstrap
|
||||
|
@ -62838,6 +63326,8 @@ all-stagetrain-gas: maybe-all-stagetrain-intl
|
|||
all-stagefeedback-gas: maybe-all-stagefeedback-intl
|
||||
all-stageautoprofile-gas: maybe-all-stageautoprofile-intl
|
||||
all-stageautofeedback-gas: maybe-all-stageautofeedback-intl
|
||||
install-gprofng: maybe-install-opcodes
|
||||
install-gprofng: maybe-install-bfd
|
||||
configure-ld: maybe-configure-intl
|
||||
configure-stage1-ld: maybe-configure-stage1-intl
|
||||
configure-stage2-ld: maybe-configure-stage2-intl
|
||||
|
@ -63240,6 +63730,7 @@ configure-gdb: stage_last
|
|||
configure-gdbserver: stage_last
|
||||
configure-gdbsupport: stage_last
|
||||
configure-gprof: stage_last
|
||||
configure-gprofng: stage_last
|
||||
configure-sid: stage_last
|
||||
configure-sim: stage_last
|
||||
configure-fastjar: stage_last
|
||||
|
@ -63272,6 +63763,12 @@ all-gprof: maybe-all-bfd
|
|||
all-gprof: maybe-all-opcodes
|
||||
all-gprof: maybe-all-intl
|
||||
all-gprof: maybe-all-gas
|
||||
configure-gprofng: maybe-configure-intl
|
||||
all-gprofng: maybe-all-libiberty
|
||||
all-gprofng: maybe-all-bfd
|
||||
all-gprofng: maybe-all-opcodes
|
||||
all-gprofng: maybe-all-intl
|
||||
all-gprofng: maybe-all-gas
|
||||
all-sid: maybe-all-libiberty
|
||||
all-sid: maybe-all-bfd
|
||||
all-sid: maybe-all-opcodes
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2022-03-11 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
|
||||
|
||||
* MAINTAINERS: Add gprofng maintainer.
|
||||
* README-how-to-make-a-release: Add gprofng.
|
||||
|
||||
2022-03-10 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* dwarf.c (use_debuginfod): New variable. Set to 1.
|
||||
|
|
|
@ -84,6 +84,7 @@ responsibility among the other maintainers.
|
|||
FRV Alexandre Oliva <aoliva@sourceware.org>
|
||||
GOLD Ian Lance Taylor <iant@google.com>
|
||||
GOLD Cary Coutant <ccoutant@gmail.com>
|
||||
gprofng Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
|
||||
H8300 Prafulla Thakare <prafulla.thakare@kpitcummins.com>
|
||||
HPPA Dave Anglin <dave.anglin@bell.net>
|
||||
HPPA elf32 Alan Modra <amodra@gmail.com>
|
||||
|
|
|
@ -35,7 +35,7 @@ Approx time to complete from here: 2 hours ....
|
|||
in the gold directory - it has its own release numbering.
|
||||
|
||||
Likewise for the ChangeLog files in: bfd, binutils, config, cpu,
|
||||
elfcpp, gas, gold, gprof, include, ld, libctf, libiberty, opcodes
|
||||
elfcpp, gas, gold, gprof, gprofng, include, ld, libctf, libiberty, opcodes
|
||||
and toplevel.
|
||||
|
||||
Add a note of the name of the new branch to binutils/BRANCHES.
|
||||
|
@ -97,8 +97,8 @@ Approx time to complete from here: 2 hours ....
|
|||
m4_define([BFD_VERSION], [2.39.50])
|
||||
|
||||
Regenerate various files on both branch and HEAD by configuring
|
||||
with "--enable-maintainer-mode --enable-gold" and then building
|
||||
with "make all-binutils all-gas all-gold all-gprof all-ld"
|
||||
with "--enable-maintainer-mode --enable-gold --enable-shared" and then building
|
||||
with "make all-binutils all-gas all-gold all-gprof all-gprofng all-ld"
|
||||
|
||||
Add ChangeLog entries for the updated files. Commit the changes.
|
||||
Make sure that this includes the .pot files as well as the
|
||||
|
@ -114,7 +114,7 @@ Approx time to complete from here: 2 hours ....
|
|||
|
||||
b. Create a source tarball of the BRANCH sources:
|
||||
|
||||
./src-release -x binutils
|
||||
./src-release.sh -x binutils
|
||||
|
||||
c. Build a test target using this tarball.
|
||||
|
||||
|
@ -262,8 +262,8 @@ When the time comes to actually make the release....
|
|||
chmod -R -w binutils-2.*
|
||||
mkdir build
|
||||
cd build
|
||||
../binutils-2.*/configure --quiet --enable-gold --prefix=`pwd`/install --enable-plugins
|
||||
make all-gas all-gold all-ld all-binutils all-gprof
|
||||
../binutils-2.*/configure --quiet --enable-gold --prefix=`pwd`/install --enable-plugins --enable-shared
|
||||
make all-gas all-gold all-ld all-binutils all-gprof all-gprofng
|
||||
make check-gas check-binutils check-ld check-gold
|
||||
make install-gas install-gold install-ld install-binutils
|
||||
|
||||
|
|
18
configure
vendored
18
configure
vendored
|
@ -787,6 +787,7 @@ enable_as_accelerator_for
|
|||
enable_offload_targets
|
||||
enable_gold
|
||||
enable_ld
|
||||
enable_gprofng
|
||||
enable_compressed_debug_sections
|
||||
enable_libquadmath
|
||||
enable_libquadmath_support
|
||||
|
@ -1514,6 +1515,7 @@ Optional Features:
|
|||
offload target compiler during the build
|
||||
--enable-gold[=ARG] build gold [ARG={default,yes,no}]
|
||||
--enable-ld[=ARG] build ld [ARG={default,yes,no}]
|
||||
--enable-gprofng[=ARG] build gprofng [ARG={yes,no}]
|
||||
--enable-compressed-debug-sections={all,gas,gold,ld,none}
|
||||
Enable compressed debug sections for gas, gold or ld
|
||||
by default
|
||||
|
@ -3072,6 +3074,22 @@ $as_echo "$as_me: WARNING: neither ld nor gold are enabled" >&2;}
|
|||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-gprofng was given.
|
||||
if test "${enable_gprofng+set}" = set; then :
|
||||
enableval=$enable_gprofng; enable_gprofng=$enableval
|
||||
else
|
||||
enable_gprofng=yes
|
||||
fi
|
||||
|
||||
if test "$enable_gprofng" = "yes"; then
|
||||
case "${target}" in
|
||||
x86_64-*-linux* | i?86-*-linux* | aarch64-*-linux*)
|
||||
configdirs="$configdirs gprofng"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# PR gas/19109
|
||||
# Decide the default method for compressing debug sections.
|
||||
# Provide a configure time option to override our default.
|
||||
|
|
14
configure.ac
14
configure.ac
|
@ -392,6 +392,20 @@ case "${ENABLE_LD}" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(gprofng,
|
||||
[AS_HELP_STRING([[--enable-gprofng[=ARG]]],
|
||||
[build gprofng @<:@ARG={yes,no}@:>@])],
|
||||
enable_gprofng=$enableval,
|
||||
enable_gprofng=yes)
|
||||
if test "$enable_gprofng" = "yes"; then
|
||||
case "${target}" in
|
||||
x86_64-*-linux* | i?86-*-linux* | aarch64-*-linux*)
|
||||
configdirs="$configdirs gprofng"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# PR gas/19109
|
||||
# Decide the default method for compressing debug sections.
|
||||
# Provide a configure time option to override our default.
|
||||
|
|
79
gprofng/Makefile.am
Normal file
79
gprofng/Makefile.am
Normal file
|
@ -0,0 +1,79 @@
|
|||
## Process this file with automake to generate Makefile.in
|
||||
#
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I . -I ..
|
||||
|
||||
AUTOMAKE_OPTIONS = dejagnu foreign
|
||||
|
||||
if BUILD_COLLECTOR
|
||||
COLLECTOR_SUBDIRS = libcollector
|
||||
endif
|
||||
if BUILD_SRC
|
||||
SRC_SUBDIRS = src gp-display-html doc
|
||||
endif
|
||||
SUBDIRS = $(COLLECTOR_SUBDIRS) $(SRC_SUBDIRS)
|
||||
DIST_SUBDIRS = libcollector src gp-display-html doc
|
||||
|
||||
# Setup the testing framework, if you have one
|
||||
EXPECT = expect
|
||||
RUNTEST = runtest
|
||||
RUNTESTFLAGS =
|
||||
|
||||
BASEDIR = $(srcdir)/..
|
||||
BFDDIR = $(BASEDIR)/bfd
|
||||
jdk_inc = @jdk_inc@
|
||||
LD_NO_AS_NEEDED = @LD_NO_AS_NEEDED@
|
||||
GPROFNG_CFLAGS = @GPROFNG_CFLAGS@
|
||||
GPROFNG_CPPFLAGS = @GPROFNG_CPPFLAGS@
|
||||
GPROFNG_LIBDIR = @GPROFNG_LIBDIR@
|
||||
|
||||
AM_MAKEFLAGS = \
|
||||
jdk_inc="$(jdk_inc)" \
|
||||
LD_NO_AS_NEEDED="$(LD_NO_AS_NEEDED)" \
|
||||
GPROFNG_CFLAGS="$(GPROFNG_CFLAGS)" \
|
||||
GPROFNG_CPPFLAGS="$(GPROFNG_CPPFLAGS)" \
|
||||
GPROFNG_LIBDIR="$(GPROFNG_LIBDIR)"
|
||||
|
||||
if TCL_TRY
|
||||
check-DEJAGNU: site.exp development.exp
|
||||
srcroot=`cd $(srcdir) && pwd`; export srcroot; \
|
||||
r=`pwd`; export r; \
|
||||
LC_ALL=C; export LC_ALL; \
|
||||
EXPECT=$(EXPECT); export EXPECT; \
|
||||
jdk_inc="$(jdk_inc)"; export jdk_inc; \
|
||||
runtest=$(RUNTEST); \
|
||||
if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
|
||||
$$runtest --tool $(DEJATOOL) --srcdir $${srcroot}/testsuite \
|
||||
MAKE="$(MAKE)" CC="$(CC)" CFLAGS="$(CFLAGS) $(PTHREAD_CFLAGS)" \
|
||||
LDFLAGS="$(LDFLAGS)" LIBS="$(PTHREAD_LIBS) $(LIBS)" \
|
||||
BUILDDIR="$(abs_top_builddir)" $(RUNTESTFLAGS); \
|
||||
else echo "WARNING: could not find \`runtest'" 1>&2; :;\
|
||||
fi
|
||||
|
||||
development.exp: $(BFDDIR)/development.sh
|
||||
$(EGREP) "(development|experimental)=" $(BFDDIR)/development.sh \
|
||||
| $(AWK) -F= '{ print "set " $$1 " " $$2 }' > $@
|
||||
|
||||
# development.sh is used to determine -Werror default.
|
||||
CONFIG_STATUS_DEPENDENCIES = $(BFDDIR)/development.sh
|
||||
|
||||
EXTRA_DEJAGNU_SITE_CONFIG = development.exp
|
||||
|
||||
DISTCLEANFILES = site.exp development.exp
|
||||
endif
|
||||
|
940
gprofng/Makefile.in
Normal file
940
gprofng/Makefile.in
Normal file
|
@ -0,0 +1,940 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
#
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = .
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \
|
||||
$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
|
||||
$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/../config/warnings.m4 \
|
||||
$(top_srcdir)/../config/enable.m4 \
|
||||
$(top_srcdir)/../config/ax_pthread.m4 \
|
||||
$(top_srcdir)/config/bison.m4 $(top_srcdir)/../bfd/version.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
|
||||
$(am__configure_deps) $(am__DIST_COMMON)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||
install-data-recursive install-dvi-recursive \
|
||||
install-exec-recursive install-html-recursive \
|
||||
install-info-recursive install-pdf-recursive \
|
||||
install-ps-recursive install-recursive installcheck-recursive \
|
||||
installdirs-recursive pdf-recursive ps-recursive \
|
||||
tags-recursive uninstall-recursive
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
am__recursive_targets = \
|
||||
$(RECURSIVE_TARGETS) \
|
||||
$(RECURSIVE_CLEAN_TARGETS) \
|
||||
$(am__extra_recursive_targets)
|
||||
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||
cscope distdir dist dist-all distcheck
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
CSCOPE = cscope
|
||||
DEJATOOL = $(PACKAGE)
|
||||
RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/../ar-lib \
|
||||
$(top_srcdir)/../compile $(top_srcdir)/../config.guess \
|
||||
$(top_srcdir)/../config.sub $(top_srcdir)/../install-sh \
|
||||
$(top_srcdir)/../ltmain.sh $(top_srcdir)/../missing \
|
||||
$(top_srcdir)/../mkinstalldirs \
|
||||
$(top_srcdir)/common/config.h.in README
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
am__remove_distdir = \
|
||||
if test -d "$(distdir)"; then \
|
||||
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
&& rm -rf "$(distdir)" \
|
||||
|| { sleep 5 && rm -rf "$(distdir)"; }; \
|
||||
else :; fi
|
||||
am__post_remove_distdir = $(am__remove_distdir)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
DIST_ARCHIVES = $(distdir).tar.gz
|
||||
GZIP_ENV = --best
|
||||
DIST_TARGETS = dist-gzip
|
||||
distuninstallcheck_listfiles = find . -type f -print
|
||||
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
||||
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_SUBDIRS = @BUILD_SUBDIRS@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
# Setup the testing framework, if you have one
|
||||
EXPECT = expect
|
||||
FGREP = @FGREP@
|
||||
GPROFNG_CFLAGS = @GPROFNG_CFLAGS@
|
||||
GPROFNG_CPPFLAGS = @GPROFNG_CPPFLAGS@
|
||||
GPROFNG_LIBADD = @GPROFNG_LIBADD@
|
||||
GPROFNG_LIBDIR = @GPROFNG_LIBDIR@
|
||||
GREP = @GREP@
|
||||
HELP2MAN = @HELP2MAN@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
JAVA = @JAVA@
|
||||
JAVAC = @JAVAC@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LD_NO_AS_NEEDED = @LD_NO_AS_NEEDED@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
WERROR = @WERROR@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
ax_pthread_config = @ax_pthread_config@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
gprofng_cflags = @gprofng_cflags@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
jdk_inc = @jdk_inc@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
ACLOCAL_AMFLAGS = -I . -I ..
|
||||
AUTOMAKE_OPTIONS = dejagnu foreign
|
||||
@BUILD_COLLECTOR_TRUE@COLLECTOR_SUBDIRS = libcollector
|
||||
@BUILD_SRC_TRUE@SRC_SUBDIRS = src gp-display-html doc
|
||||
SUBDIRS = $(COLLECTOR_SUBDIRS) $(SRC_SUBDIRS)
|
||||
DIST_SUBDIRS = libcollector src gp-display-html doc
|
||||
RUNTEST = runtest
|
||||
RUNTESTFLAGS =
|
||||
BASEDIR = $(srcdir)/..
|
||||
BFDDIR = $(BASEDIR)/bfd
|
||||
AM_MAKEFLAGS = \
|
||||
jdk_inc="$(jdk_inc)" \
|
||||
LD_NO_AS_NEEDED="$(LD_NO_AS_NEEDED)" \
|
||||
GPROFNG_CFLAGS="$(GPROFNG_CFLAGS)" \
|
||||
GPROFNG_CPPFLAGS="$(GPROFNG_CPPFLAGS)" \
|
||||
GPROFNG_LIBDIR="$(GPROFNG_LIBDIR)"
|
||||
|
||||
|
||||
# development.sh is used to determine -Werror default.
|
||||
@TCL_TRY_TRUE@CONFIG_STATUS_DEPENDENCIES = $(BFDDIR)/development.sh
|
||||
@TCL_TRY_TRUE@EXTRA_DEJAGNU_SITE_CONFIG = development.exp
|
||||
@TCL_TRY_TRUE@DISTCLEANFILES = site.exp development.exp
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
am--refresh: Makefile
|
||||
@:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
|
||||
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
config.h: stamp-h1
|
||||
@test -f $@ || rm -f stamp-h1
|
||||
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
|
||||
|
||||
stamp-h1: $(top_srcdir)/common/config.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||
$(top_srcdir)/common/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool config.lt
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run 'make' without going through this Makefile.
|
||||
# To change the values of 'make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in 'config.status', edit 'config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run 'make');
|
||||
# (2) otherwise, pass the desired values on the 'make' command line.
|
||||
$(am__recursive_targets):
|
||||
@fail=; \
|
||||
if $(am__make_keepgoing); then \
|
||||
failcom='fail=yes'; \
|
||||
else \
|
||||
failcom='exit 1'; \
|
||||
fi; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-recursive
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-recursive
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscope: cscope.files
|
||||
test ! -s cscope.files \
|
||||
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
|
||||
clean-cscope:
|
||||
-rm -f cscope.files
|
||||
cscope.files: clean-cscope cscopelist
|
||||
cscopelist: cscopelist-recursive
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||
|
||||
@TCL_TRY_FALSE@check-DEJAGNU: site.exp
|
||||
@TCL_TRY_FALSE@ srcdir='$(srcdir)'; export srcdir; \
|
||||
@TCL_TRY_FALSE@ EXPECT=$(EXPECT); export EXPECT; \
|
||||
@TCL_TRY_FALSE@ if $(SHELL) -c "$(RUNTEST) --version" > /dev/null 2>&1; then \
|
||||
@TCL_TRY_FALSE@ exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \
|
||||
@TCL_TRY_FALSE@ if $(RUNTEST) $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
|
||||
@TCL_TRY_FALSE@ then :; else exit_status=1; fi; \
|
||||
@TCL_TRY_FALSE@ done; \
|
||||
@TCL_TRY_FALSE@ else echo "WARNING: could not find '$(RUNTEST)'" 1>&2; :;\
|
||||
@TCL_TRY_FALSE@ fi; \
|
||||
@TCL_TRY_FALSE@ exit $$exit_status
|
||||
site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
|
||||
@echo 'Making a new site.exp file ...'
|
||||
@echo '## these variables are automatically generated by make ##' >site.tmp
|
||||
@echo '# Do not edit here. If you wish to override these values' >>site.tmp
|
||||
@echo '# edit the last section' >>site.tmp
|
||||
@echo 'set srcdir "$(srcdir)"' >>site.tmp
|
||||
@echo "set objdir `pwd`" >>site.tmp
|
||||
@echo 'set build_alias "$(build_alias)"' >>site.tmp
|
||||
@echo 'set build_triplet $(build_triplet)' >>site.tmp
|
||||
@echo 'set host_alias "$(host_alias)"' >>site.tmp
|
||||
@echo 'set host_triplet $(host_triplet)' >>site.tmp
|
||||
@list='$(EXTRA_DEJAGNU_SITE_CONFIG)'; for f in $$list; do \
|
||||
echo "## Begin content included from file $$f. Do not modify. ##" \
|
||||
&& cat `test -f "$$f" || echo '$(srcdir)/'`$$f \
|
||||
&& echo "## End content included from file $$f. ##" \
|
||||
|| exit 1; \
|
||||
done >> site.tmp
|
||||
@echo "## End of auto-generated content; you can edit from here. ##" >> site.tmp
|
||||
@if test -f site.exp; then \
|
||||
sed -e '1,/^## End of auto-generated content.*##/d' site.exp >> site.tmp; \
|
||||
fi
|
||||
@-rm -f site.bak
|
||||
@test ! -f site.exp || mv site.exp site.bak
|
||||
@mv site.tmp site.exp
|
||||
|
||||
distclean-DEJAGNU:
|
||||
-rm -f site.exp site.bak
|
||||
-l='$(DEJATOOL)'; for tool in $$l; do \
|
||||
rm -f $$tool.sum $$tool.log; \
|
||||
done
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
$(am__make_dryrun) \
|
||||
|| test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
-test -n "$(am__skip_mode_fix)" \
|
||||
|| find "$(distdir)" -type d ! -perm -755 \
|
||||
-exec chmod u+rwx,go+rx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r "$(distdir)"
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-bzip2: distdir
|
||||
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-lzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-xz: distdir
|
||||
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
@echo WARNING: "Support for distribution archives compressed with" \
|
||||
"legacy program 'compress' is deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-shar: distdir
|
||||
@echo WARNING: "Support for shar distribution archives is" \
|
||||
"deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist dist-all:
|
||||
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lz*) \
|
||||
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
|
||||
*.tar.xz*) \
|
||||
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir)
|
||||
chmod u+w $(distdir)
|
||||
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
|
||||
chmod a-w $(distdir)
|
||||
test -d $(distdir)/_build || exit 0; \
|
||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||
&& am__cwd=`pwd` \
|
||||
&& $(am__cd) $(distdir)/_build/sub \
|
||||
&& ../../configure \
|
||||
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
|
||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||
--srcdir=../.. --prefix="$$dc_install_base" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||
distuninstallcheck \
|
||||
&& chmod -R a-w "$$dc_install_base" \
|
||||
&& ({ \
|
||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||
&& rm -rf "$$dc_destdir" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||
&& rm -rf $(DIST_ARCHIVES) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||
&& cd "$$am__cwd" \
|
||||
|| exit 1
|
||||
$(am__post_remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@test -n '$(distuninstallcheck_dir)' || { \
|
||||
echo 'ERROR: trying to run $@ with an empty' \
|
||||
'$$(distuninstallcheck_dir)' >&2; \
|
||||
exit 1; \
|
||||
}; \
|
||||
$(am__cd) '$(distuninstallcheck_dir)' || { \
|
||||
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
|
||||
exit 1; \
|
||||
}; \
|
||||
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left after uninstall:" ; \
|
||||
if test -n "$(DESTDIR)"; then \
|
||||
echo " (check DESTDIR support)"; \
|
||||
fi ; \
|
||||
$(distuninstallcheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
distcleancheck: distclean
|
||||
@if test '$(srcdir)' = . ; then \
|
||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||
$(distcleancheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
|
||||
check: check-recursive
|
||||
all-am: Makefile config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-DEJAGNU distclean-generic \
|
||||
distclean-hdr distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(am__recursive_targets) all check-am install-am install-strip
|
||||
|
||||
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
|
||||
am--refresh check check-DEJAGNU check-am clean clean-cscope \
|
||||
clean-generic clean-libtool cscope cscopelist-am ctags \
|
||||
ctags-am dist dist-all dist-bzip2 dist-gzip dist-lzip \
|
||||
dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \
|
||||
distclean-DEJAGNU distclean-generic distclean-hdr \
|
||||
distclean-libtool distclean-tags distcleancheck distdir \
|
||||
distuninstallcheck dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
installdirs-am maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
|
||||
ps ps-am tags tags-am uninstall uninstall-am
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
@TCL_TRY_TRUE@check-DEJAGNU: site.exp development.exp
|
||||
@TCL_TRY_TRUE@ srcroot=`cd $(srcdir) && pwd`; export srcroot; \
|
||||
@TCL_TRY_TRUE@ r=`pwd`; export r; \
|
||||
@TCL_TRY_TRUE@ LC_ALL=C; export LC_ALL; \
|
||||
@TCL_TRY_TRUE@ EXPECT=$(EXPECT); export EXPECT; \
|
||||
@TCL_TRY_TRUE@ jdk_inc="$(jdk_inc)"; export jdk_inc; \
|
||||
@TCL_TRY_TRUE@ runtest=$(RUNTEST); \
|
||||
@TCL_TRY_TRUE@ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
|
||||
@TCL_TRY_TRUE@ $$runtest --tool $(DEJATOOL) --srcdir $${srcroot}/testsuite \
|
||||
@TCL_TRY_TRUE@ MAKE="$(MAKE)" CC="$(CC)" CFLAGS="$(CFLAGS) $(PTHREAD_CFLAGS)" \
|
||||
@TCL_TRY_TRUE@ LDFLAGS="$(LDFLAGS)" LIBS="$(PTHREAD_LIBS) $(LIBS)" \
|
||||
@TCL_TRY_TRUE@ BUILDDIR="$(abs_top_builddir)" $(RUNTESTFLAGS); \
|
||||
@TCL_TRY_TRUE@ else echo "WARNING: could not find \`runtest'" 1>&2; :;\
|
||||
@TCL_TRY_TRUE@ fi
|
||||
|
||||
@TCL_TRY_TRUE@development.exp: $(BFDDIR)/development.sh
|
||||
@TCL_TRY_TRUE@ $(EGREP) "(development|experimental)=" $(BFDDIR)/development.sh \
|
||||
@TCL_TRY_TRUE@ | $(AWK) -F= '{ print "set " $$1 " " $$2 }' > $@
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
100
gprofng/README
Normal file
100
gprofng/README
Normal file
|
@ -0,0 +1,100 @@
|
|||
What is gprofng?
|
||||
|
||||
Gprofng is the GNU Next Generation profiler for analyzing the performance
|
||||
of Linux applications. Gprofng allows you to:
|
||||
- Profile C / C++ / Java / Scala applications without needing to recompile
|
||||
- Profile multi-threaded applications
|
||||
- Analyze and compare multiple experiments
|
||||
- Use time-based sampling and / or hardware event counters
|
||||
|
||||
Building gprofng
|
||||
|
||||
Gprofng is distributed with binutils. To build gprofng, you build binutils.
|
||||
Overview:
|
||||
1. Set paths
|
||||
2. Verify prerequisites
|
||||
3. Git clone
|
||||
4. Configure, make, and make install
|
||||
Details follow for each of these.
|
||||
|
||||
1. Set paths
|
||||
|
||||
If you are configuring binutils for the default location, it will use:
|
||||
/usr/local
|
||||
In your shell initialization procedure, set your paths using commands
|
||||
similar to these:
|
||||
export PATH=/usr/local/bin:$PATH
|
||||
export MANPATH=/usr/local/share/man:$MANPATH
|
||||
export INFOPATH=/usr/local/share/info/:$INFOPATH
|
||||
|
||||
2. Verify prerequisites
|
||||
|
||||
To build a recent version of binutils, it is useful to have a developer
|
||||
system with the most recent compilers, libraries, and operating system.
|
||||
Development systems will typically already include most of these:
|
||||
|
||||
bison bison-devel bzip2 elfutils-debuginfod-client-devel
|
||||
expat-devel flex gcc gcc-c++ git-core git-core-doc gmp-devel
|
||||
help2man libbabeltrace-devel libipt-devel m4 make mpfr-devel
|
||||
ncurses-devel perl-Data-Dumper tar texinfo xz zlib-devel
|
||||
java-17-openjdk-devel
|
||||
|
||||
CAUTION: The list of prerequisites changes depending on your operating system
|
||||
and changes as binutils evolves. The list above is a snapshot of the useful
|
||||
packages in early 2022 for Red Hat Enterprise Linux and Oracle Linux.
|
||||
|
||||
Your system may use other packages; for example, you may be able to use a
|
||||
different version of Java than shown above. If there are failures, you may
|
||||
need to search for other packages as described in the "Hints" section below.
|
||||
|
||||
3. Git clone
|
||||
|
||||
Select a binutils repository and a branch that you would like
|
||||
to start from. For example, to clone from the master at
|
||||
sourceware.org, you could say:
|
||||
git clone http://sourceware.org/git/binutils-gdb.git CloneDir
|
||||
|
||||
4. Configure, make, and install
|
||||
|
||||
There are many options for configure (see: configure --help). For example,
|
||||
--prefix sets the destination, as described in the "Hints" section below.
|
||||
If the default destination /usr/local is acceptable for your needs, then
|
||||
after the clone operation finishes, you can simply say:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
../CloneDir/configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
Getting started
|
||||
|
||||
To start using gprofng, see the tutorial available by saying:
|
||||
info gprofng
|
||||
|
||||
Hints and tips for building binutils
|
||||
|
||||
- Use the script(1) command to write a log of your build.
|
||||
|
||||
- If you run multiple commands at once (for example: make --jobs=10) then you
|
||||
should also use make option:
|
||||
--output-sync
|
||||
Without --output-sync, the log would be difficult to interpret.
|
||||
|
||||
- Search the log for errors and warnings, for example:
|
||||
configure: WARNING: <package> is missing or unusable; some features
|
||||
may be unavailable.
|
||||
The above message suggests that <package> may be needed on your system.
|
||||
|
||||
- Sometimes the above message is not sufficiently specific to guide you to
|
||||
the right package. In the directory where the failure happens, config.log
|
||||
may identify a specific missing file, and your package manager may allow
|
||||
you to search for it. For example, if build/gprofng/config.log shows that
|
||||
javac is missing, and if your package manager is dnf, you could try:
|
||||
dnf --repo='*' whatprovides '*/javac'
|
||||
|
||||
- You can set a custom destination directory using configure --prefix.
|
||||
This is useful if you prefer not to change /usr/local, or if you are not
|
||||
allowed to do so. If you set a custom prefix, be sure to change all three
|
||||
paths mentioned in the PATH section above.
|
||||
|
4
gprofng/acinclude.m4
Normal file
4
gprofng/acinclude.m4
Normal file
|
@ -0,0 +1,4 @@
|
|||
m4_include([../config/warnings.m4])
|
||||
m4_include([../config/enable.m4])
|
||||
m4_include([../config/ax_pthread.m4])
|
||||
m4_include([config/bison.m4])
|
1254
gprofng/aclocal.m4
vendored
Normal file
1254
gprofng/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
44
gprofng/common/cc_libcollector.h
Normal file
44
gprofng/common/cc_libcollector.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* This file describes the enum's, etc. shared by the collector control
|
||||
* class and libcollector and its modules. It is #included in collctrl.h
|
||||
* so any changes to it should follow the procedure described there.
|
||||
*/
|
||||
|
||||
#ifndef _CC_LIBCOLLECTOR_H
|
||||
#define _CC_LIBCOLLECTOR_H
|
||||
|
||||
/* definitions for synchronization tracing scope -- a bit mask */
|
||||
#define SYNCSCOPE_NATIVE 0x1
|
||||
#define SYNCSCOPE_JAVA 0x2
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FOLLOW_NONE = 0x0,
|
||||
FOLLOW_EXEC = 0x1,
|
||||
FOLLOW_FORK = 0x2,
|
||||
FOLLOW_ON = 0x3,
|
||||
FOLLOW_COMBO = 0x4,
|
||||
FOLLOW_ALL = 0x7
|
||||
} Follow_type;
|
||||
|
||||
#endif /* !__CC_LIBCOLLECTOR_H */
|
117
gprofng/common/config.h.in
Normal file
117
gprofng/common/config.h.in
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* common/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Enable debugging output. */
|
||||
#undef DEBUG
|
||||
|
||||
/* Enable java profiling */
|
||||
#undef GPROFNG_JAVA_PROFILING
|
||||
|
||||
/* Define to 1 if you have the declaration of `basename', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_BASENAME
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strsignal' function. */
|
||||
#undef HAVE_STRSIGNAL
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
3023
gprofng/common/core_pcbe.c
Normal file
3023
gprofng/common/core_pcbe.c
Normal file
File diff suppressed because it is too large
Load diff
303
gprofng/common/cpu_frequency.h
Normal file
303
gprofng/common/cpu_frequency.h
Normal file
|
@ -0,0 +1,303 @@
|
|||
/* Copyright (C) 2021 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 _CPU_FREQUENCY_H
|
||||
#define _CPU_FREQUENCY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
#include <unistd.h> /* processor_info_t */
|
||||
#include <fcntl.h>
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
#define MAXSTRLEN 1024
|
||||
/*
|
||||
* This file provide the api to detect Intel CPU frequency variation features
|
||||
*/
|
||||
|
||||
#define COL_CPUFREQ_NONE 0x0000
|
||||
#define COL_CPUFREQ_SCALING 0x0001
|
||||
#define COL_CPUFREQ_TURBO 0x0002
|
||||
|
||||
#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
|
||||
|
||||
// YLM: one can use cputrack to estimate max turbo frequency
|
||||
// example: for a cpu-bound app that runs for > 10 seconds, count cycles for 10 seconds:
|
||||
// cputrack -T 10 -v -c cpu_clk_unhalted.thread_p a.out
|
||||
|
||||
static int
|
||||
get_max_turbo_freq (int model)
|
||||
{
|
||||
switch (model)
|
||||
{
|
||||
// Nehalem
|
||||
case 30:// Core i7-870: 2/2/4/5
|
||||
return 2 * 133333;
|
||||
case 26:// Xeon L5520: 1/1/1/2
|
||||
return 2 * 133333;
|
||||
case 46:// Xeon E7540: 2
|
||||
return 2 * 133333;
|
||||
// Westmere
|
||||
case 37:// Core i5-520M: 2/4
|
||||
return 2 * 133333;
|
||||
case 44:// Xeon E5620: 1/1/2/2
|
||||
return 2 * 133333;
|
||||
case 47:// Xeon E7-2820: 1/1/1/2
|
||||
return 1 * 133333;
|
||||
// Sandy Bridge
|
||||
case 42:// Core i5-2500: 1/2/3/4
|
||||
return 3 * 100000;
|
||||
// http://ark.intel.com/products/64584/Intel-Xeon-Processor-E5-2660-20M-Cache-2_20-GHz-8_00-GTs-Intel-QPI
|
||||
case 45:// Xeon E5-2660 GenuineIntel 206D7 family 6 model 45 step 7 clock 2200 MHz
|
||||
return 8 * 100000;
|
||||
// Ivy Bridge
|
||||
case 58:// Core i7-3770: 3/4/5/5
|
||||
return 4 * 100000;
|
||||
case 62:// Xeon E5-2697: 3/3/3/3/3/3/3/4/5/6/7/8
|
||||
return 7 * 100000;
|
||||
// Haswell
|
||||
case 60:
|
||||
return 789000; // empirically we see 3189 MHz - 2400 MHz
|
||||
case 63:
|
||||
return 1280000; // empirically we see 3580 MHz - 2300 MHz for single-threaded
|
||||
// return 500000; // empirically we see 2800 MHz - 2300 MHz for large throughput
|
||||
// Broadwell
|
||||
// where are these values listed?
|
||||
// maybe try https://en.wikipedia.org/wiki/Broadwell_%28microarchitecture%29#Server_processors
|
||||
case 61:
|
||||
return 400000;
|
||||
case 71:
|
||||
return 400000;
|
||||
case 79:
|
||||
return 950000; // empirically we see (3550-2600) MHz for single-threaded on x6-2a
|
||||
case 85:
|
||||
return 1600000; // X7: empirically see ~3.7GHz with single thread, baseline is 2.1Ghz Return 3,700,000-2,100,000
|
||||
case 31: // Nehalem?
|
||||
case 28: // Atom
|
||||
case 69: // Haswell
|
||||
case 70: // Haswell
|
||||
case 78: // Skylake
|
||||
case 94: // Skylake
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* parameter: mode, pointer to a 8bit mode indicator
|
||||
* return: max cpu frequency in MHz
|
||||
*/
|
||||
//YXXX Updating this function? Check similar cut/paste code in:
|
||||
// collctrl.cc::Coll_Ctrl()
|
||||
// collector.c::log_header_write()
|
||||
// cpu_frequency.h::get_cpu_frequency()
|
||||
|
||||
static int
|
||||
get_cpu_frequency (uint8_t *mode)
|
||||
{
|
||||
int ret_freq = 0;
|
||||
if (mode != NULL)
|
||||
*mode = COL_CPUFREQ_NONE;
|
||||
FILE *procf = fopen ("/proc/cpuinfo", "r");
|
||||
if (procf != NULL)
|
||||
{
|
||||
char temp[1024];
|
||||
int cpu = -1;
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
int model = -1;
|
||||
int family = -1;
|
||||
#endif
|
||||
while (fgets (temp, 1024, procf) != NULL)
|
||||
{
|
||||
if (strncmp (temp, "processor", strlen ("processor")) == 0)
|
||||
{
|
||||
char *val = strchr (temp, ':');
|
||||
cpu = val ? atoi (val + 1) : -1;
|
||||
}
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
else if (strncmp (temp, "model", strlen ("model")) == 0
|
||||
&& strstr (temp, "name") == 0)
|
||||
{
|
||||
char *val = strchr (temp, ':');
|
||||
model = val ? atoi (val + 1) : -1;
|
||||
}
|
||||
else if (strncmp (temp, "cpu family", strlen ("cpu family")) == 0)
|
||||
{
|
||||
char *val = strchr (temp, ':');
|
||||
family = val ? atoi (val + 1) : -1;
|
||||
}
|
||||
#endif
|
||||
else if (strncmp (temp, "cpu MHz", strlen ("cpu MHz")) == 0)
|
||||
{
|
||||
char *val = strchr (temp, ':');
|
||||
int mhz = val ? atoi (val + 1) : 0; /* reading it as int is fine */
|
||||
char scaling_freq_file[MAXSTRLEN + 1];
|
||||
snprintf (scaling_freq_file, sizeof (scaling_freq_file),
|
||||
"/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", cpu);
|
||||
int intel_pstate = 0;
|
||||
int no_turbo = 0;
|
||||
if (access (scaling_freq_file, R_OK) == 0)
|
||||
{
|
||||
FILE *cpufreqd = fopen (scaling_freq_file, "r");
|
||||
if (cpufreqd != NULL)
|
||||
{
|
||||
if (fgets (temp, 1024, cpufreqd) != NULL
|
||||
&& strncmp (temp, "intel_pstate", sizeof ("intel_pstate") - 1) == 0)
|
||||
intel_pstate = 1;
|
||||
fclose (cpufreqd);
|
||||
}
|
||||
}
|
||||
snprintf (scaling_freq_file, sizeof (scaling_freq_file),
|
||||
"/sys/devices/system/cpu/intel_pstate/no_turbo");
|
||||
if (access (scaling_freq_file, R_OK) == 0)
|
||||
{
|
||||
FILE *pstatent = fopen (scaling_freq_file, "r");
|
||||
if (pstatent != NULL)
|
||||
{
|
||||
if (fgets (temp, 1024, pstatent) != NULL)
|
||||
if (strncmp (temp, "1", sizeof ("1") - 1) == 0)
|
||||
no_turbo = 1;
|
||||
fclose (pstatent);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf (scaling_freq_file, sizeof (scaling_freq_file),
|
||||
"/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpu);
|
||||
int frequency_scaling = 0;
|
||||
int turbo_mode = 0;
|
||||
if (access (scaling_freq_file, R_OK) == 0)
|
||||
{
|
||||
FILE *cpufreqf = fopen (scaling_freq_file, "r");
|
||||
if (cpufreqf != NULL)
|
||||
{
|
||||
if (fgets (temp, 1024, cpufreqf) != NULL)
|
||||
{
|
||||
int ondemand = 0;
|
||||
if (strncmp (temp, "ondemand", sizeof ("ondemand") - 1) == 0)
|
||||
ondemand = 1;
|
||||
int performance = 0;
|
||||
if (strncmp (temp, "performance", sizeof ("performance") - 1) == 0)
|
||||
performance = 1;
|
||||
int powersave = 0;
|
||||
if (strncmp (temp, "powersave", sizeof ("powersave") - 1) == 0)
|
||||
powersave = 1;
|
||||
if (intel_pstate || ondemand || performance)
|
||||
{
|
||||
snprintf (scaling_freq_file, sizeof (scaling_freq_file),
|
||||
"/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
|
||||
if (access (scaling_freq_file, R_OK) == 0)
|
||||
{
|
||||
FILE * cpufreqf_max;
|
||||
if ((cpufreqf_max = fopen (scaling_freq_file, "r")) != NULL)
|
||||
{
|
||||
if (fgets (temp, 1024, cpufreqf_max) != NULL)
|
||||
{
|
||||
int tmpmhz = atoi (temp);
|
||||
snprintf (scaling_freq_file, sizeof (scaling_freq_file),
|
||||
"/sys/devices/system/cpu/cpu%d/cpufreq/scaling_available_frequencies", cpu);
|
||||
if (intel_pstate)
|
||||
{
|
||||
frequency_scaling = 1;
|
||||
turbo_mode = !no_turbo;
|
||||
if (powersave)
|
||||
// the system might have been relatively cold
|
||||
// so we might do better with scaling_max_freq
|
||||
mhz = (int) (((double) tmpmhz / 1000.0) + 0.5);
|
||||
}
|
||||
else if (access (scaling_freq_file, R_OK) == 0)
|
||||
{
|
||||
FILE * cpufreqf_ava;
|
||||
if ((cpufreqf_ava = fopen (scaling_freq_file, "r")) != NULL)
|
||||
{
|
||||
if (fgets (temp, 1024, cpufreqf_ava) != NULL)
|
||||
{
|
||||
if (strchr (temp, ' ') != strrchr (temp, ' ') && ondemand)
|
||||
frequency_scaling = 1;
|
||||
if (tmpmhz > 1000)
|
||||
{
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
if (family == 6)
|
||||
{
|
||||
// test turbo mode
|
||||
char non_turbo_max_freq[1024];
|
||||
snprintf (non_turbo_max_freq, sizeof (non_turbo_max_freq),
|
||||
"%d", tmpmhz - 1000);
|
||||
if (strstr (temp, non_turbo_max_freq))
|
||||
{
|
||||
turbo_mode = 1;
|
||||
tmpmhz = (tmpmhz - 1000) + get_max_turbo_freq (model);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
fclose (cpufreqf_ava);
|
||||
}
|
||||
mhz = (int) (((double) tmpmhz / 1000.0) + 0.5);
|
||||
}
|
||||
}
|
||||
fclose (cpufreqf_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose (cpufreqf);
|
||||
}
|
||||
}
|
||||
if (mhz > ret_freq)
|
||||
ret_freq = mhz;
|
||||
if (frequency_scaling && mode != NULL)
|
||||
*mode |= COL_CPUFREQ_SCALING;
|
||||
if (turbo_mode && mode != NULL)
|
||||
*mode |= COL_CPUFREQ_TURBO;
|
||||
}
|
||||
else if (strncmp (temp, "Cpu", 3) == 0 && temp[3] != '\0' &&
|
||||
strncmp (strchr (temp + 1, 'C') ? strchr (temp + 1, 'C') : (temp + 4), "ClkTck", 6) == 0)
|
||||
{ // sparc-Linux
|
||||
char *val = strchr (temp, ':');
|
||||
if (val)
|
||||
{
|
||||
unsigned long long freq;
|
||||
sscanf (val + 2, "%llx", &freq);
|
||||
int mhz = (unsigned int) (((double) freq) / 1000000.0 + 0.5);
|
||||
if (mhz > ret_freq)
|
||||
ret_freq = mhz;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose (procf);
|
||||
}
|
||||
return ret_freq;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_CPU_FREQUENCY_H*/
|
203
gprofng/common/cpuid.c
Normal file
203
gprofng/common/cpuid.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
#include <cpuid.h> /* GCC-provided */
|
||||
#elif defined(__aarch64__)
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
|
||||
static inline uint_t __attribute_const__
|
||||
__get_cpuid (unsigned int op ATTRIBUTE_UNUSED, unsigned int *eax,
|
||||
unsigned int *ebx ATTRIBUTE_UNUSED,
|
||||
unsigned int *ecx ATTRIBUTE_UNUSED, unsigned int *edx ATTRIBUTE_UNUSED)
|
||||
{
|
||||
// CPUID bit assignments:
|
||||
// [31:24] IMPLEMENTER (0x50 - ARM_CPU_IMP_APM)
|
||||
// [23:20] VARIANT indicates processor revision (0x2 = Revision 2)
|
||||
// [19:16] Constant (Reads as 0xF)
|
||||
// [15:04] PARTNO indicates part number (0xC23 = Cortex-M3)
|
||||
// [03:00] REVISION indicates patch release (0x0 = Patch 0)
|
||||
// unsigned long v = 0;
|
||||
// __asm volatile ("MRS %[result], MPIDR_EL1" : [result] "=r" (v));
|
||||
// Tprintf(DBG_LT0, "cpuid.c:%d read_cpuid_id() MPIDR_EL1=0x%016lx\n", __LINE__, v);
|
||||
uint_t res = 0;
|
||||
__asm volatile ("MRS %[result], MIDR_EL1" : [result] "=r" (*eax));
|
||||
Tprintf (DBG_LT0, "cpuid.c:%d read_cpuid_id() MIDR_EL1=0x%016x\n", __LINE__, *eax);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Various routines to handle identification
|
||||
* and classification of x86 processors.
|
||||
*/
|
||||
|
||||
#define IS_GLOBAL /* externally visible */
|
||||
#define X86_VENDOR_Intel 0
|
||||
#define X86_VENDORSTR_Intel "GenuineIntel"
|
||||
#define X86_VENDOR_IntelClone 1
|
||||
#define X86_VENDOR_AMD 2
|
||||
#define X86_VENDORSTR_AMD "AuthenticAMD"
|
||||
|
||||
#define BITX(u, h, l) (((u) >> (l)) & ((1LU << ((h) - (l) + 1LU)) - 1LU))
|
||||
#define CPI_FAMILY_XTD(reg) BITX(reg, 27, 20)
|
||||
#define CPI_MODEL_XTD(reg) BITX(reg, 19, 16)
|
||||
#define CPI_TYPE(reg) BITX(reg, 13, 12)
|
||||
#define CPI_FAMILY(reg) BITX(reg, 11, 8)
|
||||
#define CPI_STEP(reg) BITX(reg, 3, 0)
|
||||
#define CPI_MODEL(reg) BITX(reg, 7, 4)
|
||||
#define IS_EXTENDED_MODEL_INTEL(model) ((model) == 0x6 || (model) >= 0xf)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int eax;
|
||||
unsigned int ebx;
|
||||
unsigned int ecx;
|
||||
unsigned int edx;
|
||||
} cpuid_regs_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int cpi_model;
|
||||
unsigned int cpi_family;
|
||||
unsigned int cpi_vendor; /* enum of cpi_vendorstr */
|
||||
unsigned int cpi_maxeax; /* fn 0: %eax */
|
||||
char cpi_vendorstr[13]; /* fn 0: %ebx:%ecx:%edx */
|
||||
} cpuid_info_t;
|
||||
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
static uint_t
|
||||
cpuid_vendorstr_to_vendorcode (char *vendorstr)
|
||||
{
|
||||
if (strcmp (vendorstr, X86_VENDORSTR_Intel) == 0)
|
||||
return X86_VENDOR_Intel;
|
||||
else if (strcmp (vendorstr, X86_VENDORSTR_AMD) == 0)
|
||||
return X86_VENDOR_AMD;
|
||||
else
|
||||
return X86_VENDOR_IntelClone;
|
||||
}
|
||||
|
||||
static int
|
||||
my_cpuid (unsigned int op, cpuid_regs_t *regs)
|
||||
{
|
||||
regs->eax = regs->ebx = regs->ecx = regs->edx = 0;
|
||||
int ret = __get_cpuid (op, ®s->eax, ®s->ebx, ®s->ecx, ®s->edx);
|
||||
TprintfT (DBG_LT1, "my_cpuid: __get_cpuid(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) returns %d\n",
|
||||
op, regs->eax, regs->ebx, regs->ecx, regs->edx, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static cpuid_info_t *
|
||||
get_cpuid_info ()
|
||||
{
|
||||
static int cpuid_inited = 0;
|
||||
static cpuid_info_t cpuid_info;
|
||||
cpuid_info_t *cpi = &cpuid_info;
|
||||
if (cpuid_inited)
|
||||
return cpi;
|
||||
cpuid_inited = 1;
|
||||
|
||||
#if defined(__aarch64__)
|
||||
// CPUID bit assignments:
|
||||
// [31:24] IMPLEMENTER (0x50 - ARM_CPU_IMP_APM)
|
||||
// [23:20] VARIANT indicates processor revision (0x2 = Revision 2)
|
||||
// [19:16] Constant (Reads as 0xF)
|
||||
// [15:04] PARTNO indicates part number (0xC23 = Cortex-M3)
|
||||
// [03:00] REVISION indicates patch release (0x0 = Patch 0)
|
||||
uint_t reg = 0;
|
||||
__asm volatile ("MRS %[result], MIDR_EL1" : [result] "=r" (reg));
|
||||
cpi->cpi_vendor = reg >> 24;
|
||||
cpi->cpi_model = (reg >> 4) & 0xfff;
|
||||
switch (cpi->cpi_vendor)
|
||||
{
|
||||
case ARM_CPU_IMP_APM:
|
||||
case ARM_CPU_IMP_ARM:
|
||||
case ARM_CPU_IMP_CAVIUM:
|
||||
case ARM_CPU_IMP_BRCM:
|
||||
case ARM_CPU_IMP_QCOM:
|
||||
strncpy (cpi->cpi_vendorstr, AARCH64_VENDORSTR_ARM, sizeof (cpi->cpi_vendorstr));
|
||||
break;
|
||||
default:
|
||||
strncpy (cpi->cpi_vendorstr, "UNKNOWN ARM", sizeof (cpi->cpi_vendorstr));
|
||||
break;
|
||||
}
|
||||
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)
|
||||
cpuid_regs_t regs;
|
||||
my_cpuid (0, ®s);
|
||||
cpi->cpi_maxeax = regs.eax;
|
||||
((uint32_t *) cpi->cpi_vendorstr)[0] = regs.ebx;
|
||||
((uint32_t *) cpi->cpi_vendorstr)[1] = regs.edx;
|
||||
((uint32_t *) cpi->cpi_vendorstr)[2] = regs.ecx;
|
||||
cpi->cpi_vendorstr[12] = 0;
|
||||
cpi->cpi_vendor = cpuid_vendorstr_to_vendorcode (cpi->cpi_vendorstr);
|
||||
|
||||
my_cpuid (1, ®s);
|
||||
cpi->cpi_model = CPI_MODEL (regs.eax);
|
||||
cpi->cpi_family = CPI_FAMILY (regs.eax);
|
||||
if (cpi->cpi_family == 0xf)
|
||||
cpi->cpi_family += CPI_FAMILY_XTD (regs.eax);
|
||||
|
||||
/*
|
||||
* Beware: AMD uses "extended model" iff base *FAMILY* == 0xf.
|
||||
* Intel, and presumably everyone else, uses model == 0xf, as
|
||||
* one would expect (max value means possible overflow). Sigh.
|
||||
*/
|
||||
switch (cpi->cpi_vendor)
|
||||
{
|
||||
case X86_VENDOR_Intel:
|
||||
if (IS_EXTENDED_MODEL_INTEL (cpi->cpi_family))
|
||||
cpi->cpi_model += CPI_MODEL_XTD (regs.eax) << 4;
|
||||
break;
|
||||
case X86_VENDOR_AMD:
|
||||
if (CPI_FAMILY (cpi->cpi_family) == 0xf)
|
||||
cpi->cpi_model += CPI_MODEL_XTD (regs.eax) << 4;
|
||||
break;
|
||||
default:
|
||||
if (cpi->cpi_model == 0xf)
|
||||
cpi->cpi_model += CPI_MODEL_XTD (regs.eax) << 4;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return cpi;
|
||||
}
|
||||
|
||||
static inline uint_t
|
||||
cpuid_getvendor ()
|
||||
{
|
||||
return get_cpuid_info ()->cpi_vendor;
|
||||
}
|
||||
|
||||
static inline uint_t
|
||||
cpuid_getfamily ()
|
||||
{
|
||||
return get_cpuid_info ()->cpi_family;
|
||||
}
|
||||
|
||||
static inline uint_t
|
||||
cpuid_getmodel ()
|
||||
{
|
||||
return get_cpuid_info ()->cpi_model;
|
||||
}
|
58
gprofng/common/gp-defs.h
Normal file
58
gprofng/common/gp-defs.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (C) 2021 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 _GP_DEFS_H_
|
||||
#define _GP_DEFS_H_
|
||||
|
||||
/* Define the ARCH and WSIZE predicates */
|
||||
/*
|
||||
* The way we define and use predicates is similar to the
|
||||
* standard #assert with one important exception:
|
||||
* if an argument of a predicate is not known the result
|
||||
* is 'false' and we want a compile time error to avoid
|
||||
* silent results from typos like ARCH(INTEL), COMPILER(gnu),
|
||||
* etc.
|
||||
*/
|
||||
#define ARCH(x) TOK_A_##x(ARCH)
|
||||
#define TOK_A_Aarch64(x) x##_Aarch64
|
||||
#define TOK_A_SPARC(x) x##_SPARC
|
||||
#define TOK_A_Intel(x) x##_Intel
|
||||
|
||||
#define WSIZE(x) TOK_W_##x(WSIZE)
|
||||
#define TOK_W_32(x) x##_32
|
||||
#define TOK_W_64(x) x##_64
|
||||
|
||||
#if defined(sparc) || defined(__sparcv9)
|
||||
#define ARCH_SPARC 1
|
||||
#elif defined(__i386__) || defined(__x86_64)
|
||||
#define ARCH_Intel 1
|
||||
#elif defined(__aarch64__)
|
||||
#define ARCH_Aarch64 1
|
||||
#else
|
||||
#error "Undefined platform"
|
||||
#endif
|
||||
|
||||
#if defined(__sparcv9) || defined(__x86_64) || defined(__aarch64__)
|
||||
#define WSIZE_64 1
|
||||
#else
|
||||
#define WSIZE_32 1
|
||||
#endif
|
||||
|
||||
#endif
|
186
gprofng/common/gp-experiment.h
Normal file
186
gprofng/common/gp-experiment.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* Copyright (C) 2021 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 _EXPERIMENT_H
|
||||
#define _EXPERIMENT_H
|
||||
|
||||
/* version numbers define experiment format */
|
||||
#define SUNPERF_VERNUM 12
|
||||
#define SUNPERF_VERNUM_MINOR 4
|
||||
|
||||
/* backward compatibility down to: */
|
||||
#define SUNPERF_VERNUM_LEAST 12
|
||||
|
||||
#include "Emsgnum.h" /* for COL_ERROR_*, etc. symbols */
|
||||
|
||||
#define SP_REMOTE_PROTOCOL_VERSION "12.4.1"
|
||||
|
||||
#define SP_GROUP_HEADER "#analyzer experiment group"
|
||||
|
||||
/* Experiment name macro definitions */
|
||||
|
||||
/* for descendant experiments */
|
||||
#define DESCENDANT_EXPT_KEY ".er/_"
|
||||
#define IS_DESC_EXPT(exptname) (strstr(exptname,DESCENDANT_EXPT_KEY) != NULL)
|
||||
#define IS_FNDR_EXPT(exptname) (strstr(exptname,DESCENDANT_EXPT_KEY) == NULL)
|
||||
|
||||
/* File name definitions */
|
||||
#define SP_ARCHIVES_DIR "archives"
|
||||
#define SP_ARCHIVE_LOG_FILE "archive.log"
|
||||
#define SP_LOG_FILE "log.xml"
|
||||
#define SP_NOTES_FILE "notes"
|
||||
#define SP_IFREQ_FILE "ifreq"
|
||||
#define SP_MAP_FILE "map.xml"
|
||||
#define SP_LABELS_FILE "labels.xml"
|
||||
#define SP_DYNTEXT_FILE "dyntext"
|
||||
#define SP_OVERVIEW_FILE "overview"
|
||||
#define SP_PROFILE_FILE "profile"
|
||||
#define SP_SYNCTRACE_FILE "synctrace"
|
||||
#define SP_IOTRACE_FILE "iotrace"
|
||||
#define SP_OMPTRACE_FILE "omptrace"
|
||||
#define SP_MPVIEW_FILE "mpview.dat3"
|
||||
#define SP_HWCNTR_FILE "hwcounters"
|
||||
#define SP_HEAPTRACE_FILE "heaptrace"
|
||||
#define SP_JCLASSES_FILE "jclasses"
|
||||
#define SP_DYNAMIC_CLASSES "jdynclasses"
|
||||
#define SP_RACETRACE_FILE "dataraces"
|
||||
#define SP_DEADLOCK_FILE "deadlocks"
|
||||
#define SP_FRINFO_FILE "frameinfo"
|
||||
#define SP_WARN_FILE "warnings.xml"
|
||||
|
||||
#define SP_LIBCOLLECTOR_NAME "libgp-collector.so"
|
||||
#define SP_LIBAUDIT_NAME "libcollect-ng.so"
|
||||
|
||||
/* XML tags */
|
||||
#define SP_TAG_COLLECTOR "collector"
|
||||
#define SP_TAG_CPU "cpu"
|
||||
#define SP_TAG_DATAPTR "dataptr"
|
||||
#define SP_TAG_EVENT "event"
|
||||
#define SP_TAG_EXPERIMENT "experiment"
|
||||
#define SP_TAG_FIELD "field"
|
||||
#define SP_TAG_PROCESS "process"
|
||||
#define SP_TAG_PROFILE "profile"
|
||||
#define SP_TAG_PROFDATA "profdata"
|
||||
#define SP_TAG_PROFPCKT "profpckt"
|
||||
#define SP_TAG_SETTING "setting"
|
||||
#define SP_TAG_STATE "state"
|
||||
#define SP_TAG_SYSTEM "system"
|
||||
#define SP_TAG_POWERM "powerm"
|
||||
#define SP_TAG_FREQUENCY "frequency"
|
||||
#define SP_TAG_DTRACEFATAL "dtracefatal"
|
||||
|
||||
/* 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"
|
||||
#define SP_JCMD_RESUME "resume"
|
||||
#define SP_JCMD_RUN "run"
|
||||
#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"
|
||||
#define SP_MAP_UNRESOLVABLE "Unresolvable"
|
||||
|
||||
#define SP_UNKNOWN_NAME "(unknown)"
|
||||
|
||||
#define MAX_STACKDEPTH 2048
|
||||
#endif /* _EXPERIMENT_H */
|
46
gprofng/common/gp-time.h
Normal file
46
gprofng/common/gp-time.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Copyright (C) 2021 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 _GP_TIME_H_
|
||||
#define _GP_TIME_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef long long hrtime_t;
|
||||
typedef struct timespec timestruc_t;
|
||||
|
||||
#define ITIMER_REALPROF ITIMER_PROF
|
||||
#define NANOSEC 1000000000
|
||||
#define MICROSEC 1000000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
hrtime_t gethrtime (void);
|
||||
hrtime_t gethrvtime (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
198
gprofng/common/hwc_cpus.h
Normal file
198
gprofng/common/hwc_cpus.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Hardware counter profiling: cpu types */
|
||||
|
||||
#ifndef __HWC_CPUS_H
|
||||
#define __HWC_CPUS_H
|
||||
|
||||
#define MAX_PICS 20 /* Max # of HW ctrs that can be enabled simultaneously */
|
||||
|
||||
/* type for specifying CPU register number */
|
||||
typedef int regno_t;
|
||||
#define REGNO_ANY ((regno_t)-1)
|
||||
#define REGNO_INVALID ((regno_t)-2)
|
||||
|
||||
/* --- Utilities for use with regno_t and reg_list[] --- */
|
||||
#define REG_LIST_IS_EMPTY(reg_list) (!(reg_list) || (reg_list)[0] == REGNO_ANY)
|
||||
#define REG_LIST_EOL(regno) ((regno)==REGNO_ANY)
|
||||
#define REG_LIST_SINGLE_VALID_ENTRY(reg_list) \
|
||||
(((reg_list) && (reg_list)[1] == REGNO_ANY && \
|
||||
(reg_list)[0] != REGNO_ANY ) ? (reg_list)[0] : REGNO_ANY)
|
||||
|
||||
/* enum for specifying unknown or uninitialized CPU */
|
||||
enum
|
||||
{
|
||||
CPUVER_GENERIC = 0,
|
||||
CPUVER_UNDEFINED = -1
|
||||
};
|
||||
|
||||
// Note: changing an values below may make older HWC experiments unreadable.
|
||||
// --- Sun/Oracle SPARC ---
|
||||
#define CPC_ULTRA1 1000
|
||||
#define CPC_ULTRA2 1001
|
||||
#define CPC_ULTRA3 1002
|
||||
#define CPC_ULTRA3_PLUS 1003
|
||||
#define CPC_ULTRA3_I 1004
|
||||
#define CPC_ULTRA4_PLUS 1005 /* Panther */
|
||||
#define CPC_ULTRA4 1017 /* Jaguar */
|
||||
#define CPC_ULTRA_T1 1100 /* Niagara1 */
|
||||
#define CPC_ULTRA_T2 1101 /* Niagara2 */
|
||||
#define CPC_ULTRA_T2P 1102
|
||||
#define CPC_ULTRA_T3 1103
|
||||
#define CPC_SPARC_T4 1104
|
||||
#define CPC_SPARC_T5 1110
|
||||
#define CPC_SPARC_T6 1120
|
||||
// #define CPC_SPARC_T7 1130 // use CPC_SPARC_M7
|
||||
#define CPC_SPARC_M4 1204 /* Obsolete */
|
||||
#define CPC_SPARC_M5 1210
|
||||
#define CPC_SPARC_M6 1220
|
||||
#define CPC_SPARC_M7 1230
|
||||
#define CPC_SPARC_M8 1240
|
||||
|
||||
// --- Intel ---
|
||||
// Pentium
|
||||
#define CPC_PENTIUM 2000
|
||||
#define CPC_PENTIUM_MMX 2001
|
||||
#define CPC_PENTIUM_PRO 2002
|
||||
#define CPC_PENTIUM_PRO_MMX 2003
|
||||
#define CPC_PENTIUM_4 2017
|
||||
#define CPC_PENTIUM_4_HT 2027
|
||||
|
||||
// Core Microarchitecture (Merom/Menryn)
|
||||
#define CPC_INTEL_CORE2 2028
|
||||
#define CPC_INTEL_NEHALEM 2040
|
||||
#define CPC_INTEL_WESTMERE 2042
|
||||
#define CPC_INTEL_SANDYBRIDGE 2045
|
||||
#define CPC_INTEL_IVYBRIDGE 2047
|
||||
#define CPC_INTEL_ATOM 2050 /* Atom*/
|
||||
#define CPC_INTEL_HASWELL 2060
|
||||
#define CPC_INTEL_BROADWELL 2070
|
||||
#define CPC_INTEL_SKYLAKE 2080
|
||||
#define CPC_INTEL_UNKNOWN 2499
|
||||
#define CPC_AMD_K8C 2500 /* Opteron, Athlon... */
|
||||
#define CPC_AMD_FAM_10H 2501 /* Barcelona, Shanghai... */
|
||||
#define CPC_AMD_FAM_11H 2502 /* Griffin... */
|
||||
#define CPC_AMD_FAM_15H 2503
|
||||
#define CPC_KPROF 3003 // OBSOLETE (To support 12.3 and earlier)
|
||||
#define CPC_FOX 3004 /* pseudo-chip */
|
||||
|
||||
// --- Fujitsu ---
|
||||
#define CPC_SPARC64_III 3000
|
||||
#define CPC_SPARC64_V 3002
|
||||
#define CPC_SPARC64_VI 4003 /* OPL-C */
|
||||
#define CPC_SPARC64_VII 4004 /* Jupiter */
|
||||
#define CPC_SPARC64_X 4006 /* Athena */
|
||||
#define CPC_SPARC64_XII 4010 /* Athena++ */
|
||||
|
||||
// aarch64. Constants from arch/arm64/include/asm/cputype.h
|
||||
enum {
|
||||
ARM_CPU_IMP_ARM = 0x41,
|
||||
ARM_CPU_IMP_BRCM = 0x42,
|
||||
ARM_CPU_IMP_CAVIUM = 0x43,
|
||||
ARM_CPU_IMP_APM = 0x50,
|
||||
ARM_CPU_IMP_QCOM = 0x51
|
||||
};
|
||||
|
||||
#define AARCH64_VENDORSTR_ARM "ARM"
|
||||
|
||||
/* strings below must match those returned by cpc_getcpuver() */
|
||||
typedef struct
|
||||
{
|
||||
int cpc2_cpuver;
|
||||
const char * cpc2_cciname;
|
||||
} libcpc2_cpu_lookup_t;
|
||||
#define LIBCPC2_CPU_LOOKUP_LIST \
|
||||
{CPC_AMD_K8C , "AMD Opteron & Athlon64"}, \
|
||||
{CPC_AMD_FAM_10H , "AMD Family 10h"}, \
|
||||
{CPC_AMD_FAM_11H , "AMD Family 11h"}, \
|
||||
{CPC_AMD_FAM_15H , "AMD Family 15h Model 01h"}, \
|
||||
{CPC_AMD_FAM_15H , "AMD Family 15h Model 02h"},/*future*/ \
|
||||
{CPC_AMD_FAM_15H , "AMD Family 15h Model 03h"},/*future*/ \
|
||||
{CPC_PENTIUM_4_HT , "Pentium 4 with HyperThreading"}, \
|
||||
{CPC_PENTIUM_4 , "Pentium 4"}, \
|
||||
{CPC_PENTIUM_PRO_MMX , "Pentium Pro with MMX, Pentium II"}, \
|
||||
{CPC_PENTIUM_PRO , "Pentium Pro, Pentium II"}, \
|
||||
{CPC_PENTIUM_MMX , "Pentium with MMX"}, \
|
||||
{CPC_PENTIUM , "Pentium"}, \
|
||||
{CPC_INTEL_CORE2 , "Core Microarchitecture"}, \
|
||||
/* Merom: F6M15: Clovertown, Kentsfield, Conroe, Merom, Woodcrest */ \
|
||||
/* Merom: F6M22: Merom Conroe */ \
|
||||
/* Penryn: F6M23: Yorkfield, Wolfdale, Penryn, Harpertown */ \
|
||||
/* Penryn: F6M29: Dunnington */ \
|
||||
{CPC_INTEL_NEHALEM , "Intel Arch PerfMon v3 on Family 6 Model 26"},/*Bloomfield, Nehalem EP*/ \
|
||||
{CPC_INTEL_NEHALEM , "Intel Arch PerfMon v3 on Family 6 Model 30"},/*Clarksfield, Lynnfield, Jasper Forest*/ \
|
||||
{CPC_INTEL_NEHALEM , "Intel Arch PerfMon v3 on Family 6 Model 31"},/*(TBD)*/ \
|
||||
{CPC_INTEL_NEHALEM , "Intel Arch PerfMon v3 on Family 6 Model 46"},/*Nehalem EX*/ \
|
||||
{CPC_INTEL_WESTMERE , "Intel Arch PerfMon v3 on Family 6 Model 37"},/*Arrandale, Clarskdale*/ \
|
||||
{CPC_INTEL_WESTMERE , "Intel Arch PerfMon v3 on Family 6 Model 44"},/*Gulftown, Westmere EP*/ \
|
||||
{CPC_INTEL_WESTMERE , "Intel Arch PerfMon v3 on Family 6 Model 47"},/*Westmere EX*/ \
|
||||
{CPC_INTEL_SANDYBRIDGE , "Intel Arch PerfMon v3 on Family 6 Model 42"},/*Sandy Bridge*/ \
|
||||
{CPC_INTEL_SANDYBRIDGE , "Intel Arch PerfMon v3 on Family 6 Model 45"},/*Sandy Bridge E, SandyBridge-EN, SandyBridge EP*/ \
|
||||
{CPC_INTEL_IVYBRIDGE , "Intel Arch PerfMon v3 on Family 6 Model 58"},/*Ivy Bridge*/ \
|
||||
{CPC_INTEL_IVYBRIDGE , "Intel Arch PerfMon v3 on Family 6 Model 62"},/*(TBD)*/ \
|
||||
{CPC_INTEL_ATOM , "Intel Arch PerfMon v3 on Family 6 Model 28"},/*Atom*/ \
|
||||
{CPC_INTEL_HASWELL , "Intel Arch PerfMon v3 on Family 6 Model 60"},/*Haswell*/ \
|
||||
{CPC_INTEL_HASWELL , "Intel Arch PerfMon v3 on Family 6 Model 63"},/*Haswell*/ \
|
||||
{CPC_INTEL_HASWELL , "Intel Arch PerfMon v3 on Family 6 Model 69"},/*Haswell*/ \
|
||||
{CPC_INTEL_HASWELL , "Intel Arch PerfMon v3 on Family 6 Model 70"},/*Haswell*/ \
|
||||
{CPC_INTEL_BROADWELL , "Intel Arch PerfMon v3 on Family 6 Model 61"},/*Broadwell*/ \
|
||||
{CPC_INTEL_BROADWELL , "Intel Arch PerfMon v3 on Family 6 Model 71"},/*Broadwell*/ \
|
||||
{CPC_INTEL_BROADWELL , "Intel Arch PerfMon v3 on Family 6 Model 79"},/*Broadwell*/ \
|
||||
{CPC_INTEL_BROADWELL , "Intel Arch PerfMon v3 on Family 6 Model 86"},/*Broadwell*/ \
|
||||
{CPC_INTEL_SKYLAKE , "Intel Arch PerfMon v4 on Family 6 Model 78"},/*Skylake*/ \
|
||||
{CPC_INTEL_SKYLAKE , "Intel Arch PerfMon v4 on Family 6 Model 85"},/*Skylake*/ \
|
||||
{CPC_INTEL_SKYLAKE , "Intel Arch PerfMon v4 on Family 6 Model 94"},/*Skylake*/ \
|
||||
{CPC_INTEL_UNKNOWN , "Intel Arch PerfMon"},/*Not yet in table*/ \
|
||||
{CPC_SPARC64_III , "SPARC64 III"/*?*/}, \
|
||||
{CPC_SPARC64_V , "SPARC64 V"/*?*/}, \
|
||||
{CPC_SPARC64_VI , "SPARC64 VI"}, \
|
||||
{CPC_SPARC64_VII , "SPARC64 VI & VII"}, \
|
||||
{CPC_SPARC64_X , "SPARC64 X"}, \
|
||||
{CPC_SPARC64_XII , "SPARC64 XII"}, \
|
||||
{CPC_ULTRA_T1 , "UltraSPARC T1"}, \
|
||||
{CPC_ULTRA_T2 , "UltraSPARC T2"}, \
|
||||
{CPC_ULTRA_T2P , "UltraSPARC T2+"}, \
|
||||
{CPC_ULTRA_T3 , "SPARC T3"}, \
|
||||
{CPC_SPARC_T4 , "SPARC T4"}, \
|
||||
{CPC_SPARC_M4 , "SPARC M4"}, \
|
||||
{CPC_SPARC_T5 , "SPARC T5"}, \
|
||||
{CPC_SPARC_M5 , "SPARC M5"}, \
|
||||
{CPC_SPARC_T6 , "SPARC T6"}, \
|
||||
{CPC_SPARC_M6 , "SPARC M6"}, \
|
||||
{CPC_SPARC_M7 , "SPARC T7"}, \
|
||||
{CPC_SPARC_M7 , "SPARC 3e40"}, \
|
||||
{CPC_SPARC_M7 , "SPARC M7"}, \
|
||||
{CPC_SPARC_M8 , "SPARC 3e50"}, \
|
||||
{CPC_ULTRA4_PLUS , "UltraSPARC IV+"}, \
|
||||
{CPC_ULTRA4 , "UltraSPARC IV"}, \
|
||||
{CPC_ULTRA3_I , "UltraSPARC IIIi"}, \
|
||||
{CPC_ULTRA3_I , "UltraSPARC IIIi & IIIi+"}, \
|
||||
{CPC_ULTRA3_PLUS , "UltraSPARC III+"}, \
|
||||
{CPC_ULTRA3_PLUS , "UltraSPARC III+ & IV"}, \
|
||||
{CPC_ULTRA3 , "UltraSPARC III"}, \
|
||||
{CPC_ULTRA2 , "UltraSPARC I&II"}, \
|
||||
{CPC_ULTRA1 , "UltraSPARC I&II"}, \
|
||||
{ARM_CPU_IMP_APM , AARCH64_VENDORSTR_ARM}, \
|
||||
{0, NULL}
|
||||
/* init like this:
|
||||
static libcpc2_cpu_lookup_t cpu_table[]={LIBCPC2_CPU_LOOKUP_LIST};
|
||||
*/
|
||||
#endif
|
1454
gprofng/common/hwcdrv.c
Normal file
1454
gprofng/common/hwcdrv.c
Normal file
File diff suppressed because it is too large
Load diff
330
gprofng/common/hwcdrv.h
Normal file
330
gprofng/common/hwcdrv.h
Normal file
|
@ -0,0 +1,330 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Hardware counter profiling driver's header */
|
||||
|
||||
#ifndef __HWCDRV_H
|
||||
#define __HWCDRV_H
|
||||
|
||||
#include "hwcfuncs.h"
|
||||
|
||||
#ifdef linux
|
||||
#define HWCFUNCS_SIGNAL SIGIO
|
||||
#define HWCFUNCS_SIGNAL_STRING "SIGIO"
|
||||
#else
|
||||
#define HWCFUNCS_SIGNAL SIGEMT
|
||||
#define HWCFUNCS_SIGNAL_STRING "SIGEMT"
|
||||
#endif
|
||||
|
||||
#ifndef LIBCOLLECTOR_SRC /* not running in libcollector */
|
||||
#include <string.h>
|
||||
|
||||
#else /* running in libcollector */
|
||||
#include "collector_module.h"
|
||||
#include "libcol_util.h"
|
||||
|
||||
#define get_hwcdrv __collector_get_hwcdrv
|
||||
#define hwcdrv_drivers __collector_hwcdrv_drivers
|
||||
#define hwcdrv_cpc1_api __collector_hwcdrv_cpc1_api
|
||||
#define hwcdrv_cpc2_api __collector_hwcdrv_cpc2_api
|
||||
#define hwcdrv_default __collector_hwcdrv_default
|
||||
#define hwcdrv_driver __collector_hwcdrv_driver
|
||||
#define hwcdrv_init __collector_hwcdrv_init
|
||||
#define hwcdrv_get_info __collector_hwcdrv_get_info
|
||||
#define hwcdrv_enable_mt __collector_hwcdrv_enable_mt
|
||||
#define hwcdrv_get_descriptions __collector_hwcdrv_get_descriptions
|
||||
#define hwcdrv_assign_regnos __collector_hwcdrv_assign_regnos
|
||||
#define hwcdrv_create_counters __collector_hwcdrv_create_counters
|
||||
#define hwcdrv_start __collector_hwcdrv_start
|
||||
#define hwcdrv_overflow __collector_hwcdrv_overflow
|
||||
#define hwcdrv_read_events __collector_hwcdrv_read_events
|
||||
#define hwcdrv_sighlr_restart __collector_hwcdrv_sighlr_restart
|
||||
#define hwcdrv_lwp_suspend __collector_hwcdrv_lwp_suspend
|
||||
#define hwcdrv_lwp_resume __collector_hwcdrv_lwp_resume
|
||||
#define hwcdrv_free_counters __collector_hwcdrv_free_counters
|
||||
#define hwcdrv_lwp_init __collector_hwcdrv_lwp_init
|
||||
#define hwcdrv_lwp_fini __collector_hwcdrv_lwp_fini
|
||||
#define hwcdrv_assign_all_regnos __collector_hwcdrv_assign_all_regnos
|
||||
#define hwcdrv_lookup_cpuver __collector_hwcdrv_lookup_cpuver
|
||||
#define hwcfuncs_int_capture_errmsg __collector_hwcfuncs_int_capture_errmsg
|
||||
|
||||
#define GTXT(x) x
|
||||
|
||||
/* Implemented by libcollector */
|
||||
#define calloc __collector_calloc
|
||||
#define close CALL_UTIL(close)
|
||||
#define fcntl CALL_UTIL(fcntl)
|
||||
#define fprintf CALL_UTIL(fprintf)
|
||||
//#define free __collector_free
|
||||
#define free(...)
|
||||
#define gethrtime __collector_gethrtime
|
||||
#define ioctl CALL_UTIL(ioctl)
|
||||
#define malloc __collector_malloc
|
||||
#define memcpy __collector_memcpy
|
||||
#define memset CALL_UTIL(memset)
|
||||
#define mmap CALL_UTIL(mmap)
|
||||
#define snprintf CALL_UTIL(snprintf)
|
||||
#define strchr CALL_UTIL(strchr)
|
||||
#define strcmp CALL_UTIL(strcmp)
|
||||
#define strncmp CALL_UTIL(strncmp)
|
||||
#define strcpy CALL_UTIL(strcpy)
|
||||
#define strdup __collector_strdup
|
||||
#define strncpy CALL_UTIL(strncpy)
|
||||
#define strerror CALL_UTIL(strerror)
|
||||
#define strlen CALL_UTIL(strlen)
|
||||
#define strstr CALL_UTIL(strstr)
|
||||
#define strtol CALL_UTIL(strtol)
|
||||
#define strtoll CALL_UTIL(strtoll)
|
||||
#define strtoul CALL_UTIL(strtoul)
|
||||
#define strtoull CALL_UTIL(strtoull)
|
||||
#define syscall CALL_UTIL(syscall)
|
||||
#define sysconf CALL_UTIL(sysconf)
|
||||
#define vsnprintf CALL_UTIL(vsnprintf)
|
||||
|
||||
#endif /* --- LIBCOLLECTOR_SRC --- */
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
#define DBG_LT4 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* hwcdrv api */
|
||||
typedef struct
|
||||
{
|
||||
int (*hwcdrv_init)(hwcfuncs_abort_fn_t abort_ftn, int * tsd_sz);
|
||||
/* Initialize hwc counter library (do not call again after fork)
|
||||
Must be called before other functions.
|
||||
Input:
|
||||
<abort_ftn>: NULL or callback function to be used for fatal errors
|
||||
<tsd_sz>: If not NULL, returns size in bytes required for thread-specific storage
|
||||
Return: 0 if successful
|
||||
*/
|
||||
|
||||
void (*hwcdrv_get_info)(int *cpuver, const char **cciname, uint_t *npics,
|
||||
const char **docref, uint64_t *support);
|
||||
/* get info about session
|
||||
Input:
|
||||
<cpuver>: if not NULL, returns value of CPC cpu version
|
||||
<cciname>: if not NULL, returns name of CPU
|
||||
<npics>: if not NULL, returns maximum # of HWCs
|
||||
<docref>: if not NULL, returns documentation reference
|
||||
<support>: if not NULL, returns bitmask (see hwcfuncs.h) of hwc support
|
||||
Return: 0 if successful, nonzero otherwise
|
||||
*/
|
||||
|
||||
int (*hwcdrv_enable_mt)(hwcfuncs_tsd_get_fn_t tsd_ftn);
|
||||
/* Enables multi-threaded mode (do not need to call again after fork)
|
||||
Input:
|
||||
<tsd_ftn>: If <tsd_sz>==0, this parameter is ignored.
|
||||
Otherwise:
|
||||
tsd_ftn() must be able to return a pointer to thread-specific
|
||||
memory of <tsd_sz> bytes.
|
||||
For a given thread, tsd_ftn() must
|
||||
always return the same pointer.
|
||||
Return: none
|
||||
*/
|
||||
|
||||
int (*hwcdrv_get_descriptions)(hwcf_hwc_cb_t *hwc_find_action,
|
||||
hwcf_attr_cb_t *attr_find_action);
|
||||
/* Initiate callbacks with all available HWC names and and HWC attributes.
|
||||
Input:
|
||||
<hwc_find_action>: if not NULL, will be called once for each HWC
|
||||
<attr_find_action>: if not NULL, will be called once for each attribute
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error
|
||||
*/
|
||||
|
||||
int (*hwcdrv_assign_regnos)(Hwcentry* entries[], unsigned numctrs);
|
||||
/* Assign entries[]->reg_num values as needed by platform
|
||||
Input:
|
||||
<entries>: array of counters
|
||||
<numctrs>: number of items in <entries>
|
||||
Return: 0 if successful
|
||||
HWCFUNCS_ERROR_HWCINIT if resources unavailable
|
||||
HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
|
||||
*/
|
||||
|
||||
int (*hwcdrv_create_counters)(unsigned hwcdef_cnt, Hwcentry *hwcdef);
|
||||
/* Create the counters, but don't start them.
|
||||
call this once in main thread to create counters.
|
||||
Input:
|
||||
<defcnt>: number of counter definitions.
|
||||
<hwcdef>: counter definitions.
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error
|
||||
*/
|
||||
|
||||
int (*hwcdrv_start)(void);
|
||||
/* Start the counters.
|
||||
call this once in main thread to start counters.
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error
|
||||
*/
|
||||
|
||||
int (*hwcdrv_overflow)(siginfo_t *si, hwc_event_t *sample,
|
||||
hwc_event_t *lost_samples);
|
||||
/* Linux only. Capture current counter values.
|
||||
This is intended to be called from SIGEMT handler;
|
||||
Input:
|
||||
<si>: signal handler context information
|
||||
<sample>: returns non-zero values for counters that overflowed
|
||||
<lost_samples>: returns non-zero values for counters that "lost" counts
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error.
|
||||
*/
|
||||
|
||||
int (*hwcdrv_read_events)(hwc_event_t *overflow_data,
|
||||
hwc_event_samples_t *sampled_data);
|
||||
/* Read current counter values and samples. Read of samples is destructive.
|
||||
Note: hwcdrv_read_events is not supported on Linux.
|
||||
<overflow_data>: returns snapshot of counter values
|
||||
<sampled_data>: returns sampled data
|
||||
Return: 0 if successful
|
||||
HWCFUNCS_ERROR_UNAVAIL if resource unavailable(e.g. called before initted)
|
||||
(other values may be possible)
|
||||
*/
|
||||
|
||||
int (*hwcdrv_sighlr_restart)(const hwc_event_t* startVals);
|
||||
/* Restarts the counters at the given value.
|
||||
This is intended to be called from SIGEMT handler;
|
||||
Input:
|
||||
<startVals>: Solaris: new start values.
|
||||
Linux: pointer may be NULL; startVals is ignored.
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error.
|
||||
*/
|
||||
|
||||
int (*hwcdrv_lwp_suspend)(void);
|
||||
/* Attempt to stop counters on this lwp only.
|
||||
hwcdrv_lwp_resume() should be used to restart counters.
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error.
|
||||
*/
|
||||
|
||||
int (*hwcdrv_lwp_resume)(void);
|
||||
/* Attempt to restart counters on this lwp when counters were
|
||||
stopped with hwcdrv_lwp_suspend().
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error.
|
||||
*/
|
||||
|
||||
int (*hwcdrv_free_counters)(void);
|
||||
/* Stops counters on this lwp only and frees resources.
|
||||
This will fail w/ unpredictable results if other lwps's are
|
||||
still running. After this call returns,
|
||||
hwcdrv_create_counters() may be called with new values.
|
||||
Return: 0 if successful
|
||||
or a cpc return code upon error.
|
||||
*/
|
||||
|
||||
int (*hwcdrv_lwp_init)(void);
|
||||
/* per-thread counter init.
|
||||
Solaris: nop.
|
||||
Linux: just after thread creation call this from inside thread
|
||||
to create context and start counters.
|
||||
Return: 0 if successful
|
||||
or a perfctr return code upon error
|
||||
*/
|
||||
|
||||
void (*hwcdrv_lwp_fini)(void);
|
||||
/* per-thread counter cleanup.
|
||||
Solaris: nop.
|
||||
Linux: call in each thread upon thread destruction.
|
||||
*/
|
||||
|
||||
int hwcdrv_init_status;
|
||||
} hwcdrv_api_t;
|
||||
|
||||
extern hwcdrv_api_t *get_hwcdrv ();
|
||||
extern hwcdrv_api_t *__collector_get_hwcdrv ();
|
||||
extern int __collector_hwcfuncs_bind_descriptor (const char *defstring);
|
||||
extern Hwcentry **__collector_hwcfuncs_get_ctrs (unsigned *defcnt);
|
||||
extern hwcdrv_api_t *hwcdrv_drivers[]; // array of available drivers
|
||||
|
||||
/* prototypes for internal use by hwcdrv drivers */
|
||||
typedef struct
|
||||
{ // see hwcdrv_get_info() for field definitions
|
||||
int cpcN_cpuver;
|
||||
uint_t cpcN_npics;
|
||||
const char *cpcN_docref;
|
||||
const char *cpcN_cciname;
|
||||
} hwcdrv_about_t;
|
||||
|
||||
extern int hwcdrv_assign_all_regnos (Hwcentry* entries[], unsigned numctrs);
|
||||
/* assign user's counters to specific CPU registers */
|
||||
|
||||
extern int hwcdrv_lookup_cpuver (const char * cpcN_cciname);
|
||||
/* returns hwc_cpus.h ID for a given string. */
|
||||
|
||||
extern void hwcfuncs_int_capture_errmsg (const char *fn, int subcode,
|
||||
const char *fmt, va_list ap);
|
||||
#define logerr hwcfuncs_int_logerr
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* prototypes for internal use by linux hwcdrv drivers */
|
||||
#define PERFCTR_FIXED_MAGIC 0x40000000 /* tells perfctr to use intel fixed pmcs */
|
||||
#define PERFCTR_UMASK_SHIFT 8
|
||||
#define EXTENDED_EVNUM_2_EVSEL(evnum) \
|
||||
( (((eventsel_t)(evnum) & 0x0f00ULL) << 24) | ((eventsel_t)(evnum) & ~0x0f00ULL) )
|
||||
|
||||
typedef uint64_t eventsel_t;
|
||||
extern int hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name,
|
||||
eventsel_t *return_event, uint_t *return_pmc_sel);
|
||||
|
||||
typedef int (hwcdrv_get_events_fn_t) (hwcf_hwc_cb_t *hwc_cb);
|
||||
typedef int (hwcdrv_get_eventnum_fn_t) (const char *eventname, uint_t pmc,
|
||||
eventsel_t *eventnum,
|
||||
eventsel_t *valid_umask, uint_t *pmc_sel);
|
||||
extern hwcdrv_get_eventnum_fn_t *hwcdrv_get_x86_eventnum;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char * attrname; // user-visible name of attribute
|
||||
int is_inverted; // nonzero means boolean attribute is inverted
|
||||
eventsel_t mask; // which attribute bits can be set?
|
||||
eventsel_t shift; // how far to shift bits for use in x86 register
|
||||
} attr_info_t;
|
||||
extern const attr_info_t *perfctr_attrs_table;
|
||||
|
||||
/* hdrv_pcbe api: cpu-specific drivers for Linux */
|
||||
typedef struct
|
||||
{
|
||||
int (*hdrv_pcbe_init)(void);
|
||||
uint_t (*hdrv_pcbe_ncounters)(void);
|
||||
const char *(*hdrv_pcbe_impl_name)(void);
|
||||
const char *(*hdrv_pcbe_cpuref)(void);
|
||||
int (*hdrv_pcbe_get_events)(hwcf_hwc_cb_t *hwc_cb);
|
||||
int (*hdrv_pcbe_get_eventnum)(const char * eventname, uint_t pmc,
|
||||
eventsel_t *eventnum, eventsel_t *valid_umask,
|
||||
uint_t *pmc_sel);
|
||||
} hdrv_pcbe_api_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
417
gprofng/common/hwcentry.h
Normal file
417
gprofng/common/hwcentry.h
Normal file
|
@ -0,0 +1,417 @@
|
|||
/* Copyright (C) 2021 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 _HWCENTRY_H
|
||||
#define _HWCENTRY_H
|
||||
|
||||
#ifndef LIBCOLLECTOR_SRC /* not running in libcollector */
|
||||
#include <stdio.h> /* FILE */
|
||||
#endif /* --- LIBCOLLECTOR_SRC --- */
|
||||
#include <stdlib.h> /* size_t */
|
||||
#include "hwc_cpus.h"
|
||||
#include "gp-time.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* ABS backtrack types */
|
||||
typedef enum
|
||||
{
|
||||
/* !! Lowest 2 bits are used to indicate load and store, respectively !! */
|
||||
/* Example: On SPARC, backtrack.c did this: if (ABS_memop & inst_type) ... */
|
||||
ABST_NONE = 0x0,
|
||||
ABST_LOAD = 0x1,
|
||||
ABST_STORE = 0x2,
|
||||
ABST_LDST = 0x3,
|
||||
ABST_COUNT = 0x4,
|
||||
ABST_US_DTLBM = 0xF,
|
||||
ABST_NOPC = 0x100,
|
||||
ABST_CLKDS = 0x103, // Obsolete
|
||||
ABST_EXACT = 0x203,
|
||||
ABST_LDST_SPARC64 = 0x303,
|
||||
ABST_EXACT_PEBS_PLUS1 = 0x403
|
||||
/* full description below... */
|
||||
} ABST_type;
|
||||
|
||||
#define ABST_PLUS_BY_DEFAULT(n) ((n)==ABST_EXACT || (n)==ABST_EXACT_PEBS_PLUS1)
|
||||
#define ABST_BACKTRACK_ENABLED(n) ((n)!=ABST_NONE && (n)!=ABST_NOPC)
|
||||
#define ABST_MEMSPACE_ENABLED(n) ((n)!=ABST_NONE && (n)!=ABST_NOPC && (n)!=ABST_COUNT)
|
||||
|
||||
/* ABS determines the type of backtracking available for a particular metric.
|
||||
* Backtracking is enabled with the "+" in "-h +<countername>...".
|
||||
*
|
||||
* When Backtracking is not possible:
|
||||
*
|
||||
* ABST_NONE=0: Either the user did not specify "+", or backtracking
|
||||
* is not applicable to the metric, for example:
|
||||
* clk cycles,
|
||||
* instruct counts (dispatch + branch + prefetch),
|
||||
* i$,
|
||||
* FP ops
|
||||
* ABST_NOPC=0x100 Used for non-program-related external events, for example:
|
||||
* system interface events,
|
||||
* memory controller counters
|
||||
* Of all ABST_type options, only ABST_NOPC prevents hwprofile.c
|
||||
* from recording PC/stack information.
|
||||
*
|
||||
* When backtracking is allowed:
|
||||
*
|
||||
* ABST_LOAD=1: data read events, used with metrics like:
|
||||
* D$, E$, P$ read misses and hits.
|
||||
* [DC+EC+PC]_rd*, Re_*_miss*,
|
||||
* EC_snoop_cb(?)
|
||||
* ABST_STORE=2: data write events, used with metrics like:
|
||||
* D$ writes and write related misses
|
||||
* DC_wr/wr-miss, EC_wb, WC=writecache, Rstall_storeQ
|
||||
* [EC+PC=pcache]_snoop_inv(?), WC_snoop_cb(?),
|
||||
* ABST_LDST=3: data reads/writes, used with metrics like:
|
||||
* E$ references, misses.
|
||||
* ABST_COUNT=4: dedicated assembly instruction: '%hi(0xfc000)'
|
||||
* See SW_count_n metric on sparc.
|
||||
* ABST_US_DTLBM=0xF: for load-store on Sparc -- seems to be used only
|
||||
* for "unskidded DTLB_miss" with DTLB_miss metric.
|
||||
* Checks two adjacent instructions for Data access.
|
||||
* ABST_CLKDS=0x103: data reads/writes, used with Clock-based Dataspace
|
||||
* profiling. Ultrasparc T2 and earlier.
|
||||
* ABST_EXACT=0x203: data reads/writes, precise trap with no skid
|
||||
* ABST_LDST_SPARC64=0x303: Fujitsu SPARC64 load/store
|
||||
* ABST_EXACT_PEBS_PLUS1=0x403: data reads/writes, precise sampling with 1 instr. skid
|
||||
*/
|
||||
|
||||
/* Hwcentry - structure for defining a counter.
|
||||
* Some fields have different usage when returned from
|
||||
* hwc_lookup(), hwc_post_lookup(), or hwc_scan_*().
|
||||
* Each function will describe its return values in more detail.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *name; /* user HWC specification */
|
||||
char *int_name; /* internal HWC specification */
|
||||
regno_t reg_num; /* register in CPU, aka picnum, or REGNO_ANY */
|
||||
char *metric; /* descriptive name, for well-known counters only */
|
||||
volatile int val; /* default or actual overflow value */
|
||||
int timecvt; /* multiplier to convert metric to time, 0 if N/A */
|
||||
ABST_type memop; /* type of backtracking allowed */
|
||||
char *short_desc; /* optional one-liner description, or NULL */
|
||||
int type; /* Type of perf_event_attr */
|
||||
long long config; /* perf_event_type -specific configuration */
|
||||
/* the fields above this line are expected, in order, by the tables in hwctable.c */
|
||||
/* ================================================== */
|
||||
/* the fields below this line are more flexible */
|
||||
int sort_order; /* "tag" to associate experiment record with HWC def */
|
||||
regno_t *reg_list; /* if not NULL, legal values for <reg_num> field above */
|
||||
/* Note: reg_list will be terminated by REGNO_ANY */
|
||||
/* Max size of array is MAX_PICS */
|
||||
hrtime_t min_time; /* target minimum time between overflow events. 0 is off. See HWCTIME_* macros */
|
||||
hrtime_t min_time_default; /* if min_time==HWCTIME_AUTO, use this value instead. 0 is off. */
|
||||
int ref_val; /* if min_time==HWCTIME_AUTO, use this time. 0 is off. */
|
||||
int lval, hval; /* temporary to allow DBX to build until dbx glue.cc fixed */
|
||||
} Hwcentry;
|
||||
|
||||
// Hwcentry.min_time canned values
|
||||
#define HWCTIME_TBD ((hrtime_t)( -1LL)) /* self-adjusting enabled but nsecs not yet selected */
|
||||
#define HWCTIME_HI ( 1 * 1000 * 1000LL ) /* 1 msec represented in nsecs */
|
||||
#define HWCTIME_ON ( 10 * 1000 * 1000LL ) /* 10 msec represented in nsecs */
|
||||
#define HWCTIME_LO ( 100 * 1000 * 1000LL ) /* 100 msec represented in nsecs */
|
||||
|
||||
#define HWC_VAL_HI(refVal) (((refVal)/10) + 1)
|
||||
#define HWC_VAL_ON(refVal) (refVal)
|
||||
#define HWC_VAL_LO(refVal) (((refVal)*10)/100*100 + 1) // zero's out lower digits, add 1
|
||||
#define HWC_VAL_CUSTOM(refVal, targetNanoSec) ((double)(refVal)*(targetNanoSec)/HWCTIME_ON)
|
||||
|
||||
#define HWCENTRY_USES_SAMPLING(h) ((h)->memop==ABST_EXACT_PEBS_PLUS1)
|
||||
|
||||
extern int hwc_lookup (int forKernel, hrtime_t min_time_default,
|
||||
const char *uname, Hwcentry *list[], unsigned listsz,
|
||||
char **emsg, char **wmsg);
|
||||
/* Parses counter cmdline string. Returns counter definitions.
|
||||
* Input:
|
||||
* <forKernel> lookup using which table: 0-collect or 1-er_kernel
|
||||
* <min_time_default> minimum nseconds between events if Hwcentry.min_time == HWCTIME_TBD. 0 to disable.
|
||||
* <uname> command line HWC definition of format:
|
||||
* <ctr_def>...[{','|(whitespace)}<ctr_n_def>] where
|
||||
* <ctr_def> == [+]<ctr>[/<reg#>][,<interval>]
|
||||
* <list> array of pointers to store counter definitions
|
||||
* <listsz> number of elements in <list>
|
||||
* Returns:
|
||||
* Success:
|
||||
* Returns number of valid counters in <list> and <list>'s elements
|
||||
* will be initialized as follows:
|
||||
*
|
||||
* <list[]->name>:
|
||||
* Copy of the <uname> with the following modification:
|
||||
* if backtracking is not supported, the + will be removed.
|
||||
* <list[]->int_name>:
|
||||
* For well-known and convenience ctrs, the internal HWC specification,
|
||||
* e.g. BSQ_cache_reference~emask=0x0100.
|
||||
* For raw ctrs, this will be a copy of <name>.
|
||||
* <list[]->reg_num>:
|
||||
* Register number if specified by user or table, REGNO_ANY otherwise.
|
||||
* <list[]->metric>:
|
||||
* For well-known counters, descriptive name, e.g. "D$ Read Misses".
|
||||
* NULL otherwise.
|
||||
* <list[]->val>:
|
||||
* Overflow value selected by user, default value otherwise.
|
||||
* <list[]->timecvt>:
|
||||
* Value from tables.
|
||||
* <list[]->memop>:
|
||||
* If + is selected and backtracking is allowed, value from table.
|
||||
* ABST_NONE or ABST_NOPC otherwise.
|
||||
*
|
||||
* It is the responsibility of the caller to free 'name' and 'int_name'.
|
||||
* 'metric' is a static string and shouldn't be freed.
|
||||
* 'emsg' will point to NULL
|
||||
*
|
||||
* Failure:
|
||||
* Frees all allocated elements.
|
||||
* emsg will point to a string with an error message to print
|
||||
* returns -1
|
||||
*/
|
||||
|
||||
extern char *hwc_validate_ctrs (int forKernel, Hwcentry *list[], unsigned listsz);
|
||||
/* Validates that the vector of specified HW counters can be loaded (more-or-less)
|
||||
* Some invalid combinations, especially on Linux will not be detected
|
||||
*/
|
||||
|
||||
extern int hwc_get_cpc_cpuver ();
|
||||
/* Return the cpc_cpuver for this system. Other possible values:
|
||||
* CPUVER_GENERIC=0, CPU could not be determined, but HWCs are ok.
|
||||
* CPUVER_UNDEFINED=-1, HWCs are not available.
|
||||
*/
|
||||
|
||||
extern char *hwc_get_docref (char *buf, size_t buflen);
|
||||
/* Return a CPU HWC document reference, or NULL. */
|
||||
|
||||
// TBR
|
||||
extern char *hwc_get_default_cntrs ();
|
||||
/* Return a default HW counter string; may be NULL, or zero-length */
|
||||
/* NULL means none is defined in the table; or zero-length means string defined could not be loaded */
|
||||
|
||||
extern char *hwc_get_default_cntrs2 (int forKernel, int style);
|
||||
/* like hwc_get_default_cntrs() for style==1 */
|
||||
/* but allows other styles of formatting as well */
|
||||
/* deprecate and eventually remove hwc_get_default_cntrs() */
|
||||
|
||||
extern char *hwc_get_orig_default_cntrs ();
|
||||
/* Get the default HW counter string as set in the table */
|
||||
/* NULL means none is defined in the table */
|
||||
|
||||
extern void hwc_update_val (Hwcentry *ctr);
|
||||
/* Check time-based intervals and update Hwcentry.val as needed */
|
||||
|
||||
extern char *hwc_get_cpuname (char *buf, size_t buflen);
|
||||
/* Return the cpc cpu name for this system, or NULL. */
|
||||
|
||||
extern unsigned hwc_get_max_regs ();
|
||||
/* Return number of counters registers for this system. */
|
||||
|
||||
extern unsigned hwc_get_max_concurrent (int forKernel);
|
||||
/* Return the max number of simultaneous counters for this system. */
|
||||
|
||||
extern char **hwc_get_attrs (int forKernel);
|
||||
/* Return:
|
||||
* Array of attributes (strings) supported by this system.
|
||||
* Last element in array is null.
|
||||
* Array and its elements should NOT be freed by the caller.
|
||||
*/
|
||||
|
||||
extern unsigned hwc_scan_attrs (void (*action)(const char *attr,
|
||||
const char *desc));
|
||||
/* Scan the HW counter attributes, and call function for each attribute.
|
||||
* Input:
|
||||
* <action>:
|
||||
* If NULL, no action is performed, but count is still returned.
|
||||
* Otherwise called for each type of attributes, or if none exist,
|
||||
* called once with NULL parameter.
|
||||
* Return: count of times <action> would have been called w/ non-NULL data.
|
||||
*/
|
||||
|
||||
extern Hwcentry *hwc_post_lookup (Hwcentry * pret_ctr, char *uname,
|
||||
char * int_name, int cpc_cpuver);
|
||||
/* When post-processing a run, look up a Hwcentry for given type of system.
|
||||
* Input:
|
||||
* <pret_ctr>: storage for counter definition
|
||||
* <uname>: well-known name, convenience name, or complete HWC defintion.
|
||||
* <int_name>: Hwcentry->int_name or NULL for don't care
|
||||
* <cpc_cpuver>: version of cpu used for experiment.
|
||||
* Return:
|
||||
* <pret_ctr>'s elements set as follows:
|
||||
*
|
||||
* <pret_ctr->name>:
|
||||
* Copy of <uname> with the following modifications:
|
||||
* 1) + and /<regnum> will be stripped off
|
||||
* 2) attributes will be sorted and values will shown in hex.
|
||||
* <pret_ctr->int_name>:
|
||||
* For well-known/convenience counters, the internal HWC specification
|
||||
* from the table, e.g. BSQ_cache_reference~emask=0x0100.
|
||||
* Otherwise, a copy of <uname>.
|
||||
* <pret_ctr->reg_num>:
|
||||
* Register number if specified by user or table,
|
||||
* REGNO_ANY othewise.
|
||||
* <pret_ctr->metric>:
|
||||
* For well-known counters, descriptive name, e.g. "D$ Read Misses".
|
||||
* NULL otherwise.
|
||||
* <pret_ctr->timecvt>:
|
||||
* For well-known/convenience/hidden counters, value from table.
|
||||
* 0 otherwise.
|
||||
* <pret_ctr->memop>:
|
||||
* For well-known/convenience/hidden counters, value from table.
|
||||
* ABST_NONE otherwise.
|
||||
* <pret_ctr->sort_order>:
|
||||
* Set to 0.
|
||||
*
|
||||
* It is the responsibility of the caller to free 'name' and 'int_name'.
|
||||
* 'metric' is a static string and shouldn't be freed.
|
||||
*/
|
||||
|
||||
extern Hwcentry **hwc_get_std_ctrs (int forKernel);
|
||||
/* Return:
|
||||
* Array of well-known counters supported by this system.
|
||||
* Last element in array will be NULL.
|
||||
* Array and its elements should NOT be freed by the caller.
|
||||
*/
|
||||
|
||||
extern unsigned hwc_scan_std_ctrs (void (*action)(const Hwcentry *));
|
||||
/* Call <action> for each well-known counter.
|
||||
* Input:
|
||||
* <action>:
|
||||
* If NULL, no action is performed, but count is still returned.
|
||||
* Otherwise called for each type of attributes, or if none exist,
|
||||
* called once with NULL parameter.
|
||||
* Return:
|
||||
* Count of times <action> would have been called w/ non-NULL data.
|
||||
* If <action> is not NULL, Hwcentry fields will be set as follows:
|
||||
* <ctr->name>:
|
||||
* HWC alias name, e.g. dcrm.
|
||||
* <ctr->int_name>:
|
||||
* The internal HWC specification, e.g. BSQ_cache_reference~emask=0x0100.
|
||||
* <ctr->reg_num>:
|
||||
* Register number if specified by the table, REGNO_ANY otherwise.
|
||||
* <ctr->metric>:
|
||||
* Descriptive name, e.g. "D$ Read Misses".
|
||||
* <ctr->lval>:
|
||||
* Low-resolution overflow value.
|
||||
* <ctr->val>:
|
||||
* Default overflow value.
|
||||
* <ctr->hval>:
|
||||
* High-resolution overflow value.
|
||||
* <ctr->timecvt>:
|
||||
* multiplier to convert metric to time, 0 otherwise.
|
||||
* <ctr->memop>:
|
||||
* ABST_* type for this counter.
|
||||
* <ctr->reg_list>:
|
||||
* Array of legal <reg_num> values. Terminated by REGNO_ANY.
|
||||
*
|
||||
* Note: All fields point to static data, none should be freed.
|
||||
*/
|
||||
|
||||
extern Hwcentry **hwc_get_raw_ctrs (int forKernel);
|
||||
/* Return:
|
||||
* Table of raw (not well-known) counters supported by this system.
|
||||
* Last element in array will be NULL.
|
||||
* Table and its elements should NOT be freed by the caller.
|
||||
*/
|
||||
|
||||
extern unsigned hwc_scan_raw_ctrs (void (*action)(const Hwcentry *));
|
||||
/* Call <action> for each raw counter.
|
||||
* Input:
|
||||
* <action>:
|
||||
* If NULL, no action is performed, but count is still returned.
|
||||
* Otherwise called for each type of attributes, or if none exist,
|
||||
* called once with NULL parameter.
|
||||
* Return:
|
||||
* Count of times <action> would have been called w/ non-NULL data.
|
||||
* If <action> is not NULL, Hwcentry fields will be set as follows:
|
||||
* <ctr->name>:
|
||||
* HWC raw name without attributes, e.g. BSQ_cache_reference.
|
||||
* <ctr->int_name>:
|
||||
* NULL.
|
||||
* <ctr->metric>:
|
||||
* NULL.
|
||||
* The remainder of the fields are the same as for
|
||||
* hwc_scan_std_ctrs().
|
||||
*
|
||||
* Note: All fields point to static data, none should be freed.
|
||||
*/
|
||||
|
||||
extern void
|
||||
hwc_usage (int forKernel, const char *cmd, const char *dataspace_msg);
|
||||
/* Print an i18n'd description of "-h" usage, used by collect and er_kernel.
|
||||
*/
|
||||
|
||||
extern void hwc_usage_f (int forKernel, FILE *f, const char *cmd,
|
||||
const char *dataspace_msg, int show_syntax,
|
||||
int show_short_desc);
|
||||
/* Print an i18n'd description of "-h" usage to a FILE. Used by GUI. */
|
||||
|
||||
extern char *hwc_rate_string (const Hwcentry *pctr, int force_numeric_format);
|
||||
/* Returns {"on"|"hi"|"lo"|""|<value>}. Return value must be freed by caller. */
|
||||
|
||||
extern char *hwc_i18n_metric (const Hwcentry *ctr);
|
||||
/* Get a basic lable for a counter, properly i18n'd.
|
||||
* Note: NOT MT SAFE.
|
||||
* Examples:
|
||||
* CPU Cycles
|
||||
* DC_rd Events
|
||||
* Pseudocode:
|
||||
* if(ctr->metric != NULL) {
|
||||
* sprintf(metricbuf, PTXT(ctr->metric) );
|
||||
* } else if (ctr->name != NULL) {
|
||||
* sprintf(metricbuf, GTXT("%s Events"), ctr->name );
|
||||
* } else if (ctr->int_name != NULL) {
|
||||
* sprintf(metricbuf, GTXT("%s Events"), ctr->int_name );
|
||||
* }
|
||||
* Return: pointer to a buffer containing the above description.
|
||||
*/
|
||||
|
||||
extern char *hwc_hwcentry_string (char *buf, size_t buflen, const Hwcentry *ctr);
|
||||
/* Get a i18n'd description of a HW counter's options.
|
||||
* Examples of well-known counters:
|
||||
* cycles[/{0|1}],9999991 ('CPU Cycles', alias for Cycle_cnt; CPU-cycles)
|
||||
* dcr[/0],1000003 ('D$ Read Refs', alias for DC_rd; load events)
|
||||
* Examples of raw counters:
|
||||
* Cycle_cnt[/{0|1}],1000003 (CPU-cycles)
|
||||
* DC_rd[/0],1000003 (load events)
|
||||
* Return: <buf>, filled in.
|
||||
*/
|
||||
|
||||
extern char *hwc_hwcentry_specd_string (char *buf, size_t buflen, const Hwcentry *ctr);
|
||||
/* Get a i18n'd description of a HW counter's specific configuration.
|
||||
* Examples of well-known counters:
|
||||
* cycles,9999991 ('CPU Cycles')
|
||||
* +dcr/0,1000003 ('D$ Read Refs')
|
||||
* Examples of raw counters:
|
||||
* Cycle_cnt,1000003
|
||||
* +DC_rd/0,1000003
|
||||
* Return: <buf>, filled in.
|
||||
*/
|
||||
|
||||
extern const char *hwc_memop_string (ABST_type memop);
|
||||
/* Get a i18n'd description of a variable of type ABST_type.
|
||||
* Return: pointer to static string.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
704
gprofng/common/hwcfuncs.c
Normal file
704
gprofng/common/hwcfuncs.c
Normal file
|
@ -0,0 +1,704 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Hardware counter profiling */
|
||||
#include "hwcdrv.h"
|
||||
#include "hwcfuncs.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* macros */
|
||||
|
||||
#define IS_GLOBAL /* Mark global symbols */
|
||||
#define HWCDRV_API static /* Mark functions used by hwcdrv API */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* static variables */
|
||||
static uint_t cpcN_npics;
|
||||
static char hwcfuncs_errmsg_buf[1024];
|
||||
static int hwcfuncs_errmsg_enabled = 1;
|
||||
static int hwcfuncs_errmsg_valid;
|
||||
|
||||
/* --- user counter selections and options */
|
||||
static unsigned hwcdef_cnt; /* number of *active* hardware counters */
|
||||
static Hwcentry hwcdef[MAX_PICS]; /* HWC definitions */
|
||||
static Hwcentry *hwctable[MAX_PICS]; /* HWC definitions */
|
||||
|
||||
/* --- drivers --- */
|
||||
|
||||
// default driver
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_init (hwcfuncs_abort_fn_t abort_ftn, int* tsd_sz)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API void
|
||||
hwcdrv_get_info (
|
||||
int * cpuver, const char ** cciname,
|
||||
uint_t * npics, const char ** docref, uint64_t* support) { }
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_enable_mt (hwcfuncs_tsd_get_fn_t tsd_ftn)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_get_descriptions (hwcf_hwc_cb_t *hwc_find_action,
|
||||
hwcf_attr_cb_t *attr_find_action)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_assign_regnos (Hwcentry *entries[], unsigned numctrs)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_create_counters (unsigned hwcdef_cnt, Hwcentry *hwcdef)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_read_events (hwc_event_t *events, hwc_event_samples_t*samples)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_start (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_overflow (siginfo_t *si, hwc_event_t *s, hwc_event_t *t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_sighlr_restart (const hwc_event_t *sample)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_lwp_suspend (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_lwp_resume (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_free_counters (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWCDRV_API int
|
||||
hwcdrv_lwp_init (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWCDRV_API void
|
||||
hwcdrv_lwp_fini (void) { }
|
||||
|
||||
static hwcdrv_api_t hwcdrv_default = {
|
||||
hwcdrv_init,
|
||||
hwcdrv_get_info,
|
||||
hwcdrv_enable_mt,
|
||||
hwcdrv_get_descriptions,
|
||||
hwcdrv_assign_regnos,
|
||||
hwcdrv_create_counters,
|
||||
hwcdrv_start,
|
||||
hwcdrv_overflow,
|
||||
hwcdrv_read_events,
|
||||
hwcdrv_sighlr_restart,
|
||||
hwcdrv_lwp_suspend,
|
||||
hwcdrv_lwp_resume,
|
||||
hwcdrv_free_counters,
|
||||
hwcdrv_lwp_init,
|
||||
hwcdrv_lwp_fini,
|
||||
-1 // hwcdrv_init_status
|
||||
};
|
||||
|
||||
static hwcdrv_api_t *hwcdrv_driver = &hwcdrv_default;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* misc */
|
||||
|
||||
/* print a counter definition (for debugging) */
|
||||
static void
|
||||
ctrdefprint (int dbg_lvl, const char * hdr, Hwcentry*phwcdef)
|
||||
{
|
||||
TprintfT (dbg_lvl, "%s: name='%s', int_name='%s',"
|
||||
" reg_num=%d, timecvt=%d, memop=%d, "
|
||||
"interval=%d, tag=%u, reg_list=%p\n",
|
||||
hdr, phwcdef->name, phwcdef->int_name, phwcdef->reg_num,
|
||||
phwcdef->timecvt, phwcdef->memop, phwcdef->val,
|
||||
phwcdef->sort_order, phwcdef->reg_list);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* errmsg buffering */
|
||||
|
||||
/* errmsg buffering is needed only because the most descriptive error
|
||||
messages from CPC are delivered using a callback mechanism.
|
||||
hwcfuncs_errmsg_get() should only be used during initialization, and
|
||||
ideally, only to provide feedback to an end user when his counters can't
|
||||
be bound to HW.
|
||||
*/
|
||||
IS_GLOBAL char *
|
||||
hwcfuncs_errmsg_get (char *buf, size_t bufsize, int enable)
|
||||
{
|
||||
hwcfuncs_errmsg_enabled = 0;
|
||||
if (buf && bufsize)
|
||||
{
|
||||
if (hwcfuncs_errmsg_valid)
|
||||
{
|
||||
strncpy (buf, hwcfuncs_errmsg_buf, bufsize);
|
||||
buf[bufsize - 1] = 0;
|
||||
}
|
||||
else
|
||||
*buf = 0;
|
||||
}
|
||||
hwcfuncs_errmsg_buf[0] = 0;
|
||||
hwcfuncs_errmsg_valid = 0;
|
||||
hwcfuncs_errmsg_enabled = enable;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* used by cpc to log an error */
|
||||
IS_GLOBAL void
|
||||
hwcfuncs_int_capture_errmsg (const char *fn, int subcode,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
if (hwcfuncs_errmsg_enabled &&
|
||||
!hwcfuncs_errmsg_valid)
|
||||
{
|
||||
vsnprintf (hwcfuncs_errmsg_buf, sizeof (hwcfuncs_errmsg_buf), fmt, ap);
|
||||
TprintfT (DBG_LT0, "hwcfuncs: cpcN_capture_errmsg(): %s\n",
|
||||
hwcfuncs_errmsg_buf);
|
||||
hwcfuncs_errmsg_valid = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Log an internal error to the CPC error buffer.
|
||||
* Note: only call this during init functions.
|
||||
* Note: when most cpc calls fail, they will call cpcN_capture_errmsg()
|
||||
* directly, so only call logerr() when a non-cpc function fails.
|
||||
*/
|
||||
IS_GLOBAL void
|
||||
hwcfuncs_int_logerr (const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start (va, format);
|
||||
hwcfuncs_int_capture_errmsg ("logerr", 0, format, va);
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
/* utils to parse counter strings */
|
||||
static void
|
||||
clear_hwcdefs ()
|
||||
{
|
||||
for (unsigned idx = 0; idx < MAX_PICS; idx++)
|
||||
{
|
||||
static Hwcentry empty;
|
||||
hwcdef[idx] = empty; // leaks strings and reg_list array
|
||||
hwcdef[idx].reg_num = REGNO_ANY;
|
||||
hwcdef[idx].val = -1;
|
||||
hwcdef[idx].sort_order = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize hwcdef[] based on user's counter definitions */
|
||||
static int
|
||||
process_data_descriptor (const char *defstring)
|
||||
{
|
||||
/*
|
||||
* <defstring> format should be of format
|
||||
* :%s:%s:0x%x:%d:%lld:%d:%d:0x%x[,%s...repeat for each ctr]
|
||||
* where the counter fields are:
|
||||
* :<userName>:<internalCtr>:<register>:<timeoutVal>[:m<min_time>]:<tag>:<timecvt>:<memop>
|
||||
* See Coll_Ctrl::build_data_desc().
|
||||
*/
|
||||
int err = 0;
|
||||
char *ds = NULL;
|
||||
char *dsp = NULL;
|
||||
unsigned idx;
|
||||
|
||||
clear_hwcdefs ();
|
||||
if (!defstring || !strlen (defstring))
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
ds = strdup (defstring);
|
||||
if (!ds)
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCINIT;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
dsp = ds;
|
||||
|
||||
for (idx = 0; idx < MAX_PICS && *dsp; idx++)
|
||||
{
|
||||
char *name = NULL;
|
||||
char *int_name = NULL;
|
||||
regno_t reg = REGNO_ANY;
|
||||
ABST_type memop = ABST_NONE;
|
||||
int interval = 0;
|
||||
int timecvt = 0;
|
||||
unsigned sort_order = (unsigned) - 1;
|
||||
|
||||
/* name */
|
||||
name = dsp;
|
||||
dsp = strchr (dsp, ':');
|
||||
if (dsp == NULL)
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
*dsp++ = (char) 0;
|
||||
|
||||
/* int_name */
|
||||
int_name = dsp;
|
||||
dsp = strchr (dsp, ':');
|
||||
if (dsp == NULL)
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
*dsp++ = (char) 0;
|
||||
|
||||
/* reg_num */
|
||||
reg = (int) strtol (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
if (reg < 0 && reg != -1)
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
if (reg >= 0)
|
||||
hwcdef[idx].reg_num = reg;
|
||||
|
||||
/* val */
|
||||
interval = (int) strtol (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
if (interval < 0)
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
hwcdef[idx].val = interval;
|
||||
|
||||
/* min_time */
|
||||
/*
|
||||
* This is a new field.
|
||||
* An old launcher (dbx, etc.) would not include it.
|
||||
* Detect the presence of the field by the char 'm'.
|
||||
*/
|
||||
if (*dsp == 'm')
|
||||
{
|
||||
long long tmp_ll = 0;
|
||||
dsp++;
|
||||
tmp_ll = strtoll (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
if (tmp_ll < 0)
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
hwcdef[idx].min_time = tmp_ll;
|
||||
}
|
||||
else
|
||||
hwcdef[idx].min_time = 0;
|
||||
|
||||
/* sort_order */
|
||||
sort_order = (int) strtoul (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
hwcdef[idx].sort_order = sort_order;
|
||||
|
||||
/* timecvt */
|
||||
timecvt = (int) strtol (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
hwcdef[idx].timecvt = timecvt;
|
||||
|
||||
/* memop */
|
||||
memop = (ABST_type) strtol (dsp, &dsp, 0);
|
||||
if (*dsp != 0 && *dsp++ != ',')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
hwcdef[idx].memop = memop;
|
||||
if (*name)
|
||||
hwcdef[idx].name = strdup (name);
|
||||
else
|
||||
hwcdef[idx].name = strdup (int_name);
|
||||
if (*int_name)
|
||||
hwcdef[idx].int_name = strdup (int_name);
|
||||
else
|
||||
hwcdef[idx].int_name = strdup (name);
|
||||
ctrdefprint (DBG_LT1, "hwcfuncs: process_data_descriptor", &hwcdef[idx]);
|
||||
}
|
||||
|
||||
if (*dsp)
|
||||
{
|
||||
TprintfT (DBG_LT0, "hwcfuncs: ERROR: process_data_descriptor(): "
|
||||
"ctr string had some trailing garbage:"
|
||||
" '%s'\n", dsp);
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
goto ext_hw_install_end;
|
||||
}
|
||||
free (ds);
|
||||
hwcdef_cnt = idx;
|
||||
return 0;
|
||||
|
||||
ext_hw_install_end:
|
||||
if (dsp && *dsp)
|
||||
{
|
||||
TprintfT (DBG_LT0, "hwcfuncs: ERROR: process_data_descriptor(): "
|
||||
" syntax error just before:"
|
||||
" '%s;\n", dsp);
|
||||
logerr (GTXT ("Data descriptor syntax error near `%s'\n"), dsp);
|
||||
}
|
||||
else
|
||||
logerr (GTXT ("Data descriptor syntax error\n"));
|
||||
free (ds);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* initialize hwcdef[] based on user's counter definitions */
|
||||
static int
|
||||
process_hwcentrylist (const Hwcentry* entries[], unsigned numctrs)
|
||||
{
|
||||
int err = 0;
|
||||
clear_hwcdefs ();
|
||||
if (numctrs > cpcN_npics)
|
||||
{
|
||||
logerr (GTXT ("More than %d counters were specified\n"), cpcN_npics); /*!*/
|
||||
return HWCFUNCS_ERROR_HWCARGS;
|
||||
}
|
||||
for (unsigned idx = 0; idx < numctrs; idx++)
|
||||
{
|
||||
Hwcentry *phwcdef = &hwcdef[idx];
|
||||
*phwcdef = *entries[idx];
|
||||
if (phwcdef->name)
|
||||
phwcdef->name = strdup (phwcdef->name);
|
||||
else
|
||||
phwcdef->name = "NULL";
|
||||
if (phwcdef->int_name)
|
||||
phwcdef->int_name = strdup (phwcdef->int_name);
|
||||
else
|
||||
phwcdef->int_name = "NULL";
|
||||
if (phwcdef->val < 0)
|
||||
{
|
||||
logerr (GTXT ("Negative interval specified for HW counter `%s'\n"), /*!*/
|
||||
phwcdef->name);
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
break;
|
||||
}
|
||||
ctrdefprint (DBG_LT1, "hwcfuncs: process_hwcentrylist", phwcdef);
|
||||
}
|
||||
if (!err)
|
||||
hwcdef_cnt = numctrs;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* see hwcfuncs.h */
|
||||
IS_GLOBAL void *
|
||||
hwcfuncs_parse_attrs (const char *countername, hwcfuncs_attr_t attrs[],
|
||||
unsigned max_attrs, uint_t *pnum_attrs, char**errstring)
|
||||
{
|
||||
char *head = NULL;
|
||||
char *tail = NULL;
|
||||
uint_t nattrs = 0;
|
||||
char *counter_copy;
|
||||
int success = 0;
|
||||
char errbuf[512];
|
||||
errbuf[0] = 0;
|
||||
counter_copy = strdup (countername);
|
||||
|
||||
/* advance pointer to first attribute */
|
||||
tail = strchr (counter_copy, HWCFUNCS_PARSE_ATTR);
|
||||
if (tail)
|
||||
*tail = 0;
|
||||
|
||||
/* remove regno and value, if supplied */
|
||||
{
|
||||
char *tmp = strchr (counter_copy, HWCFUNCS_PARSE_REGNUM);
|
||||
if (tmp)
|
||||
*tmp = 0;
|
||||
tmp = strchr (counter_copy, HWCFUNCS_PARSE_VALUE);
|
||||
if (tmp)
|
||||
*tmp = 0;
|
||||
}
|
||||
|
||||
while (tail)
|
||||
{
|
||||
char *pch;
|
||||
if (nattrs >= max_attrs)
|
||||
{
|
||||
snprintf (errbuf, sizeof (errbuf),
|
||||
GTXT ("Too many attributes defined in `%s'"),
|
||||
countername);
|
||||
goto mycpc2_parse_attrs_end;
|
||||
}
|
||||
/* get attribute name */
|
||||
head = tail + 1;
|
||||
tail = strchr (head, HWCFUNCS_PARSE_EQUAL);
|
||||
if (!tail)
|
||||
{
|
||||
snprintf (errbuf, sizeof (errbuf),
|
||||
GTXT ("Missing value for attribute `%s' in `%s'"),
|
||||
head, countername);
|
||||
goto mycpc2_parse_attrs_end;
|
||||
}
|
||||
*tail = 0; /* null terminate current component */
|
||||
attrs[nattrs].ca_name = head;
|
||||
|
||||
/* get attribute value */
|
||||
head = tail + 1;
|
||||
tail = strchr (head, HWCFUNCS_PARSE_ATTR);
|
||||
if (tail)
|
||||
*tail = 0; /* null terminate current component */
|
||||
attrs[nattrs].ca_val = strtoull (head, &pch, 0);
|
||||
if (pch == head)
|
||||
{
|
||||
snprintf (errbuf, sizeof (errbuf),
|
||||
GTXT ("Illegal value for attribute `%s' in `%s'"),
|
||||
attrs[nattrs].ca_name, countername);
|
||||
goto mycpc2_parse_attrs_end;
|
||||
}
|
||||
TprintfT (DBG_LT0, "hwcfuncs: pic_: '%s', attribute[%u]"
|
||||
" '%s' = 0x%llx\n",
|
||||
counter_copy, nattrs, attrs[nattrs].ca_name,
|
||||
(long long unsigned int) attrs[nattrs].ca_val);
|
||||
|
||||
nattrs++;
|
||||
}
|
||||
success = 1;
|
||||
|
||||
mycpc2_parse_attrs_end:
|
||||
*pnum_attrs = nattrs;
|
||||
if (success)
|
||||
{
|
||||
if (errstring)
|
||||
*errstring = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (errstring)
|
||||
*errstring = strdup (errbuf);
|
||||
free (counter_copy);
|
||||
counter_copy = NULL;
|
||||
}
|
||||
return counter_copy;
|
||||
}
|
||||
|
||||
IS_GLOBAL void
|
||||
hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly,
|
||||
char **pattrs, char **pregstr, regno_t *pregno)
|
||||
{
|
||||
char *nameptr, *copy, *slash, *attr_delim;
|
||||
int plus;
|
||||
regno_t regno;
|
||||
nameptr = copy = strdup (counter_def);
|
||||
|
||||
/* plus */
|
||||
plus = 0;
|
||||
if (nameptr[0] == HWCFUNCS_PARSE_BACKTRACK)
|
||||
{
|
||||
plus = 1;
|
||||
nameptr++;
|
||||
}
|
||||
else if (nameptr[0] == HWCFUNCS_PARSE_BACKTRACK_OFF)
|
||||
{
|
||||
plus = -1;
|
||||
nameptr++;
|
||||
}
|
||||
if (pplus)
|
||||
*pplus = plus;
|
||||
|
||||
/* regno */
|
||||
regno = REGNO_ANY;
|
||||
if (pregstr)
|
||||
*pregstr = NULL;
|
||||
slash = strchr (nameptr, HWCFUNCS_PARSE_REGNUM);
|
||||
if (slash != NULL)
|
||||
{
|
||||
/* the remaining string should be a number > 0 */
|
||||
if (pregstr)
|
||||
*pregstr = strdup (slash);
|
||||
char *endchar = NULL;
|
||||
regno = (regno_t) strtol (slash + 1, &endchar, 0);
|
||||
if (*endchar != 0)
|
||||
regno = -2;
|
||||
if (*(slash + 1) == '-')
|
||||
regno = -2;
|
||||
/* terminate previous element up to slash */
|
||||
*slash = 0;
|
||||
}
|
||||
if (pregno)
|
||||
*pregno = regno;
|
||||
|
||||
/* attrs */
|
||||
if (pattrs)
|
||||
*pattrs = NULL;
|
||||
attr_delim = strchr (nameptr, HWCFUNCS_PARSE_ATTR);
|
||||
if (attr_delim != NULL)
|
||||
{
|
||||
if (pattrs)
|
||||
*pattrs = strdup (attr_delim);
|
||||
/* terminate previous element up to attr_delim */
|
||||
*attr_delim++ = 0;
|
||||
}
|
||||
if (pnameOnly)
|
||||
*pnameOnly = strdup (nameptr);
|
||||
free (copy);
|
||||
}
|
||||
|
||||
/* create counters */
|
||||
IS_GLOBAL int
|
||||
hwcfuncs_bind_descriptor (const char *defstring)
|
||||
{
|
||||
int err = process_data_descriptor (defstring);
|
||||
if (err)
|
||||
{
|
||||
TprintfT (DBG_LT0, "hwcfuncs: ERROR: hwcfuncs_bind_descriptor failed\n");
|
||||
return err;
|
||||
}
|
||||
err = hwcdrv_driver->hwcdrv_create_counters (hwcdef_cnt, hwcdef);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* see hwcfuncs.h */
|
||||
IS_GLOBAL int
|
||||
hwcfuncs_bind_hwcentry (const Hwcentry* entries[], unsigned numctrs)
|
||||
{
|
||||
int err = -1;
|
||||
err = process_hwcentrylist (entries, numctrs);
|
||||
if (err)
|
||||
{
|
||||
TprintfT (DBG_LT0, "hwcfuncs: ERROR: hwcfuncs_bind_hwcentry\n");
|
||||
return err;
|
||||
}
|
||||
err = hwcdrv_driver->hwcdrv_create_counters (hwcdef_cnt, hwcdef);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* see hwcfuncs.h */
|
||||
IS_GLOBAL Hwcentry **
|
||||
hwcfuncs_get_ctrs (unsigned *defcnt)
|
||||
{
|
||||
if (defcnt)
|
||||
*defcnt = hwcdef_cnt;
|
||||
return hwctable;
|
||||
}
|
||||
|
||||
/* return 1 if <regno> is in Hwcentry's list */
|
||||
IS_GLOBAL int
|
||||
regno_is_valid (const Hwcentry * pctr, regno_t regno)
|
||||
{
|
||||
regno_t *reg_list = pctr->reg_list;
|
||||
if (REG_LIST_IS_EMPTY (reg_list))
|
||||
return 0;
|
||||
if (regno == REGNO_ANY) /* wildcard */
|
||||
return 1;
|
||||
for (int ii = 0; ii < MAX_PICS; ii++)
|
||||
{
|
||||
regno_t tmp = reg_list[ii];
|
||||
if (REG_LIST_EOL (tmp)) /* end of list */
|
||||
break;
|
||||
if (tmp == regno) /* is in list */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* supplied by hwcdrv_api drivers */
|
||||
IS_GLOBAL int
|
||||
hwcfuncs_assign_regnos (Hwcentry* entries[],
|
||||
unsigned numctrs)
|
||||
{
|
||||
if (numctrs > cpcN_npics)
|
||||
{
|
||||
logerr (GTXT ("More than %d counters were specified\n"), cpcN_npics); /*!*/
|
||||
return HWCFUNCS_ERROR_HWCARGS;
|
||||
}
|
||||
return hwcdrv_driver->hwcdrv_assign_regnos (entries, numctrs);
|
||||
}
|
||||
|
||||
extern hwcdrv_api_t hwcdrv_pcl_api;
|
||||
static int hwcdrv_driver_inited = 0;
|
||||
|
||||
hwcdrv_api_t *
|
||||
get_hwcdrv ()
|
||||
{
|
||||
if (hwcdrv_driver_inited)
|
||||
return hwcdrv_driver;
|
||||
hwcdrv_driver_inited = 1;
|
||||
cpcN_npics = 0;
|
||||
for (int i = 0; i < MAX_PICS; i++)
|
||||
hwctable[i] = &hwcdef[i];
|
||||
hwcdrv_driver = &hwcdrv_pcl_api;
|
||||
hwcdrv_driver->hwcdrv_init_status = hwcdrv_driver->hwcdrv_init (NULL, NULL);
|
||||
if (hwcdrv_driver->hwcdrv_init_status == 0)
|
||||
{
|
||||
hwcdrv_driver->hwcdrv_get_info (NULL, NULL, &cpcN_npics, NULL, NULL);
|
||||
return hwcdrv_driver;
|
||||
}
|
||||
hwcdrv_driver = &hwcdrv_default;
|
||||
return hwcdrv_driver;
|
||||
}
|
269
gprofng/common/hwcfuncs.h
Normal file
269
gprofng/common/hwcfuncs.h
Normal file
|
@ -0,0 +1,269 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Hardware counter profiling */
|
||||
|
||||
#ifndef __HWCFUNCS_H
|
||||
#define __HWCFUNCS_H
|
||||
|
||||
#ifdef LIBCOLLECTOR_SRC /* running in libcollector */
|
||||
#define hwcfuncs_int_logerr __collector_hwcfuncs_int_logerr
|
||||
#define hwcfuncs_parse_ctr __collector_hwcfuncs_parse_ctr
|
||||
#define hwcfuncs_parse_attrs __collector_hwcfuncs_parse_attrs
|
||||
#define hwcfuncs_bind_descriptor __collector_hwcfuncs_bind_descriptor
|
||||
#define hwcfuncs_bind_hwcentry __collector_hwcfuncs_bind_hwcentry
|
||||
#define hwcfuncs_assign_regnos __collector_hwcfuncs_assign_regnos
|
||||
#define regno_is_valid __collector_regno_is_valid
|
||||
#define hwcfuncs_get_ctrs __collector_hwcfuncs_get_ctrs
|
||||
#define hwcfuncs_errmsg_get __collector_hwcfuncs_errmsg_get
|
||||
#endif /* --- LIBCOLLECTOR_SRC --- */
|
||||
|
||||
#include <signal.h> /* siginfo_t */
|
||||
#include <limits.h> /* UINT64_t */
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hwcentry.h" /* for Hwcentry type */
|
||||
#include "gp-time.h"
|
||||
|
||||
typedef unsigned int uint_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* compile options */
|
||||
|
||||
#define HWC_DEBUG 0 /* 0/1 to enable extra HWC debug */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* typedefs */
|
||||
/* generic hw event */
|
||||
typedef struct _hwc_event_t
|
||||
{ /* generalized counter event */
|
||||
hrtime_t ce_hrt; /* gethrtime() */
|
||||
uint64_t ce_pic[MAX_PICS]; /* counter samples or start values */
|
||||
} hwc_event_t;
|
||||
|
||||
/* supplementary data that accompanies some hw events */
|
||||
typedef struct
|
||||
{ /* supplementary data fields */
|
||||
uint64_t smpl_pc; /* pc related to event */
|
||||
uint64_t smpl_data_source; /* chip-specific data source encoding */
|
||||
uint64_t smpl_latency; /* latency related to event */
|
||||
uint64_t smpl_mem_addr; /* memory address related to event */
|
||||
} hwc_sample_t;
|
||||
#define HWCFUNCS_INVALID_U64 0xFEEDBEEFDEADBEEFllu /* identifies fields as unused */
|
||||
|
||||
typedef struct { /* supplementary data fields */
|
||||
hwc_sample_t sample[MAX_PICS]; /* counter samples or start values */
|
||||
} hwc_event_samples_t;
|
||||
|
||||
#define HWCFUNCS_SAMPLE_RESET(sample) \
|
||||
do { \
|
||||
(sample)->smpl_pc =HWCFUNCS_INVALID_U64; \
|
||||
(sample)->smpl_data_source =HWCFUNCS_INVALID_U64; \
|
||||
(sample)->smpl_latency =HWCFUNCS_INVALID_U64; \
|
||||
(sample)->smpl_mem_addr =HWCFUNCS_INVALID_U64; \
|
||||
} while(0)
|
||||
|
||||
#define HWCFUNCS_SAMPLE_IS_RESET(sample) \
|
||||
( \
|
||||
(sample)->smpl_pc ==HWCFUNCS_INVALID_U64 && \
|
||||
(sample)->smpl_data_source==HWCFUNCS_INVALID_U64 && \
|
||||
(sample)->smpl_latency ==HWCFUNCS_INVALID_U64 && \
|
||||
(sample)->smpl_mem_addr ==HWCFUNCS_INVALID_U64 \
|
||||
)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* macros */
|
||||
|
||||
#define HW_INTERVAL_MAX UINT64_MAX
|
||||
#define HW_INTERVAL_PRESET(x) (HW_INTERVAL_MAX - ((uint64_t)(x) - 1))
|
||||
#define HW_INTERVAL_TYPE(x) ((uint64_t) (x)
|
||||
|
||||
/* parsing */
|
||||
#define HWCFUNCS_MAX_ATTRS 20
|
||||
#define HWCFUNCS_PARSE_ATTR '~'
|
||||
#define HWCFUNCS_PARSE_EQUAL '='
|
||||
#define HWCFUNCS_PARSE_BACKTRACK '+'
|
||||
#define HWCFUNCS_PARSE_BACKTRACK_OFF '-'
|
||||
#define HWCFUNCS_PARSE_REGNUM '/'
|
||||
#define HWCFUNCS_PARSE_VALUE ','
|
||||
|
||||
/* error codes */
|
||||
#define HWCFUNCS_ERROR_GENERIC (-1)
|
||||
#define HWCFUNCS_ERROR_NOT_SUPPORTED (-2)
|
||||
#define HWCFUNCS_ERROR_ALREADY_CALLED (-3)
|
||||
#define HWCFUNCS_ERROR_HWCINIT (-4)
|
||||
#define HWCFUNCS_ERROR_HWCARGS (-5)
|
||||
#define HWCFUNCS_ERROR_MEMORY (-6)
|
||||
#define HWCFUNCS_ERROR_UNAVAIL (-7)
|
||||
#define HWCFUNCS_ERROR_ERRNO_ZERO (-8)
|
||||
#define HWCFUNCS_ERROR_UNEXPECTED (-99)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* prototypes */
|
||||
|
||||
typedef void (*hwcfuncs_abort_fn_t) (int errnum, const char *msg);
|
||||
|
||||
extern void hwcfuncs_int_logerr(const char *format,...);
|
||||
/* Log an error to the internal error buffer. See hwcfuncs_errmsg_get().
|
||||
Note: Not MT-safe; don't even enable logging in an MT environment.
|
||||
Recommend using this call only during init.
|
||||
Note: when a libcpc call fails, it may automatically call
|
||||
cpcN_capture_errmsg() to log the error message in the same internal buffer.
|
||||
Recommend using this call only for non-cpc failures.
|
||||
*/
|
||||
|
||||
#define HWCFUNCS_SUPPORT_OVERFLOW_PROFILING 0x01llu
|
||||
#define HWCFUNCS_SUPPORT_PEBS_SAMPLING 0x02llu
|
||||
#define HWCFUNCS_SUPPORT_OVERFLOW_CTR_ID 0x04llu // OS identifies which counter overflowed
|
||||
/* get info about session
|
||||
Input:
|
||||
<cpuver>: if not NULL, returns value of CPC cpu version
|
||||
<cciname>: if not NULL, returns name of CPU
|
||||
<npics>: if not NULL, returns maximum # of HWCs
|
||||
<docref>: if not NULL, returns documentation reference
|
||||
<support>: if not NULL, returns bitmask (see above) of hwc support
|
||||
Return: none
|
||||
*/
|
||||
|
||||
typedef void* (*hwcfuncs_tsd_get_fn_t) (void);
|
||||
typedef void (hwcf_hwc_cb_t) (uint_t cpcregno, const char *name);
|
||||
typedef void (hwcf_attr_cb_t) (const char *attr);
|
||||
|
||||
extern void
|
||||
hwcfuncs_parse_ctr (const char *counter_def, int *pplus, char **pnameOnly,
|
||||
char **pattrs, char **pregstr, regno_t *pregno);
|
||||
/* Parse a counter definition string (value must already be stripped off).
|
||||
Input:
|
||||
<counter_def>: input whose format is
|
||||
[+|-]<countername>[~attrs...][/<regno>]
|
||||
pointers to return values: Any can be NULL.
|
||||
Return:
|
||||
<plus>: 1 if [+] is found, -1 if [-] is found, 0 otherwise
|
||||
<pnameonly>: strdup(<countername>)
|
||||
<pattrs>: strdup([~attrs...]) if specified, NULL otherwise.
|
||||
<pregstr>: strdup(/<regno>) if specified, NULL otherwise.
|
||||
<pregno>: <regno> if readable, REGNO_ANY if not specd, or -2 otherwise.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *ca_name;
|
||||
uint64_t ca_val;
|
||||
} hwcfuncs_attr_t; /* matches cpc_attr_t */
|
||||
|
||||
void * hwcfuncs_parse_attrs (const char *countername,
|
||||
hwcfuncs_attr_t attrs[], unsigned max_attrs,
|
||||
uint_t *pnum_attrs, char **errstring);
|
||||
/* Extract the attribute fields from <countername>.
|
||||
Input:
|
||||
<countername>: string whose format is
|
||||
[+]<ctrname>[~attributes...][/<regno>][,...]
|
||||
<attrs>: array of attributes to be returned
|
||||
<max_attrs>: number of elements in <attrs>
|
||||
<pnum_attrs>: if not NULL, will return how many attrs were found.
|
||||
<errstring>: pointer to a buffer for storing error info, or NULL.
|
||||
Return: upon success, a pointer to an allocated copy of <countername>, or
|
||||
NULL if there's a failure. (A copy is made in order to provide storage
|
||||
for the ca_name fields in the <attrs> array.)
|
||||
|
||||
The pointer should be freed when <attrs> is no longer in use.
|
||||
<attrs> will be filled in data from countername.
|
||||
<pnum_attrs> will have the number of elements in <attrs>. May be
|
||||
non-zero even if return value indicates an error.
|
||||
<errstring> NULL if no error, otherwise, a malloc'd GTXT string.
|
||||
*/
|
||||
|
||||
extern int hwcfuncs_bind_descriptor (const char *defstring);
|
||||
/* Bind counters to resources.
|
||||
Input:
|
||||
<defstring>: string whose format is
|
||||
:%s:%s:0x%x:%d:%d,0x%x[:%s...repeat for each ctr]
|
||||
where the fields are:
|
||||
:<userName>:<internalCtr>:<register>:<timeoutVal>:<tag>:<memop>
|
||||
Return: 0 if successful
|
||||
HWCFUNCS_ERROR_HWCINIT if resources unavailable
|
||||
HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
|
||||
*/
|
||||
|
||||
extern int hwcfuncs_bind_hwcentry (const Hwcentry *entries[],
|
||||
unsigned numctrs);
|
||||
/* Bind counters to resources.
|
||||
Input:
|
||||
<entries>: array of counters
|
||||
<numctrs>: number of items in <entries>
|
||||
Return: 0 if successful
|
||||
HWCFUNCS_ERROR_HWCINIT if resources unavailable
|
||||
HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
|
||||
*/
|
||||
|
||||
extern int hwcfuncs_assign_regnos (Hwcentry *entries[], unsigned numctrs);
|
||||
/* Assign entries[]->reg_num values as needed by platform
|
||||
Note: modifies <entries> by supplying a regno to each counter
|
||||
Input:
|
||||
<entries>: array of counters
|
||||
<numctrs>: number of items in <entries>
|
||||
Output:
|
||||
<entries>: array of counters is modified
|
||||
Return: 0 if successful
|
||||
HWCFUNCS_ERROR_HWCINIT if resources unavailable
|
||||
HWCFUNCS_ERROR_HWCARGS if counters were not specified correctly
|
||||
*/
|
||||
|
||||
extern int regno_is_valid (const Hwcentry *pctr, regno_t regno);
|
||||
/* return 1 if <regno> is in Hwcentry's list
|
||||
Input:
|
||||
<pctr>: counter definition, reg_list[] should be initialized
|
||||
<regno>: register to check
|
||||
Return: 1 if <regno> is in Hwcentry's list, 0 otherwise
|
||||
*/
|
||||
|
||||
extern Hwcentry **hwcfuncs_get_ctrs (unsigned *defcnt);
|
||||
/* Get descriptions of the currently bound counters.
|
||||
Input:
|
||||
<defcnt>: if not NULL, returns number of counter definitions.
|
||||
Return:
|
||||
table of counter definition pointers
|
||||
*/
|
||||
|
||||
extern char *hwcfuncs_errmsg_get (char * buf, size_t bufsize,
|
||||
int enable_capture);
|
||||
/* Gets a recent HWC error message.
|
||||
To clear previous error messages and insure error message is enabled,
|
||||
call hwcfuncs_errmsg_get(NULL,0,1).
|
||||
Once enabled, one error is stored in an internal buffer. A call to this
|
||||
function will clear the buffer and allow a new message to be captured.
|
||||
Note: Not MT-safe - don't enable this feature in an MT environment.
|
||||
Input:
|
||||
<buf>: pointer to buffer or NULL.
|
||||
<bufsize>: size of <buf>
|
||||
<enable_capture>: 0 - disable buffering, 1 - enable buffering.
|
||||
Return: error string or an empty string.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! __HWCFUNCS_H */
|
5410
gprofng/common/hwctable.c
Normal file
5410
gprofng/common/hwctable.c
Normal file
File diff suppressed because it is too large
Load diff
448
gprofng/common/opteron_pcbe.c
Normal file
448
gprofng/common/opteron_pcbe.c
Normal file
|
@ -0,0 +1,448 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* This file contains preset event names from the Performance Application
|
||||
* Programming Interface v3.5 which included the following notice:
|
||||
*
|
||||
* Copyright (c) 2005,6
|
||||
* Innovative Computing Labs
|
||||
* Computer Science Department,
|
||||
* University of Tennessee,
|
||||
* Knoxville, TN.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University of Tennessee nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* This open source software license conforms to the BSD License template.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Performance Counter Back-End for AMD Opteron and AMD Athlon 64 processors.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "hwcdrv.h"
|
||||
|
||||
#define CPU /* used by cpuid_get*() functions */
|
||||
|
||||
typedef struct _amd_event
|
||||
{
|
||||
char *name;
|
||||
uint16_t emask; /* Event mask setting */
|
||||
uint8_t umask_valid; /* Mask of unreserved UNIT_MASK bits */
|
||||
} amd_event_t;
|
||||
|
||||
typedef struct _amd_generic_event
|
||||
{
|
||||
char *name;
|
||||
char *event;
|
||||
uint8_t umask;
|
||||
} amd_generic_event_t;
|
||||
|
||||
#define EV_END { NULL, 0, 0 }
|
||||
#define GEN_EV_END { NULL, NULL, 0 }
|
||||
|
||||
#define AMD_cmn_events \
|
||||
{ "FP_dispatched_fpu_ops", 0x00, 0x3F }, \
|
||||
{ "FP_cycles_no_fpu_ops_retired", 0x01, 0x0 }, \
|
||||
{ "FP_dispatched_fpu_ops_ff", 0x02, 0x0 }, \
|
||||
{ "LS_seg_reg_load", 0x20, 0x7F }, \
|
||||
{ "LS_uarch_resync_self_modify", 0x21, 0x0 }, \
|
||||
{ "LS_uarch_resync_snoop", 0x22, 0x0 }, \
|
||||
{ "LS_buffer_2_full", 0x23, 0x0 }, \
|
||||
{ "LS_retired_cflush", 0x26, 0x0 }, \
|
||||
{ "LS_retired_cpuid", 0x27, 0x0 }, \
|
||||
{ "DC_access", 0x40, 0x0 }, \
|
||||
{ "DC_miss", 0x41, 0x0 }, \
|
||||
{ "DC_refill_from_L2", 0x42, 0x1F }, \
|
||||
{ "DC_refill_from_system", 0x43, 0x1F }, \
|
||||
{ "DC_misaligned_data_ref", 0x47, 0x0 }, \
|
||||
{ "DC_uarch_late_cancel_access", 0x48, 0x0 }, \
|
||||
{ "DC_uarch_early_cancel_access", 0x49, 0x0 }, \
|
||||
{ "DC_dispatched_prefetch_instr", 0x4B, 0x7 }, \
|
||||
{ "DC_dcache_accesses_by_locks", 0x4C, 0x2 }, \
|
||||
{ "BU_memory_requests", 0x65, 0x83}, \
|
||||
{ "BU_data_prefetch", 0x67, 0x3 }, \
|
||||
{ "BU_cpu_clk_unhalted", 0x76, 0x0 }, \
|
||||
{ "IC_fetch", 0x80, 0x0 }, \
|
||||
{ "IC_miss", 0x81, 0x0 }, \
|
||||
{ "IC_refill_from_L2", 0x82, 0x0 }, \
|
||||
{ "IC_refill_from_system", 0x83, 0x0 }, \
|
||||
{ "IC_itlb_L1_miss_L2_hit", 0x84, 0x0 }, \
|
||||
{ "IC_uarch_resync_snoop", 0x86, 0x0 }, \
|
||||
{ "IC_instr_fetch_stall", 0x87, 0x0 }, \
|
||||
{ "IC_return_stack_hit", 0x88, 0x0 }, \
|
||||
{ "IC_return_stack_overflow", 0x89, 0x0 }, \
|
||||
{ "FR_retired_x86_instr_w_excp_intr", 0xC0, 0x0 }, \
|
||||
{ "FR_retired_uops", 0xC1, 0x0 }, \
|
||||
{ "FR_retired_branches_w_excp_intr", 0xC2, 0x0 }, \
|
||||
{ "FR_retired_branches_mispred", 0xC3, 0x0 }, \
|
||||
{ "FR_retired_taken_branches", 0xC4, 0x0 }, \
|
||||
{ "FR_retired_taken_branches_mispred", 0xC5, 0x0 }, \
|
||||
{ "FR_retired_far_ctl_transfer", 0xC6, 0x0 }, \
|
||||
{ "FR_retired_resyncs", 0xC7, 0x0 }, \
|
||||
{ "FR_retired_near_rets", 0xC8, 0x0 }, \
|
||||
{ "FR_retired_near_rets_mispred", 0xC9, 0x0 }, \
|
||||
{ "FR_retired_taken_branches_mispred_addr_miscomp", 0xCA, 0x0 }, \
|
||||
{ "FR_retired_fastpath_double_op_instr", 0xCC, 0x7 }, \
|
||||
{ "FR_intr_masked_cycles", 0xCD, 0x0 }, \
|
||||
{ "FR_intr_masked_while_pending_cycles", 0xCE, 0x0 }, \
|
||||
{ "FR_taken_hardware_intrs", 0xCF, 0x0 }, \
|
||||
{ "FR_nothing_to_dispatch", 0xD0, 0x0 }, \
|
||||
{ "FR_dispatch_stalls", 0xD1, 0x0 }, \
|
||||
{ "FR_dispatch_stall_branch_abort_to_retire", 0xD2, 0x0 }, \
|
||||
{ "FR_dispatch_stall_serialization", 0xD3, 0x0 }, \
|
||||
{ "FR_dispatch_stall_segment_load", 0xD4, 0x0 }, \
|
||||
{ "FR_dispatch_stall_reorder_buffer_full", 0xD5, 0x0 }, \
|
||||
{ "FR_dispatch_stall_resv_stations_full", 0xD6, 0x0 }, \
|
||||
{ "FR_dispatch_stall_fpu_full", 0xD7, 0x0 }, \
|
||||
{ "FR_dispatch_stall_ls_full", 0xD8, 0x0 }, \
|
||||
{ "FR_dispatch_stall_waiting_all_quiet", 0xD9, 0x0 }, \
|
||||
{ "FR_dispatch_stall_far_ctl_trsfr_resync_branch_pend", 0xDA, 0x0 },\
|
||||
{ "FR_fpu_exception", 0xDB, 0xF }, \
|
||||
{ "FR_num_brkpts_dr0", 0xDC, 0x0 }, \
|
||||
{ "FR_num_brkpts_dr1", 0xDD, 0x0 }, \
|
||||
{ "FR_num_brkpts_dr2", 0xDE, 0x0 }, \
|
||||
{ "FR_num_brkpts_dr3", 0xDF, 0x0 }, \
|
||||
{ "NB_mem_ctrlr_bypass_counter_saturation", 0xE4, 0xF }
|
||||
|
||||
#define OPT_events \
|
||||
{ "LS_locked_operation", 0x24, 0x7 }, \
|
||||
{ "DC_copyback", 0x44, 0x1F }, \
|
||||
{ "DC_dtlb_L1_miss_L2_hit", 0x45, 0x0 }, \
|
||||
{ "DC_dtlb_L1_miss_L2_miss", 0x46, 0x0 }, \
|
||||
{ "DC_1bit_ecc_error_found", 0x4A, 0x3 }, \
|
||||
{ "BU_system_read_responses", 0x6C, 0x7 }, \
|
||||
{ "BU_quadwords_written_to_system", 0x6D, 0x1 }, \
|
||||
{ "BU_internal_L2_req", 0x7D, 0x1F }, \
|
||||
{ "BU_fill_req_missed_L2", 0x7E, 0x7 }, \
|
||||
{ "BU_fill_into_L2", 0x7F, 0x1 }, \
|
||||
{ "IC_itlb_L1_miss_L2_miss", 0x85, 0x0 }, \
|
||||
{ "FR_retired_fpu_instr", 0xCB, 0xF }, \
|
||||
{ "NB_mem_ctrlr_page_access", 0xE0, 0x7 }, \
|
||||
{ "NB_mem_ctrlr_page_table_overflow", 0xE1, 0x0 }, \
|
||||
{ "NB_mem_ctrlr_turnaround", 0xE3, 0x7 }, \
|
||||
{ "NB_ECC_errors", 0xE8, 0x80}, \
|
||||
{ "NB_sized_commands", 0xEB, 0x7F }, \
|
||||
{ "NB_probe_result", 0xEC, 0x7F}, \
|
||||
{ "NB_gart_events", 0xEE, 0x7 }, \
|
||||
{ "NB_ht_bus0_bandwidth", 0xF6, 0xF }, \
|
||||
{ "NB_ht_bus1_bandwidth", 0xF7, 0xF }, \
|
||||
{ "NB_ht_bus2_bandwidth", 0xF8, 0xF }
|
||||
|
||||
#define OPT_RevD_events \
|
||||
{ "NB_sized_blocks", 0xE5, 0x3C }
|
||||
|
||||
#define OPT_RevE_events \
|
||||
{ "NB_cpu_io_to_mem_io", 0xE9, 0xFF}, \
|
||||
{ "NB_cache_block_commands", 0xEA, 0x3D}
|
||||
|
||||
#define AMD_FAMILY_10h_cmn_events \
|
||||
{ "FP_retired_sse_ops", 0x3, 0x7F}, \
|
||||
{ "FP_retired_move_ops", 0x4, 0xF}, \
|
||||
{ "FP_retired_serialize_ops", 0x5, 0xF}, \
|
||||
{ "FP_serialize_ops_cycles", 0x6, 0x3}, \
|
||||
{ "DC_copyback", 0x44, 0x7F }, \
|
||||
{ "DC_dtlb_L1_miss_L2_hit", 0x45, 0x3 }, \
|
||||
{ "DC_dtlb_L1_miss_L2_miss", 0x46, 0x7 }, \
|
||||
{ "DC_1bit_ecc_error_found", 0x4A, 0xF }, \
|
||||
{ "DC_dtlb_L1_hit", 0x4D, 0x7 }, \
|
||||
{ "BU_system_read_responses", 0x6C, 0x17 }, \
|
||||
{ "BU_octwords_written_to_system", 0x6D, 0x1 }, \
|
||||
{ "BU_internal_L2_req", 0x7D, 0x3F }, \
|
||||
{ "BU_fill_req_missed_L2", 0x7E, 0xF }, \
|
||||
{ "BU_fill_into_L2", 0x7F, 0x3 }, \
|
||||
{ "IC_itlb_L1_miss_L2_miss", 0x85, 0x3 }, \
|
||||
{ "IC_eviction", 0x8B, 0x0 }, \
|
||||
{ "IC_cache_lines_invalidate", 0x8C, 0xF }, \
|
||||
{ "IC_itlb_reload", 0x99, 0x0 }, \
|
||||
{ "IC_itlb_reload_aborted", 0x9A, 0x0 }, \
|
||||
{ "FR_retired_mmx_sse_fp_instr", 0xCB, 0x7 }, \
|
||||
{ "NB_mem_ctrlr_page_access", 0xE0, 0xFF }, \
|
||||
{ "NB_mem_ctrlr_page_table_overflow", 0xE1, 0x3 }, \
|
||||
{ "NB_mem_ctrlr_turnaround", 0xE3, 0x3F }, \
|
||||
{ "NB_thermal_status", 0xE8, 0x7C}, \
|
||||
{ "NB_sized_commands", 0xEB, 0x3F }, \
|
||||
{ "NB_probe_results_upstream_req", 0xEC, 0xFF}, \
|
||||
{ "NB_gart_events", 0xEE, 0xFF }, \
|
||||
{ "NB_ht_bus0_bandwidth", 0xF6, 0xBF }, \
|
||||
{ "NB_ht_bus1_bandwidth", 0xF7, 0xBF }, \
|
||||
{ "NB_ht_bus2_bandwidth", 0xF8, 0xBF }, \
|
||||
{ "NB_ht_bus3_bandwidth", 0x1F9, 0xBF }, \
|
||||
{ "LS_locked_operation", 0x24, 0xF }, \
|
||||
{ "LS_cancelled_store_to_load_fwd_ops", 0x2A, 0x7 }, \
|
||||
{ "LS_smi_received", 0x2B, 0x0 }, \
|
||||
{ "LS_ineffective_prefetch", 0x52, 0x9 }, \
|
||||
{ "LS_global_tlb_flush", 0x54, 0x0 }, \
|
||||
{ "NB_mem_ctrlr_dram_cmd_slots_missed", 0xE2, 0x3 }, \
|
||||
{ "NB_mem_ctrlr_req", 0x1F0, 0xFF }, \
|
||||
{ "CB_cpu_to_dram_req_to_target", 0x1E0, 0xFF }, \
|
||||
{ "CB_io_to_dram_req_to_target", 0x1E1, 0xFF }, \
|
||||
{ "CB_cpu_read_cmd_latency_to_target_0_to_3", 0x1E2, 0xFF }, \
|
||||
{ "CB_cpu_read_cmd_req_to_target_0_to_3", 0x1E3, 0xFF }, \
|
||||
{ "CB_cpu_read_cmd_latency_to_target_4_to_7", 0x1E4, 0xFF }, \
|
||||
{ "CB_cpu_read_cmd_req_to_target_4_to_7", 0x1E5, 0xFF }, \
|
||||
{ "CB_cpu_cmd_latency_to_target_0_to_7", 0x1E6, 0xFF }, \
|
||||
{ "CB_cpu_req_to_target_0_to_7", 0x1E7, 0xFF }, \
|
||||
{ "L3_read_req", 0x4E0, 0xF7 }, \
|
||||
{ "L3_miss", 0x4E1, 0xF7 }, \
|
||||
{ "L3_l2_eviction_l3_fill", 0x4E2, 0xFF }, \
|
||||
{ "L3_eviction", 0x4E3, 0xF }
|
||||
|
||||
#define AMD_cmn_generic_events \
|
||||
{ "PAPI_br_ins", "FR_retired_branches_w_excp_intr", 0x0 },\
|
||||
{ "PAPI_br_msp", "FR_retired_branches_mispred", 0x0 }, \
|
||||
{ "PAPI_br_tkn", "FR_retired_taken_branches", 0x0 }, \
|
||||
{ "PAPI_fp_ops", "FP_dispatched_fpu_ops", 0x3 }, \
|
||||
{ "PAPI_fad_ins", "FP_dispatched_fpu_ops", 0x1 }, \
|
||||
{ "PAPI_fml_ins", "FP_dispatched_fpu_ops", 0x2 }, \
|
||||
{ "PAPI_fpu_idl", "FP_cycles_no_fpu_ops_retired", 0x0 }, \
|
||||
{ "PAPI_tot_cyc", "BU_cpu_clk_unhalted", 0x0 }, \
|
||||
{ "PAPI_tot_ins", "FR_retired_x86_instr_w_excp_intr", 0x0 }, \
|
||||
{ "PAPI_l1_dca", "DC_access", 0x0 }, \
|
||||
{ "PAPI_l1_dcm", "DC_miss", 0x0 }, \
|
||||
{ "PAPI_l1_ldm", "DC_refill_from_L2", 0xe }, \
|
||||
{ "PAPI_l1_stm", "DC_refill_from_L2", 0x10 }, \
|
||||
{ "PAPI_l1_ica", "IC_fetch", 0x0 }, \
|
||||
{ "PAPI_l1_icm", "IC_miss", 0x0 }, \
|
||||
{ "PAPI_l1_icr", "IC_fetch", 0x0 }, \
|
||||
{ "PAPI_l2_dch", "DC_refill_from_L2", 0x1e }, \
|
||||
{ "PAPI_l2_dcm", "DC_refill_from_system", 0x1e }, \
|
||||
{ "PAPI_l2_dcr", "DC_refill_from_L2", 0xe }, \
|
||||
{ "PAPI_l2_dcw", "DC_refill_from_L2", 0x10 }, \
|
||||
{ "PAPI_l2_ich", "IC_refill_from_L2", 0x0 }, \
|
||||
{ "PAPI_l2_icm", "IC_refill_from_system", 0x0 }, \
|
||||
{ "PAPI_l2_ldm", "DC_refill_from_system", 0xe }, \
|
||||
{ "PAPI_l2_stm", "DC_refill_from_system", 0x10 }, \
|
||||
{ "PAPI_res_stl", "FR_dispatch_stalls", 0x0 }, \
|
||||
{ "PAPI_stl_icy", "FR_nothing_to_dispatch", 0x0 }, \
|
||||
{ "PAPI_hw_int", "FR_taken_hardware_intrs", 0x0 }
|
||||
|
||||
#define OPT_cmn_generic_events \
|
||||
{ "PAPI_tlb_dm", "DC_dtlb_L1_miss_L2_miss", 0x0 }, \
|
||||
{ "PAPI_tlb_im", "IC_itlb_L1_miss_L2_miss", 0x0 }, \
|
||||
{ "PAPI_fp_ins", "FR_retired_fpu_instr", 0xd }, \
|
||||
{ "PAPI_vec_ins", "FR_retired_fpu_instr", 0x4 }
|
||||
|
||||
#define AMD_FAMILY_10h_generic_events \
|
||||
{ "PAPI_tlb_dm", "DC_dtlb_L1_miss_L2_miss", 0x7 }, \
|
||||
{ "PAPI_tlb_im", "IC_itlb_L1_miss_L2_miss", 0x3 }, \
|
||||
{ "PAPI_l3_dcr", "L3_read_req", 0xf1 }, \
|
||||
{ "PAPI_l3_icr", "L3_read_req", 0xf2 }, \
|
||||
{ "PAPI_l3_tcr", "L3_read_req", 0xf7 }, \
|
||||
{ "PAPI_l3_stm", "L3_miss", 0xf4 }, \
|
||||
{ "PAPI_l3_ldm", "L3_miss", 0xf3 }, \
|
||||
{ "PAPI_l3_tcm", "L3_miss", 0xf7 }
|
||||
|
||||
static amd_event_t opt_events_rev_E[] = {
|
||||
AMD_cmn_events,
|
||||
OPT_events,
|
||||
OPT_RevD_events,
|
||||
OPT_RevE_events,
|
||||
EV_END
|
||||
};
|
||||
|
||||
static amd_event_t family_10h_events[] = {
|
||||
AMD_cmn_events,
|
||||
OPT_RevE_events,
|
||||
AMD_FAMILY_10h_cmn_events,
|
||||
EV_END
|
||||
};
|
||||
|
||||
static amd_generic_event_t opt_generic_events[] = {
|
||||
AMD_cmn_generic_events,
|
||||
OPT_cmn_generic_events,
|
||||
GEN_EV_END
|
||||
};
|
||||
|
||||
static amd_generic_event_t family_10h_generic_events[] = {
|
||||
AMD_cmn_generic_events,
|
||||
AMD_FAMILY_10h_generic_events,
|
||||
GEN_EV_END
|
||||
};
|
||||
|
||||
static amd_event_t *amd_events = NULL;
|
||||
static uint_t amd_family;
|
||||
static amd_generic_event_t *amd_generic_events = NULL;
|
||||
|
||||
#define BITS(v, u, l) (((v) >> (l)) & ((1 << (1 + (u) - (l))) - 1))
|
||||
#define OPTERON_FAMILY 0x0f
|
||||
#define AMD_FAMILY_10H 0x10
|
||||
|
||||
static int
|
||||
opt_pcbe_init (void)
|
||||
{
|
||||
amd_family = cpuid_getfamily ();
|
||||
/*
|
||||
* Make sure this really _is_ an Opteron or Athlon 64 system. The kernel
|
||||
* loads this module based on its name in the module directory, but it
|
||||
* could have been renamed.
|
||||
*/
|
||||
if (cpuid_getvendor () != X86_VENDOR_AMD
|
||||
|| (amd_family != OPTERON_FAMILY && amd_family != AMD_FAMILY_10H))
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Figure out processor revision here and assign appropriate
|
||||
* event configuration.
|
||||
*/
|
||||
if (amd_family == OPTERON_FAMILY)
|
||||
{
|
||||
amd_events = opt_events_rev_E;
|
||||
amd_generic_events = opt_generic_events;
|
||||
}
|
||||
else
|
||||
{
|
||||
amd_events = family_10h_events;
|
||||
amd_generic_events = family_10h_generic_events;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint_t
|
||||
opt_pcbe_ncounters (void)
|
||||
{
|
||||
return (4);
|
||||
}
|
||||
|
||||
static const char *
|
||||
opt_pcbe_impl_name (void)
|
||||
{
|
||||
if (amd_family == OPTERON_FAMILY)
|
||||
return ("AMD Opteron & Athlon64");
|
||||
else if (amd_family == AMD_FAMILY_10H)
|
||||
return ("AMD Family 10h");
|
||||
else
|
||||
return ("Unknown AMD processor");
|
||||
}
|
||||
|
||||
static const char *
|
||||
opt_pcbe_cpuref (void)
|
||||
{
|
||||
if (amd_family == OPTERON_FAMILY)
|
||||
return GTXT ("See Chapter 10 of the \"BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD Opteron Processors,\"\nAMD publication #26094");
|
||||
else if (amd_family == AMD_FAMILY_10H)
|
||||
return GTXT ("See section 3.15 of the \"BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h Processors,\"\nAMD publication #31116");
|
||||
else
|
||||
return GTXT ("Unknown AMD processor");
|
||||
}
|
||||
|
||||
static int
|
||||
opt_pcbe_get_events (hwcf_hwc_cb_t *hwc_cb)
|
||||
{
|
||||
int count = 0;
|
||||
for (uint_t kk = 0; amd_events && amd_events[kk].name; kk++)
|
||||
for (uint_t jj = 0; jj < opt_pcbe_ncounters (); jj++)
|
||||
{
|
||||
hwc_cb (jj, amd_events[kk].name);
|
||||
count++;
|
||||
}
|
||||
for (uint_t kk = 0; amd_generic_events && amd_generic_events[kk].name; kk++)
|
||||
for (uint_t jj = 0; jj < opt_pcbe_ncounters (); jj++)
|
||||
{
|
||||
hwc_cb (jj, amd_generic_events[kk].name);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
opt_pcbe_get_eventnum (const char *eventname, uint_t pmc, eventsel_t *eventsel,
|
||||
eventsel_t *event_valid_umask, uint_t *pmc_sel)
|
||||
{
|
||||
uint_t kk;
|
||||
*pmc_sel = pmc; /* for AMD, pmc doesn't need to be adjusted */
|
||||
*eventsel = (eventsel_t) - 1;
|
||||
*event_valid_umask = 0x0;
|
||||
|
||||
/* search table */
|
||||
for (kk = 0; amd_events && amd_events[kk].name; kk++)
|
||||
{
|
||||
if (strcmp (eventname, amd_events[kk].name) == 0)
|
||||
{
|
||||
*eventsel = EXTENDED_EVNUM_2_EVSEL (amd_events[kk].emask);
|
||||
*event_valid_umask = amd_events[kk].umask_valid;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* search generic */
|
||||
int generic = 0;
|
||||
eventsel_t tmp_umask = 0;
|
||||
for (kk = 0; amd_generic_events && amd_generic_events[kk].name; kk++)
|
||||
{
|
||||
if (strcmp (eventname, amd_generic_events[kk].name) == 0)
|
||||
{
|
||||
generic = 1;
|
||||
eventname = amd_generic_events[kk].event;
|
||||
tmp_umask = amd_generic_events[kk].umask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!generic)
|
||||
return -1;
|
||||
|
||||
/* find real event # for generic event */
|
||||
for (kk = 0; amd_events && amd_events[kk].name; kk++)
|
||||
{
|
||||
if (strcmp (eventname, amd_events[kk].name) == 0)
|
||||
{
|
||||
*eventsel = EXTENDED_EVNUM_2_EVSEL (amd_events[kk].emask);
|
||||
*eventsel |= (tmp_umask << PERFCTR_UMASK_SHIFT);
|
||||
*event_valid_umask = 0; /* user umask not allowed w/generic events */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static hdrv_pcbe_api_t hdrv_pcbe_opteron_api = {
|
||||
opt_pcbe_init,
|
||||
opt_pcbe_ncounters,
|
||||
opt_pcbe_impl_name,
|
||||
opt_pcbe_cpuref,
|
||||
opt_pcbe_get_events,
|
||||
opt_pcbe_get_eventnum
|
||||
};
|
92
gprofng/config/bison.m4
Normal file
92
gprofng/config/bison.m4
Normal file
|
@ -0,0 +1,92 @@
|
|||
# serial 10
|
||||
|
||||
# Copyright (C) 2002-2006, 2008-2021 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# There are two types of parser skeletons:
|
||||
#
|
||||
# * Those that can be used with any Yacc implementation, including bison.
|
||||
# For these, in the configure.ac, up to Autoconf 2.69, you could use
|
||||
# AC_PROG_YACC
|
||||
# In newer Autoconf versions, however, this macro is broken. See
|
||||
# https://lists.gnu.org/archive/html/autoconf-patches/2013-03/msg00000.html
|
||||
# https://lists.gnu.org/archive/html/bug-autoconf/2018-12/msg00001.html
|
||||
# In the Makefile.am you could use
|
||||
# $(SHELL) $(YLWRAP) $(srcdir)/foo.y \
|
||||
# y.tab.c foo.c \
|
||||
# y.tab.h foo.h \
|
||||
# y.output foo.output \
|
||||
# -- $(YACC) $(YFLAGS) $(AM_YFLAGS)
|
||||
# or similar.
|
||||
#
|
||||
# * Those that make use of Bison extensions. For example,
|
||||
# - %define api.pure requires bison 2.7 or newer,
|
||||
# - %precedence requires bison 3.0 or newer.
|
||||
# For these, in the configure.ac you will need an invocation of
|
||||
# gl_PROG_BISON([VARIABLE], [MIN_BISON_VERSION])
|
||||
# Example:
|
||||
# gl_PROG_BISON([PARSE_DATETIME_BISON], [2.4])
|
||||
# With this preparation, in the Makefile.am there are two ways to formulate
|
||||
# the invocation. Both are direct, without use of 'ylwrap'.
|
||||
# (a) You can invoke
|
||||
# $(VARIABLE) -d $(SOME_BISON_OPTIONS) --output foo.c $(srcdir)/foo.y
|
||||
# or similar.
|
||||
# (b) If you want the invocation to honor an YFLAGS=... parameter passed to
|
||||
# 'configure' or an YFLAGS environment variable present at 'configure'
|
||||
# time, add an invocation of gl_BISON to the configure.ac, and write
|
||||
# $(VARIABLE) -d $(YFLAGS) $(AM_YFLAGS) $(srcdir)/foo.y
|
||||
# or similar.
|
||||
|
||||
# This macro defines the autoconf variable VARIABLE to 'bison' if the specified
|
||||
# minimum version of bison is found in $PATH, or to ':' otherwise.
|
||||
AC_DEFUN([gl_PROG_BISON],
|
||||
[
|
||||
AC_CHECK_PROGS([$1], [bison])
|
||||
if test -z "$[$1]"; then
|
||||
ac_verc_fail=yes
|
||||
else
|
||||
cat >conftest.y <<_ACEOF
|
||||
%require "$2"
|
||||
%%
|
||||
exp:
|
||||
_ACEOF
|
||||
AC_MSG_CHECKING([for bison $2 or newer])
|
||||
ac_prog_version=`$$1 --version 2>&1 | sed -n 's/^.*GNU Bison.* \([[0-9]]*\.[[0-9.]]*\).*$/\1/p'`
|
||||
: ${ac_prog_version:='v. ?.??'}
|
||||
if $$1 conftest.y -o conftest.c 2>/dev/null; then
|
||||
ac_prog_version="$ac_prog_version, ok"
|
||||
ac_verc_fail=no
|
||||
else
|
||||
ac_prog_version="$ac_prog_version, bad"
|
||||
ac_verc_fail=yes
|
||||
fi
|
||||
rm -f conftest.y conftest.c
|
||||
AC_MSG_RESULT([$ac_prog_version])
|
||||
fi
|
||||
if test $ac_verc_fail = yes; then
|
||||
[$1]=:
|
||||
fi
|
||||
AC_SUBST([$1])
|
||||
])
|
||||
|
||||
# This macro sets the autoconf variables YACC (for old-style yacc Makefile
|
||||
# rules) and YFLAGS (to allow options to be passed as 'configure' time).
|
||||
AC_DEFUN([gl_BISON],
|
||||
[
|
||||
: ${YACC='bison -o y.tab.c'}
|
||||
dnl
|
||||
dnl Declaring YACC & YFLAGS precious will not be necessary after GNULIB
|
||||
dnl requires an Autoconf greater than 2.59c, but it will probably still be
|
||||
dnl useful to override the description of YACC in the --help output, re
|
||||
dnl parse-datetime.y assuming 'bison -o y.tab.c'.
|
||||
AC_ARG_VAR([YACC],
|
||||
[The "Yet Another C Compiler" implementation to use. Defaults to
|
||||
'bison -o y.tab.c'. Values other than 'bison -o y.tab.c' will most likely
|
||||
break on most systems.])dnl
|
||||
AC_ARG_VAR([YFLAGS],
|
||||
[YFLAGS contains the list arguments that will be passed by default to Bison.
|
||||
This script will default YFLAGS to the empty string to avoid a default value of
|
||||
'-d' given by some make applications.])dnl
|
||||
])
|
19350
gprofng/configure
vendored
Executable file
19350
gprofng/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
189
gprofng/configure.ac
Normal file
189
gprofng/configure.ac
Normal file
|
@ -0,0 +1,189 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl This file is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 3 of the License, or
|
||||
dnl (at your option) any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
dnl GNU General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; see the file COPYING3. If not see
|
||||
dnl <http://www.gnu.org/licenses/>.
|
||||
|
||||
m4_include([../bfd/version.m4])
|
||||
AC_INIT([gprofng], BFD_VERSION)
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
AM_PROG_AR
|
||||
|
||||
AC_DISABLE_SHARED
|
||||
LT_INIT
|
||||
|
||||
GPROFNG_LIBADD="-L../../libiberty -liberty"
|
||||
if test "$enable_shared" = "yes"; then
|
||||
GPROFNG_LIBADD="-L../../libiberty/pic -liberty"
|
||||
fi
|
||||
AC_SUBST(GPROFNG_LIBADD)
|
||||
|
||||
# Figure out what compiler warnings we can enable.
|
||||
# See config/warnings.m4 for details.
|
||||
|
||||
ACX_PROG_CC_WARNINGS_ARE_ERRORS([manual])
|
||||
ACX_PROG_CC_WARNING_OPTS([-Wall], [gprofng_cflags])
|
||||
gprofng_cppflags="-U_ASM"
|
||||
build_collector=
|
||||
build_src=
|
||||
|
||||
# This is annoying: it means we have to pass --enable-shared explicitly to
|
||||
# get gprofng, while the configure default is supposed to be that shared libs
|
||||
# are on by default. But as long as libiberty has code like this, so must
|
||||
# we...
|
||||
|
||||
case "${target}" in
|
||||
x86_64-*-linux*)
|
||||
build_src=true
|
||||
build_collector=true
|
||||
;;
|
||||
i?86-*-linux*)
|
||||
build_collector=true
|
||||
build_collector=true
|
||||
;;
|
||||
aarch64-*-linux*)
|
||||
build_src=true
|
||||
build_collector=true
|
||||
;;
|
||||
esac
|
||||
AC_ARG_ENABLE(gprofng-tools,
|
||||
AS_HELP_STRING([--disable-gprofng-tools], [do not build gprofng/src directory]),
|
||||
build_src=$enableval)
|
||||
|
||||
AM_CONDITIONAL([BUILD_COLLECTOR], [test x$build_collector = xtrue])
|
||||
AM_CONDITIONAL([BUILD_SRC], [test x$build_src = xtrue])
|
||||
|
||||
run_tests=false
|
||||
if test x$build_collector = xtrue; then
|
||||
AC_CONFIG_SUBDIRS([libcollector])
|
||||
if test x${host} = x${target}; then
|
||||
run_tests=true
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([RUN_TESTS], [test x$run_tests = xtrue])
|
||||
AX_PTHREAD
|
||||
|
||||
# Specify a location for JDK
|
||||
enable_gprofng_jp=
|
||||
jdk_inc=
|
||||
AC_ARG_WITH(jdk,
|
||||
[AS_HELP_STRING([--with-jdk=PATH],
|
||||
[specify prefix directory for installed JDK.])])
|
||||
|
||||
if test "x$with_jdk" != x; then
|
||||
jdk_inc="-I$with_jdk/include -I$with_jdk/include/linux"
|
||||
enable_gprofng_jp=yes
|
||||
else
|
||||
AC_PATH_PROG([JAVAC], [javac], [javac])
|
||||
if test -f $JAVAC; then
|
||||
x=`readlink -f $JAVAC`
|
||||
x=`dirname $x`
|
||||
x=`dirname $x`
|
||||
if ! test -f $x/include/jni.h; then
|
||||
x=`dirname $x`
|
||||
fi
|
||||
if test -f $x/include/jni.h; then
|
||||
jdk_inc="-I$x/include -I$x/include/linux"
|
||||
enable_gprofng_jp=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_gprofng_jp" = x; then
|
||||
AC_PATH_PROG([JAVA], [java], [java])
|
||||
if test -f $JAVA; then
|
||||
x=`readlink -f $JAVA`
|
||||
x=`dirname $x`
|
||||
x=`dirname $x`
|
||||
if ! test -f $x/include/jni.h; then
|
||||
x=`dirname $x`
|
||||
fi
|
||||
if test -f $x/include/jni.h; then
|
||||
jdk_inc="-I$x/include -I$x/include/linux"
|
||||
enable_gprofng_jp=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_gprofng_jp" = x; then
|
||||
AC_CHECK_HEADER([jni.h], [ enable_gprofng_jp=yes ], [], [] )
|
||||
fi
|
||||
if test "x$enable_gprofng_jp" = x; then
|
||||
AC_MSG_WARN([ Cannot find the JDK include directory.
|
||||
gprofng will be build without support for profiling Java applications.
|
||||
Use --with-jdk=PATH to specify directory for the installed JDK])
|
||||
else
|
||||
AC_DEFINE(GPROFNG_JAVA_PROFILING, 1, [Enable java profiling])
|
||||
fi
|
||||
AC_SUBST(jdk_inc)
|
||||
|
||||
DEBUG=
|
||||
GCC_ENABLE([gprofng-debug], [no], [], [Enable debugging output])
|
||||
if test "${enable_gprofng_debug}" = yes; then
|
||||
AC_DEFINE(DEBUG, 1, [Enable debugging output.])
|
||||
fi
|
||||
|
||||
# Check if linker supports --as-needed and --no-as-needed options.
|
||||
AC_CACHE_CHECK(linker --as-needed support, bfd_cv_ld_as_needed,
|
||||
[bfd_cv_ld_as_needed=no
|
||||
if $LD --help 2>/dev/null | grep as-needed > /dev/null; then
|
||||
bfd_cv_ld_as_needed=yes
|
||||
fi
|
||||
])
|
||||
|
||||
no_as_needed=
|
||||
if test x"$bfd_cv_ld_as_needed" = xyes; then
|
||||
no_as_needed='-Wl,--no-as-needed'
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([EXPECT], [expect])
|
||||
AC_CACHE_CHECK([for Tcl supporting try/catch], [ac_cv_libctf_tcl_try],
|
||||
[ac_cv_libctf_tcl_try=`if test -z $EXPECT; then echo no; else $EXPECT << EOF
|
||||
if @<:@llength @<:@info commands try@:>@@:>@ then { puts yes } else { puts no }
|
||||
EOF
|
||||
fi`
|
||||
])
|
||||
AM_CONDITIONAL(TCL_TRY, test "${ac_cv_libctf_tcl_try}" = yes)
|
||||
|
||||
|
||||
# Generate manpages, if possible.
|
||||
if test $cross_compiling = no; then
|
||||
AM_MISSING_PROG(HELP2MAN, help2man)
|
||||
build_man=true
|
||||
else
|
||||
build_man=false
|
||||
fi
|
||||
AM_CONDITIONAL([BUILD_MAN], [test x$build_man = xtrue])
|
||||
|
||||
AC_SUBST(LD_NO_AS_NEEDED, [${no_as_needed}])
|
||||
AC_SUBST(GPROFNG_CFLAGS, [${gprofng_cflags}])
|
||||
AC_SUBST(GPROFNG_CPPFLAGS, [${gprofng_cppflags}])
|
||||
AC_SUBST(GPROFNG_LIBDIR, [${libdir}])
|
||||
|
||||
AC_CHECK_DECLS([basename])
|
||||
AC_CHECK_FUNCS([strsignal])
|
||||
|
||||
AC_SUBST(BUILD_SUBDIRS)
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile gp-display-html/Makefile doc/Makefile])
|
||||
AC_CONFIG_HEADERS([config.h:common/config.h.in])
|
||||
|
||||
AC_OUTPUT
|
||||
|
37
gprofng/doc/Makefile.am
Normal file
37
gprofng/doc/Makefile.am
Normal file
|
@ -0,0 +1,37 @@
|
|||
## Process this file with automake to generate Makefile.in
|
||||
#
|
||||
# Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign no-texinfo.tex
|
||||
|
||||
info_TEXINFOS = gprofng.texi
|
||||
gprofng_TEXINFOS = fdl.texi
|
||||
BUILT_SOURCES = version.texi
|
||||
CLEANFILES = version.texi
|
||||
TEXINFO_TEX = .
|
||||
MAKEINFOHTML = $(MAKEINFO) --html --no-split
|
||||
|
||||
version.texi:
|
||||
@echo "@set EDITION 1.0" > $@
|
||||
@echo "@set VERSION 1.0" >> $@
|
||||
@echo "@set UPDATED 22 February 2022" >> $@
|
||||
@echo "@set UPDATED-MONTH February 2022" >> $@
|
||||
# @echo "@set UPDATED `date +"%-d %B %Y"`" >> $@
|
||||
# @echo "@set UPDATED-MONTH `date +"%B %Y"`" >> $@
|
||||
|
||||
MAINTAINERCLEANFILES = gprofng.info
|
834
gprofng/doc/Makefile.in
Normal file
834
gprofng/doc/Makefile.in
Normal file
|
@ -0,0 +1,834 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
#
|
||||
# Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = doc
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \
|
||||
$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
|
||||
$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/../config/warnings.m4 \
|
||||
$(top_srcdir)/../config/enable.m4 \
|
||||
$(top_srcdir)/../config/ax_pthread.m4 \
|
||||
$(top_srcdir)/config/bison.m4 $(top_srcdir)/../bfd/version.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/version.texi \
|
||||
$(srcdir)/stamp-vti $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
AM_V_DVIPS = $(am__v_DVIPS_@AM_V@)
|
||||
am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@)
|
||||
am__v_DVIPS_0 = @echo " DVIPS " $@;
|
||||
am__v_DVIPS_1 =
|
||||
AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@)
|
||||
am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@)
|
||||
am__v_MAKEINFO_0 = @echo " MAKEINFO" $@;
|
||||
am__v_MAKEINFO_1 =
|
||||
AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@)
|
||||
am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@)
|
||||
am__v_INFOHTML_0 = @echo " INFOHTML" $@;
|
||||
am__v_INFOHTML_1 =
|
||||
AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@)
|
||||
am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@)
|
||||
am__v_TEXI2DVI_0 = @echo " TEXI2DVI" $@;
|
||||
am__v_TEXI2DVI_1 =
|
||||
AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@)
|
||||
am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@)
|
||||
am__v_TEXI2PDF_0 = @echo " TEXI2PDF" $@;
|
||||
am__v_TEXI2PDF_1 =
|
||||
AM_V_texinfo = $(am__v_texinfo_@AM_V@)
|
||||
am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@)
|
||||
am__v_texinfo_0 = -q
|
||||
am__v_texinfo_1 =
|
||||
AM_V_texidevnull = $(am__v_texidevnull_@AM_V@)
|
||||
am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@)
|
||||
am__v_texidevnull_0 = > /dev/null
|
||||
am__v_texidevnull_1 =
|
||||
INFO_DEPS = $(srcdir)/gprofng.info
|
||||
am__TEXINFO_TEX_DIR = $(srcdir)/.
|
||||
DVIS = gprofng.dvi
|
||||
PDFS = gprofng.pdf
|
||||
PSS = gprofng.ps
|
||||
HTMLS = gprofng.html
|
||||
TEXINFOS = gprofng.texi
|
||||
TEXI2DVI = texi2dvi
|
||||
TEXI2PDF = $(TEXI2DVI) --pdf --batch
|
||||
AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS)
|
||||
DVIPS = dvips
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__installdirs = "$(DESTDIR)$(infodir)"
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
am__DIST_COMMON = $(gprofng_TEXINFOS) $(srcdir)/Makefile.in \
|
||||
$(top_srcdir)/../mkinstalldirs mdate-sh texinfo.tex
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_SUBDIRS = @BUILD_SUBDIRS@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
EXPECT = @EXPECT@
|
||||
FGREP = @FGREP@
|
||||
GPROFNG_CFLAGS = @GPROFNG_CFLAGS@
|
||||
GPROFNG_CPPFLAGS = @GPROFNG_CPPFLAGS@
|
||||
GPROFNG_LIBADD = @GPROFNG_LIBADD@
|
||||
GPROFNG_LIBDIR = @GPROFNG_LIBDIR@
|
||||
GREP = @GREP@
|
||||
HELP2MAN = @HELP2MAN@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
JAVA = @JAVA@
|
||||
JAVAC = @JAVAC@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LD_NO_AS_NEEDED = @LD_NO_AS_NEEDED@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
WERROR = @WERROR@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
ax_pthread_config = @ax_pthread_config@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
gprofng_cflags = @gprofng_cflags@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
jdk_inc = @jdk_inc@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign no-texinfo.tex
|
||||
info_TEXINFOS = gprofng.texi
|
||||
gprofng_TEXINFOS = fdl.texi
|
||||
BUILT_SOURCES = version.texi
|
||||
CLEANFILES = version.texi
|
||||
TEXINFO_TEX = .
|
||||
MAKEINFOHTML = $(MAKEINFO) --html --no-split
|
||||
# @echo "@set UPDATED `date +"%-d %B %Y"`" >> $@
|
||||
# @echo "@set UPDATED-MONTH `date +"%B %Y"`" >> $@
|
||||
MAINTAINERCLEANFILES = gprofng.info
|
||||
all: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .dvi .html .info .pdf .ps .texi
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign doc/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
.texi.info:
|
||||
$(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \
|
||||
am__cwd=`pwd` && $(am__cd) $(srcdir) && \
|
||||
rm -rf $$backupdir && mkdir $$backupdir && \
|
||||
if ($(MAKEINFO) --version) >/dev/null 2>&1; then \
|
||||
for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
|
||||
if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
|
||||
done; \
|
||||
else :; fi && \
|
||||
cd "$$am__cwd"; \
|
||||
if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
||||
-o $@ $<; \
|
||||
then \
|
||||
rc=0; \
|
||||
$(am__cd) $(srcdir); \
|
||||
else \
|
||||
rc=$$?; \
|
||||
$(am__cd) $(srcdir) && \
|
||||
$$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
|
||||
fi; \
|
||||
rm -rf $$backupdir; exit $$rc
|
||||
|
||||
.texi.dvi:
|
||||
$(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||
$(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \
|
||||
$<
|
||||
|
||||
.texi.pdf:
|
||||
$(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||
$(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \
|
||||
$<
|
||||
|
||||
.texi.html:
|
||||
$(AM_V_MAKEINFO)rm -rf $(@:.html=.htp)
|
||||
$(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
||||
-o $(@:.html=.htp) $<; \
|
||||
then \
|
||||
rm -rf $@ && mv $(@:.html=.htp) $@; \
|
||||
else \
|
||||
rm -rf $(@:.html=.htp); exit 1; \
|
||||
fi
|
||||
$(srcdir)/gprofng.info: gprofng.texi $(srcdir)/version.texi $(gprofng_TEXINFOS)
|
||||
gprofng.dvi: gprofng.texi $(srcdir)/version.texi $(gprofng_TEXINFOS)
|
||||
gprofng.pdf: gprofng.texi $(srcdir)/version.texi $(gprofng_TEXINFOS)
|
||||
gprofng.html: gprofng.texi $(srcdir)/version.texi $(gprofng_TEXINFOS)
|
||||
$(srcdir)/version.texi: @MAINTAINER_MODE_TRUE@ $(srcdir)/stamp-vti
|
||||
$(srcdir)/stamp-vti: gprofng.texi $(top_srcdir)/configure
|
||||
@(dir=.; test -f ./gprofng.texi || dir=$(srcdir); \
|
||||
set `$(SHELL) $(srcdir)/mdate-sh $$dir/gprofng.texi`; \
|
||||
echo "@set UPDATED $$1 $$2 $$3"; \
|
||||
echo "@set UPDATED-MONTH $$2 $$3"; \
|
||||
echo "@set EDITION $(VERSION)"; \
|
||||
echo "@set VERSION $(VERSION)") > vti.tmp$$$$ && \
|
||||
(cmp -s vti.tmp$$$$ $(srcdir)/version.texi \
|
||||
|| (echo "Updating $(srcdir)/version.texi" && \
|
||||
cp vti.tmp$$$$ $(srcdir)/version.texi.tmp$$$$ && \
|
||||
mv $(srcdir)/version.texi.tmp$$$$ $(srcdir)/version.texi)) && \
|
||||
rm -f vti.tmp$$$$ $(srcdir)/version.texi.$$$$
|
||||
@cp $(srcdir)/version.texi $@
|
||||
|
||||
mostlyclean-vti:
|
||||
-rm -f vti.tmp* $(srcdir)/version.texi.tmp*
|
||||
|
||||
maintainer-clean-vti:
|
||||
@MAINTAINER_MODE_TRUE@ -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi
|
||||
.dvi.ps:
|
||||
$(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||
$(DVIPS) $(AM_V_texinfo) -o $@ $<
|
||||
|
||||
uninstall-dvi-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(DVIS)'; test -n "$(dvidir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(dvidir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-html-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(HTMLS)'; test -n "$(htmldir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \
|
||||
rm -rf "$(DESTDIR)$(htmldir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-info-am:
|
||||
@$(PRE_UNINSTALL)
|
||||
@if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \
|
||||
list='$(INFO_DEPS)'; \
|
||||
for file in $$list; do \
|
||||
relfile=`echo "$$file" | sed 's|^.*/||'`; \
|
||||
echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \
|
||||
if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \
|
||||
then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \
|
||||
done; \
|
||||
else :; fi
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(INFO_DEPS)'; \
|
||||
for file in $$list; do \
|
||||
relfile=`echo "$$file" | sed 's|^.*/||'`; \
|
||||
relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
(if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \
|
||||
echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \
|
||||
rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
|
||||
else :; fi); \
|
||||
done
|
||||
|
||||
uninstall-pdf-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(pdfdir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-ps-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(PSS)'; test -n "$(psdir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(psdir)/$$f"; \
|
||||
done
|
||||
|
||||
dist-info: $(INFO_DEPS)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(INFO_DEPS)'; \
|
||||
for base in $$list; do \
|
||||
case $$base in \
|
||||
$(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
esac; \
|
||||
if test -f $$base; then d=.; else d=$(srcdir); fi; \
|
||||
base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \
|
||||
if test -f $$file; then \
|
||||
relfile=`expr "$$file" : "$$d/\(.*\)"`; \
|
||||
test -f "$(distdir)/$$relfile" || \
|
||||
cp -p $$file "$(distdir)/$$relfile"; \
|
||||
else :; fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
mostlyclean-aminfo:
|
||||
-rm -rf gprofng.t2d gprofng.t2p
|
||||
|
||||
clean-aminfo:
|
||||
-test -z "gprofng.dvi gprofng.pdf gprofng.ps gprofng.html" \
|
||||
|| rm -rf gprofng.dvi gprofng.pdf gprofng.ps gprofng.html
|
||||
|
||||
maintainer-clean-aminfo:
|
||||
@list='$(INFO_DEPS)'; for i in $$list; do \
|
||||
i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
|
||||
rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
|
||||
done
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$(top_distdir)" distdir="$(distdir)" \
|
||||
dist-info
|
||||
check-am: all-am
|
||||
check: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-am
|
||||
all-am: Makefile $(INFO_DEPS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(infodir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-aminfo clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am: $(DVIS)
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am: $(HTMLS)
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am: $(INFO_DEPS)
|
||||
|
||||
install-data-am: install-info-am
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am: $(DVIS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(DVIS)'; test -n "$(dvidir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \
|
||||
done
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am: $(HTMLS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
$(am__strip_dir) \
|
||||
d2=$$d$$p; \
|
||||
if test -d "$$d2"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
|
||||
echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \
|
||||
$(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \
|
||||
else \
|
||||
list2="$$list2 $$d2"; \
|
||||
fi; \
|
||||
done; \
|
||||
test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
|
||||
done; }
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am: $(INFO_DEPS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \
|
||||
fi; \
|
||||
for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
esac; \
|
||||
if test -f $$file; then d=.; else d=$(srcdir); fi; \
|
||||
file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \
|
||||
$$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \
|
||||
if test -f $$ifile; then \
|
||||
echo "$$ifile"; \
|
||||
else : ; fi; \
|
||||
done; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done
|
||||
@$(POST_INSTALL)
|
||||
@if $(am__can_run_installinfo); then \
|
||||
list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
|
||||
for file in $$list; do \
|
||||
relfile=`echo "$$file" | sed 's|^.*/||'`; \
|
||||
echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\
|
||||
install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
|
||||
done; \
|
||||
else : ; fi
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am: $(PDFS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am: $(PSS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(PSS)'; test -n "$(psdir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-aminfo \
|
||||
maintainer-clean-generic maintainer-clean-vti
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-aminfo mostlyclean-generic \
|
||||
mostlyclean-libtool mostlyclean-vti
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am: $(PDFS)
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am: $(PSS)
|
||||
|
||||
uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
|
||||
uninstall-pdf-am uninstall-ps-am
|
||||
|
||||
.MAKE: all check install install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-aminfo clean-generic \
|
||||
clean-libtool cscopelist-am ctags-am dist-info distclean \
|
||||
distclean-generic distclean-libtool distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-aminfo maintainer-clean-generic \
|
||||
maintainer-clean-vti mostlyclean mostlyclean-aminfo \
|
||||
mostlyclean-generic mostlyclean-libtool mostlyclean-vti pdf \
|
||||
pdf-am ps ps-am tags-am uninstall uninstall-am \
|
||||
uninstall-dvi-am uninstall-html-am uninstall-info-am \
|
||||
uninstall-pdf-am uninstall-ps-am
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
version.texi:
|
||||
@echo "@set EDITION 1.0" > $@
|
||||
@echo "@set VERSION 1.0" >> $@
|
||||
@echo "@set UPDATED 22 February 2022" >> $@
|
||||
@echo "@set UPDATED-MONTH February 2022" >> $@
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
506
gprofng/doc/fdl.texi
Normal file
506
gprofng/doc/fdl.texi
Normal file
|
@ -0,0 +1,506 @@
|
|||
@c The GNU Free Documentation License.
|
||||
@center Version 1.3, 3 November 2008
|
||||
|
||||
@c This file is intended to be included within another document,
|
||||
@c hence no sectioning command or @node.
|
||||
|
||||
@display
|
||||
Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
|
||||
@uref{http://fsf.org/}
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
@end display
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
PREAMBLE
|
||||
|
||||
The purpose of this License is to make a manual, textbook, or other
|
||||
functional and useful document @dfn{free} in the sense of freedom: to
|
||||
assure everyone the effective freedom to copy and redistribute it,
|
||||
with or without modifying it, either commercially or noncommercially.
|
||||
Secondarily, this License preserves for the author and publisher a way
|
||||
to get credit for their work, while not being considered responsible
|
||||
for modifications made by others.
|
||||
|
||||
This License is a kind of ``copyleft'', which means that derivative
|
||||
works of the document must themselves be free in the same sense. It
|
||||
complements the GNU General Public License, which is a copyleft
|
||||
license designed for free software.
|
||||
|
||||
We have designed this License in order to use it for manuals for free
|
||||
software, because free software needs free documentation: a free
|
||||
program should come with manuals providing the same freedoms that the
|
||||
software does. But this License is not limited to software manuals;
|
||||
it can be used for any textual work, regardless of subject matter or
|
||||
whether it is published as a printed book. We recommend this License
|
||||
principally for works whose purpose is instruction or reference.
|
||||
|
||||
@item
|
||||
APPLICABILITY AND DEFINITIONS
|
||||
|
||||
This License applies to any manual or other work, in any medium, that
|
||||
contains a notice placed by the copyright holder saying it can be
|
||||
distributed under the terms of this License. Such a notice grants a
|
||||
world-wide, royalty-free license, unlimited in duration, to use that
|
||||
work under the conditions stated herein. The ``Document'', below,
|
||||
refers to any such manual or work. Any member of the public is a
|
||||
licensee, and is addressed as ``you''. You accept the license if you
|
||||
copy, modify or distribute the work in a way requiring permission
|
||||
under copyright law.
|
||||
|
||||
A ``Modified Version'' of the Document means any work containing the
|
||||
Document or a portion of it, either copied verbatim, or with
|
||||
modifications and/or translated into another language.
|
||||
|
||||
A ``Secondary Section'' is a named appendix or a front-matter section
|
||||
of the Document that deals exclusively with the relationship of the
|
||||
publishers or authors of the Document to the Document's overall
|
||||
subject (or to related matters) and contains nothing that could fall
|
||||
directly within that overall subject. (Thus, if the Document is in
|
||||
part a textbook of mathematics, a Secondary Section may not explain
|
||||
any mathematics.) The relationship could be a matter of historical
|
||||
connection with the subject or with related matters, or of legal,
|
||||
commercial, philosophical, ethical or political position regarding
|
||||
them.
|
||||
|
||||
The ``Invariant Sections'' are certain Secondary Sections whose titles
|
||||
are designated, as being those of Invariant Sections, in the notice
|
||||
that says that the Document is released under this License. If a
|
||||
section does not fit the above definition of Secondary then it is not
|
||||
allowed to be designated as Invariant. The Document may contain zero
|
||||
Invariant Sections. If the Document does not identify any Invariant
|
||||
Sections then there are none.
|
||||
|
||||
The ``Cover Texts'' are certain short passages of text that are listed,
|
||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||
the Document is released under this License. A Front-Cover Text may
|
||||
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||||
|
||||
A ``Transparent'' copy of the Document means a machine-readable copy,
|
||||
represented in a format whose specification is available to the
|
||||
general public, that is suitable for revising the document
|
||||
straightforwardly with generic text editors or (for images composed of
|
||||
pixels) generic paint programs or (for drawings) some widely available
|
||||
drawing editor, and that is suitable for input to text formatters or
|
||||
for automatic translation to a variety of formats suitable for input
|
||||
to text formatters. A copy made in an otherwise Transparent file
|
||||
format whose markup, or absence of markup, has been arranged to thwart
|
||||
or discourage subsequent modification by readers is not Transparent.
|
||||
An image format is not Transparent if used for any substantial amount
|
||||
of text. A copy that is not ``Transparent'' is called ``Opaque''.
|
||||
|
||||
Examples of suitable formats for Transparent copies include plain
|
||||
@sc{ascii} without markup, Texinfo input format, La@TeX{} input
|
||||
format, @acronym{SGML} or @acronym{XML} using a publicly available
|
||||
@acronym{DTD}, and standard-conforming simple @acronym{HTML},
|
||||
PostScript or @acronym{PDF} designed for human modification. Examples
|
||||
of transparent image formats include @acronym{PNG}, @acronym{XCF} and
|
||||
@acronym{JPG}. Opaque formats include proprietary formats that can be
|
||||
read and edited only by proprietary word processors, @acronym{SGML} or
|
||||
@acronym{XML} for which the @acronym{DTD} and/or processing tools are
|
||||
not generally available, and the machine-generated @acronym{HTML},
|
||||
PostScript or @acronym{PDF} produced by some word processors for
|
||||
output purposes only.
|
||||
|
||||
The ``Title Page'' means, for a printed book, the title page itself,
|
||||
plus such following pages as are needed to hold, legibly, the material
|
||||
this License requires to appear in the title page. For works in
|
||||
formats which do not have any title page as such, ``Title Page'' means
|
||||
the text near the most prominent appearance of the work's title,
|
||||
preceding the beginning of the body of the text.
|
||||
|
||||
The ``publisher'' means any person or entity that distributes copies
|
||||
of the Document to the public.
|
||||
|
||||
A section ``Entitled XYZ'' means a named subunit of the Document whose
|
||||
title either is precisely XYZ or contains XYZ in parentheses following
|
||||
text that translates XYZ in another language. (Here XYZ stands for a
|
||||
specific section name mentioned below, such as ``Acknowledgements'',
|
||||
``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
|
||||
of such a section when you modify the Document means that it remains a
|
||||
section ``Entitled XYZ'' according to this definition.
|
||||
|
||||
The Document may include Warranty Disclaimers next to the notice which
|
||||
states that this License applies to the Document. These Warranty
|
||||
Disclaimers are considered to be included by reference in this
|
||||
License, but only as regards disclaiming warranties: any other
|
||||
implication that these Warranty Disclaimers may have is void and has
|
||||
no effect on the meaning of this License.
|
||||
|
||||
@item
|
||||
VERBATIM COPYING
|
||||
|
||||
You may copy and distribute the Document in any medium, either
|
||||
commercially or noncommercially, provided that this License, the
|
||||
copyright notices, and the license notice saying this License applies
|
||||
to the Document are reproduced in all copies, and that you add no other
|
||||
conditions whatsoever to those of this License. You may not use
|
||||
technical measures to obstruct or control the reading or further
|
||||
copying of the copies you make or distribute. However, you may accept
|
||||
compensation in exchange for copies. If you distribute a large enough
|
||||
number of copies you must also follow the conditions in section 3.
|
||||
|
||||
You may also lend copies, under the same conditions stated above, and
|
||||
you may publicly display copies.
|
||||
|
||||
@item
|
||||
COPYING IN QUANTITY
|
||||
|
||||
If you publish printed copies (or copies in media that commonly have
|
||||
printed covers) of the Document, numbering more than 100, and the
|
||||
Document's license notice requires Cover Texts, you must enclose the
|
||||
copies in covers that carry, clearly and legibly, all these Cover
|
||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||
the back cover. Both covers must also clearly and legibly identify
|
||||
you as the publisher of these copies. The front cover must present
|
||||
the full title with all words of the title equally prominent and
|
||||
visible. You may add other material on the covers in addition.
|
||||
Copying with changes limited to the covers, as long as they preserve
|
||||
the title of the Document and satisfy these conditions, can be treated
|
||||
as verbatim copying in other respects.
|
||||
|
||||
If the required texts for either cover are too voluminous to fit
|
||||
legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||
pages.
|
||||
|
||||
If you publish or distribute Opaque copies of the Document numbering
|
||||
more than 100, you must either include a machine-readable Transparent
|
||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||
a computer-network location from which the general network-using
|
||||
public has access to download using public-standard network protocols
|
||||
a complete Transparent copy of the Document, free of added material.
|
||||
If you use the latter option, you must take reasonably prudent steps,
|
||||
when you begin distribution of Opaque copies in quantity, to ensure
|
||||
that this Transparent copy will remain thus accessible at the stated
|
||||
location until at least one year after the last time you distribute an
|
||||
Opaque copy (directly or through your agents or retailers) of that
|
||||
edition to the public.
|
||||
|
||||
It is requested, but not required, that you contact the authors of the
|
||||
Document well before redistributing any large number of copies, to give
|
||||
them a chance to provide you with an updated version of the Document.
|
||||
|
||||
@item
|
||||
MODIFICATIONS
|
||||
|
||||
You may copy and distribute a Modified Version of the Document under
|
||||
the conditions of sections 2 and 3 above, provided that you release
|
||||
the Modified Version under precisely this License, with the Modified
|
||||
Version filling the role of the Document, thus licensing distribution
|
||||
and modification of the Modified Version to whoever possesses a copy
|
||||
of it. In addition, you must do these things in the Modified Version:
|
||||
|
||||
@enumerate A
|
||||
@item
|
||||
Use in the Title Page (and on the covers, if any) a title distinct
|
||||
from that of the Document, and from those of previous versions
|
||||
(which should, if there were any, be listed in the History section
|
||||
of the Document). You may use the same title as a previous version
|
||||
if the original publisher of that version gives permission.
|
||||
|
||||
@item
|
||||
List on the Title Page, as authors, one or more persons or entities
|
||||
responsible for authorship of the modifications in the Modified
|
||||
Version, together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has fewer than five),
|
||||
unless they release you from this requirement.
|
||||
|
||||
@item
|
||||
State on the Title page the name of the publisher of the
|
||||
Modified Version, as the publisher.
|
||||
|
||||
@item
|
||||
Preserve all the copyright notices of the Document.
|
||||
|
||||
@item
|
||||
Add an appropriate copyright notice for your modifications
|
||||
adjacent to the other copyright notices.
|
||||
|
||||
@item
|
||||
Include, immediately after the copyright notices, a license notice
|
||||
giving the public permission to use the Modified Version under the
|
||||
terms of this License, in the form shown in the Addendum below.
|
||||
|
||||
@item
|
||||
Preserve in that license notice the full lists of Invariant Sections
|
||||
and required Cover Texts given in the Document's license notice.
|
||||
|
||||
@item
|
||||
Include an unaltered copy of this License.
|
||||
|
||||
@item
|
||||
Preserve the section Entitled ``History'', Preserve its Title, and add
|
||||
to it an item stating at least the title, year, new authors, and
|
||||
publisher of the Modified Version as given on the Title Page. If
|
||||
there is no section Entitled ``History'' in the Document, create one
|
||||
stating the title, year, authors, and publisher of the Document as
|
||||
given on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.
|
||||
|
||||
@item
|
||||
Preserve the network location, if any, given in the Document for
|
||||
public access to a Transparent copy of the Document, and likewise
|
||||
the network locations given in the Document for previous versions
|
||||
it was based on. These may be placed in the ``History'' section.
|
||||
You may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.
|
||||
|
||||
@item
|
||||
For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
|
||||
the Title of the section, and preserve in the section all the
|
||||
substance and tone of each of the contributor acknowledgements and/or
|
||||
dedications given therein.
|
||||
|
||||
@item
|
||||
Preserve all the Invariant Sections of the Document,
|
||||
unaltered in their text and in their titles. Section numbers
|
||||
or the equivalent are not considered part of the section titles.
|
||||
|
||||
@item
|
||||
Delete any section Entitled ``Endorsements''. Such a section
|
||||
may not be included in the Modified Version.
|
||||
|
||||
@item
|
||||
Do not retitle any existing section to be Entitled ``Endorsements'' or
|
||||
to conflict in title with any Invariant Section.
|
||||
|
||||
@item
|
||||
Preserve any Warranty Disclaimers.
|
||||
@end enumerate
|
||||
|
||||
If the Modified Version includes new front-matter sections or
|
||||
appendices that qualify as Secondary Sections and contain no material
|
||||
copied from the Document, you may at your option designate some or all
|
||||
of these sections as invariant. To do this, add their titles to the
|
||||
list of Invariant Sections in the Modified Version's license notice.
|
||||
These titles must be distinct from any other section titles.
|
||||
|
||||
You may add a section Entitled ``Endorsements'', provided it contains
|
||||
nothing but endorsements of your Modified Version by various
|
||||
parties---for example, statements of peer review or that the text has
|
||||
been approved by an organization as the authoritative definition of a
|
||||
standard.
|
||||
|
||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||
of Cover Texts in the Modified Version. Only one passage of
|
||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||
through arrangements made by) any one entity. If the Document already
|
||||
includes a cover text for the same cover, previously added by you or
|
||||
by arrangement made by the same entity you are acting on behalf of,
|
||||
you may not add another; but you may replace the old one, on explicit
|
||||
permission from the previous publisher that added the old one.
|
||||
|
||||
The author(s) and publisher(s) of the Document do not by this License
|
||||
give permission to use their names for publicity for or to assert or
|
||||
imply endorsement of any Modified Version.
|
||||
|
||||
@item
|
||||
COMBINING DOCUMENTS
|
||||
|
||||
You may combine the Document with other documents released under this
|
||||
License, under the terms defined in section 4 above for modified
|
||||
versions, provided that you include in the combination all of the
|
||||
Invariant Sections of all of the original documents, unmodified, and
|
||||
list them all as Invariant Sections of your combined work in its
|
||||
license notice, and that you preserve all their Warranty Disclaimers.
|
||||
|
||||
The combined work need only contain one copy of this License, and
|
||||
multiple identical Invariant Sections may be replaced with a single
|
||||
copy. If there are multiple Invariant Sections with the same name but
|
||||
different contents, make the title of each such section unique by
|
||||
adding at the end of it, in parentheses, the name of the original
|
||||
author or publisher of that section if known, or else a unique number.
|
||||
Make the same adjustment to the section titles in the list of
|
||||
Invariant Sections in the license notice of the combined work.
|
||||
|
||||
In the combination, you must combine any sections Entitled ``History''
|
||||
in the various original documents, forming one section Entitled
|
||||
``History''; likewise combine any sections Entitled ``Acknowledgements'',
|
||||
and any sections Entitled ``Dedications''. You must delete all
|
||||
sections Entitled ``Endorsements.''
|
||||
|
||||
@item
|
||||
COLLECTIONS OF DOCUMENTS
|
||||
|
||||
You may make a collection consisting of the Document and other documents
|
||||
released under this License, and replace the individual copies of this
|
||||
License in the various documents with a single copy that is included in
|
||||
the collection, provided that you follow the rules of this License for
|
||||
verbatim copying of each of the documents in all other respects.
|
||||
|
||||
You may extract a single document from such a collection, and distribute
|
||||
it individually under this License, provided you insert a copy of this
|
||||
License into the extracted document, and follow this License in all
|
||||
other respects regarding verbatim copying of that document.
|
||||
|
||||
@item
|
||||
AGGREGATION WITH INDEPENDENT WORKS
|
||||
|
||||
A compilation of the Document or its derivatives with other separate
|
||||
and independent documents or works, in or on a volume of a storage or
|
||||
distribution medium, is called an ``aggregate'' if the copyright
|
||||
resulting from the compilation is not used to limit the legal rights
|
||||
of the compilation's users beyond what the individual works permit.
|
||||
When the Document is included in an aggregate, this License does not
|
||||
apply to the other works in the aggregate which are not themselves
|
||||
derivative works of the Document.
|
||||
|
||||
If the Cover Text requirement of section 3 is applicable to these
|
||||
copies of the Document, then if the Document is less than one half of
|
||||
the entire aggregate, the Document's Cover Texts may be placed on
|
||||
covers that bracket the Document within the aggregate, or the
|
||||
electronic equivalent of covers if the Document is in electronic form.
|
||||
Otherwise they must appear on printed covers that bracket the whole
|
||||
aggregate.
|
||||
|
||||
@item
|
||||
TRANSLATION
|
||||
|
||||
Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section 4.
|
||||
Replacing Invariant Sections with translations requires special
|
||||
permission from their copyright holders, but you may include
|
||||
translations of some or all Invariant Sections in addition to the
|
||||
original versions of these Invariant Sections. You may include a
|
||||
translation of this License, and all the license notices in the
|
||||
Document, and any Warranty Disclaimers, provided that you also include
|
||||
the original English version of this License and the original versions
|
||||
of those notices and disclaimers. In case of a disagreement between
|
||||
the translation and the original version of this License or a notice
|
||||
or disclaimer, the original version will prevail.
|
||||
|
||||
If a section in the Document is Entitled ``Acknowledgements'',
|
||||
``Dedications'', or ``History'', the requirement (section 4) to Preserve
|
||||
its Title (section 1) will typically require changing the actual
|
||||
title.
|
||||
|
||||
@item
|
||||
TERMINATION
|
||||
|
||||
You may not copy, modify, sublicense, or distribute the Document
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense, or distribute it is void, and
|
||||
will automatically terminate your rights under this License.
|
||||
|
||||
However, if you cease all violation of this License, then your license
|
||||
from a particular copyright holder is reinstated (a) provisionally,
|
||||
unless and until the copyright holder explicitly and finally
|
||||
terminates your license, and (b) permanently, if the copyright holder
|
||||
fails to notify you of the violation by some reasonable means prior to
|
||||
60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, receipt of a copy of some or all of the same material does
|
||||
not give you any rights to use it.
|
||||
|
||||
@item
|
||||
FUTURE REVISIONS OF THIS LICENSE
|
||||
|
||||
The Free Software Foundation may publish new, revised versions
|
||||
of the GNU Free Documentation License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns. See
|
||||
@uref{http://www.gnu.org/copyleft/}.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
License ``or any later version'' applies to it, you have the option of
|
||||
following the terms and conditions either of that specified version or
|
||||
of any later version that has been published (not as a draft) by the
|
||||
Free Software Foundation. If the Document does not specify a version
|
||||
number of this License, you may choose any version ever published (not
|
||||
as a draft) by the Free Software Foundation. If the Document
|
||||
specifies that a proxy can decide which future versions of this
|
||||
License can be used, that proxy's public statement of acceptance of a
|
||||
version permanently authorizes you to choose that version for the
|
||||
Document.
|
||||
|
||||
@item
|
||||
RELICENSING
|
||||
|
||||
``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any
|
||||
World Wide Web server that publishes copyrightable works and also
|
||||
provides prominent facilities for anybody to edit those works. A
|
||||
public wiki that anybody can edit is an example of such a server. A
|
||||
``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the
|
||||
site means any set of copyrightable works thus published on the MMC
|
||||
site.
|
||||
|
||||
``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0
|
||||
license published by Creative Commons Corporation, a not-for-profit
|
||||
corporation with a principal place of business in San Francisco,
|
||||
California, as well as future copyleft versions of that license
|
||||
published by that same organization.
|
||||
|
||||
``Incorporate'' means to publish or republish a Document, in whole or
|
||||
in part, as part of another Document.
|
||||
|
||||
An MMC is ``eligible for relicensing'' if it is licensed under this
|
||||
License, and if all works that were first published under this License
|
||||
somewhere other than this MMC, and subsequently incorporated in whole
|
||||
or in part into the MMC, (1) had no cover texts or invariant sections,
|
||||
and (2) were thus incorporated prior to November 1, 2008.
|
||||
|
||||
The operator of an MMC Site may republish an MMC contained in the site
|
||||
under CC-BY-SA on the same site at any time before August 1, 2009,
|
||||
provided the MMC is eligible for relicensing.
|
||||
|
||||
@end enumerate
|
||||
|
||||
@page
|
||||
@heading ADDENDUM: How to use this License for your documents
|
||||
|
||||
To use this License in a document you have written, include a copy of
|
||||
the License in the document and put the following copyright and
|
||||
license notices just after the title page:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
Copyright (C) @var{year} @var{your name}.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.3
|
||||
or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
|
||||
Texts. A copy of the license is included in the section entitled ``GNU
|
||||
Free Documentation License''.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||||
replace the ``with@dots{}Texts.'' line with this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
with the Invariant Sections being @var{list their titles}, with
|
||||
the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
|
||||
being @var{list}.
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
If you have Invariant Sections without Cover Texts, or some other
|
||||
combination of the three, merge those two alternatives to suit the
|
||||
situation.
|
||||
|
||||
If your document contains nontrivial examples of program code, we
|
||||
recommend releasing these examples in parallel under your choice of
|
||||
free software license, such as the GNU General Public License,
|
||||
to permit their use in free software.
|
||||
|
||||
@c Local Variables:
|
||||
@c ispell-local-pdict: "ispell-dict"
|
||||
@c End:
|
||||
|
3399
gprofng/doc/gprofng.texi
Normal file
3399
gprofng/doc/gprofng.texi
Normal file
File diff suppressed because it is too large
Load diff
224
gprofng/doc/mdate-sh
Executable file
224
gprofng/doc/mdate-sh
Executable file
|
@ -0,0 +1,224 @@
|
|||
#!/bin/sh
|
||||
# Get modification time of a file or directory and pretty-print it.
|
||||
|
||||
scriptversion=2016-01-11.22; # UTC
|
||||
|
||||
# Copyright (C) 1995-2017 Free Software Foundation, Inc.
|
||||
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
|
||||
#
|
||||
# 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 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
|
||||
emulate sh
|
||||
NULLCMD=:
|
||||
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
|
||||
# is contrary to our usage. Disable this feature.
|
||||
alias -g '${1+"$@"}'='"$@"'
|
||||
setopt NO_GLOB_SUBST
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No file. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: mdate-sh [--help] [--version] FILE
|
||||
|
||||
Pretty-print the modification day of FILE, in the format:
|
||||
1 January 1970
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "mdate-sh $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
error ()
|
||||
{
|
||||
echo "$0: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
# Prevent date giving response in another language.
|
||||
LANG=C
|
||||
export LANG
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
LC_TIME=C
|
||||
export LC_TIME
|
||||
|
||||
# GNU ls changes its time format in response to the TIME_STYLE
|
||||
# variable. Since we cannot assume 'unset' works, revert this
|
||||
# variable to its documented default.
|
||||
if test "${TIME_STYLE+set}" = set; then
|
||||
TIME_STYLE=posix-long-iso
|
||||
export TIME_STYLE
|
||||
fi
|
||||
|
||||
save_arg1=$1
|
||||
|
||||
# Find out how to get the extended ls output of a file or directory.
|
||||
if ls -L /dev/null 1>/dev/null 2>&1; then
|
||||
ls_command='ls -L -l -d'
|
||||
else
|
||||
ls_command='ls -l -d'
|
||||
fi
|
||||
# Avoid user/group names that might have spaces, when possible.
|
||||
if ls -n /dev/null 1>/dev/null 2>&1; then
|
||||
ls_command="$ls_command -n"
|
||||
fi
|
||||
|
||||
# A 'ls -l' line looks as follows on OS/2.
|
||||
# drwxrwx--- 0 Aug 11 2001 foo
|
||||
# This differs from Unix, which adds ownership information.
|
||||
# drwxrwx--- 2 root root 4096 Aug 11 2001 foo
|
||||
#
|
||||
# To find the date, we split the line on spaces and iterate on words
|
||||
# until we find a month. This cannot work with files whose owner is a
|
||||
# user named "Jan", or "Feb", etc. However, it's unlikely that '/'
|
||||
# will be owned by a user whose name is a month. So we first look at
|
||||
# the extended ls output of the root directory to decide how many
|
||||
# words should be skipped to get the date.
|
||||
|
||||
# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
|
||||
set x`$ls_command /`
|
||||
|
||||
# Find which argument is the month.
|
||||
month=
|
||||
command=
|
||||
until test $month
|
||||
do
|
||||
test $# -gt 0 || error "failed parsing '$ls_command /' output"
|
||||
shift
|
||||
# Add another shift to the command.
|
||||
command="$command shift;"
|
||||
case $1 in
|
||||
Jan) month=January; nummonth=1;;
|
||||
Feb) month=February; nummonth=2;;
|
||||
Mar) month=March; nummonth=3;;
|
||||
Apr) month=April; nummonth=4;;
|
||||
May) month=May; nummonth=5;;
|
||||
Jun) month=June; nummonth=6;;
|
||||
Jul) month=July; nummonth=7;;
|
||||
Aug) month=August; nummonth=8;;
|
||||
Sep) month=September; nummonth=9;;
|
||||
Oct) month=October; nummonth=10;;
|
||||
Nov) month=November; nummonth=11;;
|
||||
Dec) month=December; nummonth=12;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -n "$month" || error "failed parsing '$ls_command /' output"
|
||||
|
||||
# Get the extended ls output of the file or directory.
|
||||
set dummy x`eval "$ls_command \"\\\$save_arg1\""`
|
||||
|
||||
# Remove all preceding arguments
|
||||
eval $command
|
||||
|
||||
# Because of the dummy argument above, month is in $2.
|
||||
#
|
||||
# On a POSIX system, we should have
|
||||
#
|
||||
# $# = 5
|
||||
# $1 = file size
|
||||
# $2 = month
|
||||
# $3 = day
|
||||
# $4 = year or time
|
||||
# $5 = filename
|
||||
#
|
||||
# On Darwin 7.7.0 and 7.6.0, we have
|
||||
#
|
||||
# $# = 4
|
||||
# $1 = day
|
||||
# $2 = month
|
||||
# $3 = year or time
|
||||
# $4 = filename
|
||||
|
||||
# Get the month.
|
||||
case $2 in
|
||||
Jan) month=January; nummonth=1;;
|
||||
Feb) month=February; nummonth=2;;
|
||||
Mar) month=March; nummonth=3;;
|
||||
Apr) month=April; nummonth=4;;
|
||||
May) month=May; nummonth=5;;
|
||||
Jun) month=June; nummonth=6;;
|
||||
Jul) month=July; nummonth=7;;
|
||||
Aug) month=August; nummonth=8;;
|
||||
Sep) month=September; nummonth=9;;
|
||||
Oct) month=October; nummonth=10;;
|
||||
Nov) month=November; nummonth=11;;
|
||||
Dec) month=December; nummonth=12;;
|
||||
esac
|
||||
|
||||
case $3 in
|
||||
???*) day=$1;;
|
||||
*) day=$3; shift;;
|
||||
esac
|
||||
|
||||
# Here we have to deal with the problem that the ls output gives either
|
||||
# the time of day or the year.
|
||||
case $3 in
|
||||
*:*) set `date`; eval year=\$$#
|
||||
case $2 in
|
||||
Jan) nummonthtod=1;;
|
||||
Feb) nummonthtod=2;;
|
||||
Mar) nummonthtod=3;;
|
||||
Apr) nummonthtod=4;;
|
||||
May) nummonthtod=5;;
|
||||
Jun) nummonthtod=6;;
|
||||
Jul) nummonthtod=7;;
|
||||
Aug) nummonthtod=8;;
|
||||
Sep) nummonthtod=9;;
|
||||
Oct) nummonthtod=10;;
|
||||
Nov) nummonthtod=11;;
|
||||
Dec) nummonthtod=12;;
|
||||
esac
|
||||
# For the first six month of the year the time notation can also
|
||||
# be used for files modified in the last year.
|
||||
if (expr $nummonth \> $nummonthtod) > /dev/null;
|
||||
then
|
||||
year=`expr $year - 1`
|
||||
fi;;
|
||||
*) year=$3;;
|
||||
esac
|
||||
|
||||
# The result.
|
||||
echo $day $month $year
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
11731
gprofng/doc/texinfo.tex
Normal file
11731
gprofng/doc/texinfo.tex
Normal file
File diff suppressed because it is too large
Load diff
4
gprofng/doc/version.texi
Normal file
4
gprofng/doc/version.texi
Normal file
|
@ -0,0 +1,4 @@
|
|||
@set EDITION 1.0
|
||||
@set VERSION 1.0
|
||||
@set UPDATED 22 February 2022
|
||||
@set UPDATED-MONTH February 2022
|
60
gprofng/gp-display-html/Makefile.am
Normal file
60
gprofng/gp-display-html/Makefile.am
Normal file
|
@ -0,0 +1,60 @@
|
|||
## Process this file with automake to generate Makefile.in
|
||||
#
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I . -I .. -I ../..
|
||||
|
||||
dist_man_MANS = gp-display-html.1
|
||||
bin_SCRIPTS = gp-display-html
|
||||
CLEANFILES = $(bin_SCRIPTS)
|
||||
MAINTAINERCLEANFILES = $(dist_man_MANS)
|
||||
|
||||
do_subst = sed -e 's/BINUTILS_VERSION/$(VERSION)/'
|
||||
|
||||
gp-display-html: gp-display-html.in Makefile
|
||||
$(do_subst) < $(srcdir)/gp-display-html.in > $@
|
||||
chmod +x $@
|
||||
|
||||
if BUILD_MAN
|
||||
|
||||
# Use this if the man pages depend on the version number.
|
||||
# common_mandeps = $(top_srcdir)/../bfd/version.m4
|
||||
#
|
||||
# Also change the dependence line below to this:
|
||||
# gp-display-html.1: $(common_mandeps) gp-display-html
|
||||
#
|
||||
# Currently, the version number shown in the man page is derived from
|
||||
# the output printed with --version.
|
||||
|
||||
# These variables are used by help2man to generate the man pages.
|
||||
|
||||
INFO_PAGE = "gprofng"
|
||||
MANUAL = "User Commands"
|
||||
TEXT_GP_DISPLAY_HTML = "generate an HTML based directory structure to browse the profiles"
|
||||
|
||||
HELP2MAN_OPT = --libtool --no-info --info-page=$(INFO_PAGE) --manual=$(MANUAL)
|
||||
H2M_FILTER = | sed 's/\.TP/\.TP\n.B/' | sed 's/Commands:/\.SH COMMANDS/' \
|
||||
| sed 's/See also:/\.SH SEE ALSO/' | sed 's/Documentation:/.SH DOCUMENTATION/' \
|
||||
| sed 's/Limitations:/.SH LIMITATIONS/'
|
||||
|
||||
gp-display-html.1: gp-display-html
|
||||
$(AM_V_GEN)_BUILDING_MANPAGE=1 $(HELP2MAN) $(HELP2MAN_OPT) \
|
||||
--name=$(TEXT_GP_DISPLAY_HTML) ./gp-display-html $(H2M_FILTER) > $@
|
||||
|
||||
endif
|
||||
|
630
gprofng/gp-display-html/Makefile.in
Normal file
630
gprofng/gp-display-html/Makefile.in
Normal file
|
@ -0,0 +1,630 @@
|
|||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
#
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = gp-display-html
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \
|
||||
$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
|
||||
$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
|
||||
$(top_srcdir)/acinclude.m4 $(top_srcdir)/../config/warnings.m4 \
|
||||
$(top_srcdir)/../config/enable.m4 \
|
||||
$(top_srcdir)/../config/ax_pthread.m4 \
|
||||
$(top_srcdir)/config/bison.m4 $(top_srcdir)/../bfd/version.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
|
||||
SCRIPTS = $(bin_SCRIPTS)
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
man1dir = $(mandir)/man1
|
||||
NROFF = nroff
|
||||
MANS = $(dist_man_MANS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \
|
||||
$(top_srcdir)/../mkinstalldirs
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BUILD_SUBDIRS = @BUILD_SUBDIRS@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
EXPECT = @EXPECT@
|
||||
FGREP = @FGREP@
|
||||
GPROFNG_CFLAGS = @GPROFNG_CFLAGS@
|
||||
GPROFNG_CPPFLAGS = @GPROFNG_CPPFLAGS@
|
||||
GPROFNG_LIBADD = @GPROFNG_LIBADD@
|
||||
GPROFNG_LIBDIR = @GPROFNG_LIBDIR@
|
||||
GREP = @GREP@
|
||||
HELP2MAN = @HELP2MAN@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
JAVA = @JAVA@
|
||||
JAVAC = @JAVAC@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LD_NO_AS_NEEDED = @LD_NO_AS_NEEDED@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
WERROR = @WERROR@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
ax_pthread_config = @ax_pthread_config@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
gprofng_cflags = @gprofng_cflags@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
jdk_inc = @jdk_inc@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I . -I .. -I ../..
|
||||
dist_man_MANS = gp-display-html.1
|
||||
bin_SCRIPTS = gp-display-html
|
||||
CLEANFILES = $(bin_SCRIPTS)
|
||||
MAINTAINERCLEANFILES = $(dist_man_MANS)
|
||||
do_subst = sed -e 's/BINUTILS_VERSION/$(VERSION)/'
|
||||
|
||||
# Use this if the man pages depend on the version number.
|
||||
# common_mandeps = $(top_srcdir)/../bfd/version.m4
|
||||
#
|
||||
# Also change the dependence line below to this:
|
||||
# gp-display-html.1: $(common_mandeps) gp-display-html
|
||||
#
|
||||
# Currently, the version number shown in the man page is derived from
|
||||
# the output printed with --version.
|
||||
|
||||
# These variables are used by help2man to generate the man pages.
|
||||
@BUILD_MAN_TRUE@INFO_PAGE = "gprofng"
|
||||
@BUILD_MAN_TRUE@MANUAL = "User Commands"
|
||||
@BUILD_MAN_TRUE@TEXT_GP_DISPLAY_HTML = "generate an HTML based directory structure to browse the profiles"
|
||||
@BUILD_MAN_TRUE@HELP2MAN_OPT = --libtool --no-info --info-page=$(INFO_PAGE) --manual=$(MANUAL)
|
||||
@BUILD_MAN_TRUE@H2M_FILTER = | sed 's/\.TP/\.TP\n.B/' | sed 's/Commands:/\.SH COMMANDS/' \
|
||||
@BUILD_MAN_TRUE@ | sed 's/See also:/\.SH SEE ALSO/' | sed 's/Documentation:/.SH DOCUMENTATION/' \
|
||||
@BUILD_MAN_TRUE@ | sed 's/Limitations:/.SH LIMITATIONS/'
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gp-display-html/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign gp-display-html/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binSCRIPTS: $(bin_SCRIPTS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n' \
|
||||
-e 'h;s|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) { files[d] = files[d] " " $$1; \
|
||||
if (++n[d] == $(am__install_max)) { \
|
||||
print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
|
||||
else { print "f", d "/" $$4, $$1 } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binSCRIPTS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 's,.*/,,;$(transform)'`; \
|
||||
dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-man1: $(dist_man_MANS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list1=''; \
|
||||
list2='$(dist_man_MANS)'; \
|
||||
test -n "$(man1dir)" \
|
||||
&& test -n "`echo $$list1$$list2`" \
|
||||
|| exit 0; \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
|
||||
{ for i in $$list1; do echo "$$i"; done; \
|
||||
if test -n "$$list2"; then \
|
||||
for i in $$list2; do echo "$$i"; done \
|
||||
| sed -n '/\.1[a-z]*$$/p'; \
|
||||
fi; \
|
||||
} | while read p; do \
|
||||
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; echo "$$p"; \
|
||||
done | \
|
||||
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||
sed 'N;N;s,\n, ,g' | { \
|
||||
list=; while read file base inst; do \
|
||||
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
|
||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
|
||||
fi; \
|
||||
done; \
|
||||
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
|
||||
done; }
|
||||
|
||||
uninstall-man1:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list=''; test -n "$(man1dir)" || exit 0; \
|
||||
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
|
||||
sed -n '/\.1[a-z]*$$/p'; \
|
||||
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(SCRIPTS) $(MANS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-man
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binSCRIPTS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man: install-man1
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binSCRIPTS uninstall-man
|
||||
|
||||
uninstall-man: uninstall-man1
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||
cscopelist-am ctags-am distclean distclean-generic \
|
||||
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-binSCRIPTS install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-man1 install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
|
||||
uninstall-am uninstall-binSCRIPTS uninstall-man uninstall-man1
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
gp-display-html: gp-display-html.in Makefile
|
||||
$(do_subst) < $(srcdir)/gp-display-html.in > $@
|
||||
chmod +x $@
|
||||
|
||||
@BUILD_MAN_TRUE@gp-display-html.1: gp-display-html
|
||||
@BUILD_MAN_TRUE@ $(AM_V_GEN)_BUILDING_MANPAGE=1 $(HELP2MAN) $(HELP2MAN_OPT) \
|
||||
@BUILD_MAN_TRUE@ --name=$(TEXT_GP_DISPLAY_HTML) ./gp-display-html $(H2M_FILTER) > $@
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
256
gprofng/gp-display-html/gp-display-html.in
Normal file
256
gprofng/gp-display-html/gp-display-html.in
Normal file
|
@ -0,0 +1,256 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Copyright (C) 2021 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.
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# gp-display-html, last updated July 2021
|
||||
#
|
||||
# NOTE: This is a skeleton version. The real code will follow as an update.
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Poor man's version of a boolean.
|
||||
#------------------------------------------------------------------------------
|
||||
my $TRUE = 1;
|
||||
my $FALSE = 0;
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Define the driver command, tool name and version number.
|
||||
#-------------------------------------------------------------------------------
|
||||
my $driver_cmd = "gprofng display html";
|
||||
my $tool_name = "gp-display-html";
|
||||
my $binutils_version = "BINUTILS_VERSION";
|
||||
my $version_info = $tool_name . " GNU binutils version " . $binutils_version;
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# This is cosmetic, but helps with the scoping of variables.
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
main ();
|
||||
|
||||
exit (0);
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# THE SUBROUTINES
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# This is the driver part of the program.
|
||||
#------------------------------------------------------------------------------
|
||||
sub
|
||||
main
|
||||
{
|
||||
my $subr_name = "main";
|
||||
my $ignore_value;
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# If no options are given, print the help info and exit.
|
||||
#------------------------------------------------------------------------------
|
||||
$ignore_value = early_scan_specific_options();
|
||||
|
||||
$ignore_value = be_patient ();
|
||||
|
||||
return (0);
|
||||
|
||||
} #-- End of subroutine main
|
||||
|
||||
sub
|
||||
be_patient
|
||||
{
|
||||
print "Functionality not implemented yet - please stay tuned for updates\n";
|
||||
|
||||
} #-- End of subroutine be_patient
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Prints the version number and license information.
|
||||
#------------------------------------------------------------------------------
|
||||
sub
|
||||
print_version_info
|
||||
{
|
||||
print "$version_info\n";
|
||||
print "Copyright (C) 2021 Free Software Foundation, Inc.\n";
|
||||
print "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n";
|
||||
print "This is free software: you are free to change and redistribute it.\n";
|
||||
print "There is NO WARRANTY, to the extent permitted by law.\n";
|
||||
|
||||
return (0);
|
||||
|
||||
} #-- End of subroutine print_version_info
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Print the help overview
|
||||
#-------------------------------------------------------------------------------
|
||||
sub
|
||||
print_help_info
|
||||
{
|
||||
print
|
||||
"Usage: $driver_cmd [OPTION(S)] EXPERIMENT(S)\n".
|
||||
"\n".
|
||||
"Process one or more experiments to generate a directory containing an index.html\n".
|
||||
"file that can be used to browse the experiment data\n".
|
||||
"\n".
|
||||
"Options:\n".
|
||||
"\n".
|
||||
" --help print usage information and exit.\n".
|
||||
" --version print the version number and exit.\n".
|
||||
" --verbose {on|off} enable (on) or disable (off) verbose mode; the default is \"off\".\n".
|
||||
"\n".
|
||||
"\n".
|
||||
" -o, --output <dir-name> use <dir-name> to store the results in; the default\n".
|
||||
" name is ./display.<n>.html with <n> the first number\n".
|
||||
" not in use; an existing directory is not overwritten.\n".
|
||||
"\n".
|
||||
" -O, --overwrite <dir-name> use <dir-name> to store the results in and overwrite\n".
|
||||
" any existing directory with the same name; make sure\n".
|
||||
" that umask is set to the correct access permissions.\n".
|
||||
"\n".
|
||||
" -fl, --func_limit <limit> impose a limit on the number of functions processed;\n".
|
||||
" this is an integer number; set to 0 to process all\n".
|
||||
" functions; the default value is 100.\n".
|
||||
"\n".
|
||||
" -ct, --calltree {on|off} enable or disable an html page with a call tree linked\n".
|
||||
" from the bottom of the first page; default is off.\n".
|
||||
"\n".
|
||||
" -tp, --threshold_percentage <percentage> provide a percentage of metric accountability; the\n".
|
||||
" inclusion of functions for each metric will take\n".
|
||||
" place in sort order until the percentage has been\n".
|
||||
" reached.\n".
|
||||
"\n".
|
||||
" -dm, --default_metrics {on|off} enable or disable automatic selection of metrics\n".
|
||||
" and use a default set of metrics; the default is off.\n".
|
||||
"\n".
|
||||
" -im, --ignore_metrics <metric-list> ignore the metrics from <metric-list>.\n".
|
||||
"\n".
|
||||
" -db, --debug {on|off} enable/disable debug mode; print detailed information to assist with troubleshooting\n".
|
||||
" or further development of this tool; default is off.\n".
|
||||
"\n".
|
||||
" -q, --quiet {on|off} disable/enable the display of warnings; default is off.\n".
|
||||
"\n".
|
||||
"Environment:\n".
|
||||
"\n".
|
||||
"The options can be set in a configuration file called .gp-display-html.rc. This\n".
|
||||
"file needs to be either in the current directory, or in the home directory of the user.\n".
|
||||
"The long name of the option without the leading dashes is supported. For example calltree\n".
|
||||
"to enable or disable the call tree. Note that some options take a value. In case the same option\n".
|
||||
"occurs multiple times in this file, only the last setting encountered is preserved.\n".
|
||||
"\n".
|
||||
"Documentation:\n".
|
||||
"\n".
|
||||
"A getting started guide for gprofng is maintained as a Texinfo manual. If the info and\n".
|
||||
"gprofng programs are properly installed at your site, the command \"info gprofng\"\n".
|
||||
"should give you access to this document.\n".
|
||||
"\n".
|
||||
"See also:\n".
|
||||
"\n".
|
||||
"gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-src(1), gp-display-text(1)\n";
|
||||
|
||||
return (0);
|
||||
|
||||
} #-- End of subroutine print_help_info
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Scan the command line for specific options.
|
||||
#------------------------------------------------------------------------------
|
||||
sub
|
||||
early_scan_specific_options
|
||||
{
|
||||
my $subr_name = "early_scan_specific_options";
|
||||
|
||||
my $ignore_value;
|
||||
my $found_option;
|
||||
my $option_has_value;
|
||||
my $option_value;
|
||||
|
||||
my $verbose_setting = $FALSE;
|
||||
my $debug_setting = $FALSE;
|
||||
my $quiet_setting = $FALSE;
|
||||
|
||||
$option_has_value = $FALSE;
|
||||
($found_option, $option_value) = find_target_option (\@ARGV, $option_has_value, "--version");
|
||||
if ($found_option)
|
||||
{
|
||||
$ignore_value = print_version_info ();
|
||||
exit(0);
|
||||
}
|
||||
$option_has_value = $FALSE;
|
||||
($found_option, $option_value) = find_target_option (\@ARGV, $option_has_value, "--help");
|
||||
if ($found_option)
|
||||
{
|
||||
$ignore_value = print_help_info ();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
} #-- End of subroutine early_scan_specific_options
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Scan the command line to see if the specified option is present.
|
||||
#
|
||||
# Two types of options are supported: options without value (e.g. --help) or
|
||||
# those that are set to "on" or "off".
|
||||
#------------------------------------------------------------------------------
|
||||
sub
|
||||
find_target_option
|
||||
{
|
||||
my ($command_line_ref, $has_value, $target_option) = @_;
|
||||
|
||||
my @command_line = @{ $command_line_ref };
|
||||
|
||||
my ($command_line_string) = join(" ", @command_line);
|
||||
|
||||
my $option_value = "not set";
|
||||
my $found_option = $FALSE;
|
||||
|
||||
if ($command_line_string =~ /\s*($target_option)\s*(on|off)*\s*/)
|
||||
{
|
||||
if ($has_value)
|
||||
{
|
||||
#------------------------------------------------------------------------------
|
||||
# We are looking for this kind if substring: "--verbose on"
|
||||
#------------------------------------------------------------------------------
|
||||
if (defined($1) and defined($2))
|
||||
{
|
||||
if ( ($2 eq "on") or ($2 eq "off") )
|
||||
{
|
||||
$found_option = $TRUE;
|
||||
$option_value = $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#------------------------------------------------------------------------------
|
||||
# We are looking for this kind if substring: "--help"
|
||||
#------------------------------------------------------------------------------
|
||||
if (defined($1))
|
||||
{
|
||||
$found_option = $TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return($found_option, $option_value);
|
||||
|
||||
} #-- End of subroutine find_target_option
|
82
gprofng/libcollector/CHK_LIBC_OBJ
Executable file
82
gprofng/libcollector/CHK_LIBC_OBJ
Executable file
|
@ -0,0 +1,82 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
#
|
||||
# CHK_LIBC_OBJ -- a script to scan the .o's in an output directory,
|
||||
# which is one of ../{intel-S2,sparc-S2,intel-Linux,sparc-Linux}
|
||||
#
|
||||
# usage: cd to the output directory, and invoke ../src/CHK_LIBC_OBJ
|
||||
|
||||
|
||||
check_obj() {
|
||||
logF="nm.`basename $1`.log"
|
||||
if [ `uname` = 'Linux' ]; then
|
||||
nm $1 | grep -v GLIBC_ > ${logF}
|
||||
else
|
||||
nm $1 > ${logF}
|
||||
fi
|
||||
|
||||
FUNC_LIST="strcpy strlcpy strncpy strcat strlcat strncat strncmp strlen \
|
||||
strerror strchr strrchr strpbrk strstr strtok strtok_r \
|
||||
printf fprintf sprintf snprintf asprintf wsprintf \
|
||||
vprintf vfprintf vsprintf vsnprintf vasprintf \
|
||||
memset memcmp memcpy strtol strtoll strtoul strtoull \
|
||||
getcpuid calloc malloc free strdup"
|
||||
res=0
|
||||
echo " -- Checking Object file '$1' for functions from libc"
|
||||
for j in `echo ${FUNC_LIST}` ; do
|
||||
grep -w ${j} ${logF} | grep UNDEF> grep.log 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
grep -w ${j} ${logF}
|
||||
res=1
|
||||
fi
|
||||
done
|
||||
return ${res}
|
||||
}
|
||||
|
||||
STATUS=0
|
||||
|
||||
for i in *.o ; do
|
||||
echo ""
|
||||
check_obj ${i}
|
||||
res=$?
|
||||
if [ ${res} -eq 0 ]; then
|
||||
echo "Object file ${i} does not reference functions in libc"
|
||||
else
|
||||
echo "======Object file: ${i} DOES reference functions in libc"
|
||||
fi
|
||||
if [ ${STATUS} -eq 0 ]; then
|
||||
STATUS=${res}
|
||||
fi
|
||||
done
|
||||
|
||||
for i in *.so ; do
|
||||
echo ""
|
||||
check_obj ${i}
|
||||
res=$?
|
||||
if [ ${res} -eq 0 ]; then
|
||||
echo "Object file ${i} does not reference functions in libc"
|
||||
else
|
||||
echo "======Object file: ${i} DOES reference functions in libc"
|
||||
fi
|
||||
if [ ${STATUS} -eq 0 ]; then
|
||||
STATUS=${res}
|
||||
fi
|
||||
done
|
||||
|
||||
exit $STATUS
|
79
gprofng/libcollector/Makefile.am
Normal file
79
gprofng/libcollector/Makefile.am
Normal file
|
@ -0,0 +1,79 @@
|
|||
## Process this file with automake to generate Makefile.in
|
||||
#
|
||||
# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I . -I ../..
|
||||
|
||||
GPROFNG_VARIANT = @GPROFNG_VARIANT@
|
||||
|
||||
CSOURCES = \
|
||||
gethrtime.c \
|
||||
dispatcher.c \
|
||||
iolib.c \
|
||||
mmaptrace.c \
|
||||
memmgr.c \
|
||||
tsd.c \
|
||||
profile.c \
|
||||
envmgmt.c \
|
||||
linetrace.c \
|
||||
libcol_hwcdrv.c \
|
||||
libcol_hwcfuncs.c \
|
||||
libcol-i386-dis.c \
|
||||
hwprofile.c \
|
||||
jprofile.c \
|
||||
unwind.c \
|
||||
libcol_util.c \
|
||||
collector.c \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = $(GPROFNG_CFLAGS) -Wno-nonnull-compare
|
||||
AM_CPPFLAGS = $(GPROFNG_CPPFLAGS) -I.. -I$(srcdir) \
|
||||
-I$(srcdir)/../common -I$(srcdir)/../src \
|
||||
-I$(srcdir)/../../include
|
||||
AM_LDFLAGS = -module -avoid-version \
|
||||
-Wl,--version-script,$(srcdir)/mapfile.$(GPROFNG_VARIANT) \
|
||||
$(LD_NO_AS_NEEDED) -Wl,-lrt -Wl,-ldl
|
||||
|
||||
myincludedir = @includedir@
|
||||
myinclude_HEADERS = $(srcdir)/../../include/collectorAPI.h \
|
||||
$(srcdir)/../../include/libcollector.h \
|
||||
$(srcdir)/../../include/libfcollector.h
|
||||
|
||||
lib_LTLIBRARIES = libgp-collector.la libgp-collectorAPI.la libgp-heap.la \
|
||||
libgp-sync.la libgp-iotrace.la
|
||||
|
||||
libgp_collector_la_SOURCES = $(CSOURCES)
|
||||
libgp_collector_la_CPPFLAGS = $(AM_CPPFLAGS) $(jdk_inc) \
|
||||
-I../../bfd -I$(srcdir)/../..
|
||||
# Prevent libtool from reordering -Wl,--no-as-needed after -lrt by
|
||||
# disguising -lrt as a linker flag.
|
||||
libgp_collector_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
libgp_collector_la_LIBADD =
|
||||
|
||||
libgp_heap_la_SOURCES = heaptrace.c
|
||||
libgp_heap_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
libgp_sync_la_SOURCES = synctrace.c
|
||||
libgp_sync_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
libgp_iotrace_la_SOURCES = iotrace.c
|
||||
libgp_iotrace_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
libgp_collectorAPI_la_SOURCES = collectorAPI.c
|
||||
libgp_collectorAPI_la_LIBADD = -lc -ldl
|
||||
|
1131
gprofng/libcollector/Makefile.in
Normal file
1131
gprofng/libcollector/Makefile.in
Normal file
File diff suppressed because it is too large
Load diff
1237
gprofng/libcollector/aclocal.m4
vendored
Normal file
1237
gprofng/libcollector/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
2494
gprofng/libcollector/collector.c
Normal file
2494
gprofng/libcollector/collector.c
Normal file
File diff suppressed because it is too large
Load diff
236
gprofng/libcollector/collector.h
Normal file
236
gprofng/libcollector/collector.h
Normal file
|
@ -0,0 +1,236 @@
|
|||
/* Copyright (C) 2021 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 _COLLECTOR_H
|
||||
#define _COLLECTOR_H
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "gp-defs.h"
|
||||
#include "data_pckts.h"
|
||||
#include "libcol_util.h"
|
||||
#include "collector_module.h"
|
||||
|
||||
#define GETRELTIME() (__collector_gethrtime() - __collector_start_time)
|
||||
|
||||
extern hrtime_t __collector_start_time;
|
||||
|
||||
/* ========================================================== */
|
||||
/* ------- internal function prototypes ----------------- */
|
||||
/* These will not be exported from libcollector.so */
|
||||
struct DataHandle;
|
||||
struct Heap;
|
||||
extern struct DataHandle *__collector_create_handle (char*);
|
||||
extern void __collector_delete_handle (struct DataHandle*);
|
||||
extern int __collector_write_record (struct DataHandle*, Common_packet*);
|
||||
extern int __collector_write_packet (struct DataHandle*, CM_Packet*);
|
||||
extern int __collector_write_string (struct DataHandle*, char*, int);
|
||||
extern FrameInfo __collector_get_frame_info (hrtime_t, int, void *);
|
||||
extern FrameInfo __collector_getUID (CM_Array *arg, FrameInfo uid);
|
||||
extern int __collector_getStackTrace (void *buf, int size, void *bptr, void *eptr, void *arg);
|
||||
extern void *__collector_ext_return_address (unsigned level);
|
||||
extern void __collector_mmap_fork_child_cleanup ();
|
||||
|
||||
extern int __collector_ext_mmap_install (int);
|
||||
extern int __collector_ext_mmap_deinstall (int);
|
||||
extern int __collector_ext_update_map_segments (void);
|
||||
extern int __collector_check_segment (unsigned long addr,
|
||||
unsigned long *base,
|
||||
unsigned long *end, int maxnretries);
|
||||
extern int __collector_check_readable_segment (unsigned long addr,
|
||||
unsigned long *base,
|
||||
unsigned long *end, int maxnretries);
|
||||
extern int __collector_ext_line_init (int * pfollow_this_experiment,
|
||||
const char * progspec,
|
||||
const char *progname);
|
||||
extern int __collector_ext_line_install (char *, const char *);
|
||||
extern void __collector_ext_line_close ();
|
||||
extern void __collector_ext_unwind_init (int);
|
||||
extern void __collector_ext_unwind_close ();
|
||||
extern int __collector_ext_jstack_unwind (char*, int, ucontext_t *);
|
||||
extern void __collector_ext_dispatcher_fork_child_cleanup ();
|
||||
extern void __collector_ext_unwind_key_init (int isPthread, void * stack);
|
||||
extern void __collector_ext_dispatcher_tsd_create_key ();
|
||||
extern void __collector_ext_dispatcher_thread_timer_suspend ();
|
||||
extern int __collector_ext_dispatcher_thread_timer_resume ();
|
||||
extern int __collector_ext_dispatcher_install ();
|
||||
extern void __collector_ext_dispatcher_suspend ();
|
||||
extern void __collector_ext_dispatcher_restart ();
|
||||
extern void __collector_ext_dispatcher_deinstall ();
|
||||
extern void __collector_ext_usage_sample (Smpl_type type, char *name);
|
||||
extern void __collector_ext_profile_handler (siginfo_t *, ucontext_t *);
|
||||
extern int __collector_ext_clone_pthread (int (*fn)(void *), void *child_stack, int flags, void *arg,
|
||||
va_list va /* pid_t *ptid, struct user_desc *tlspid_t *" ctid" */);
|
||||
|
||||
/* D-light related functions */
|
||||
extern int __collector_sigprof_install ();
|
||||
extern int __collector_ext_hwc_active ();
|
||||
extern void __collector_ext_hwc_check (siginfo_t *, ucontext_t *);
|
||||
extern int __collector_ext_hwc_lwp_init ();
|
||||
extern void __collector_ext_hwc_lwp_fini ();
|
||||
extern int __collector_ext_hwc_lwp_suspend ();
|
||||
extern int __collector_ext_hwc_lwp_resume ();
|
||||
extern int (*__collector_VM_ReadByteInstruction)(unsigned char *);
|
||||
extern int (*__collector_omp_stack_trace)(char*, int, hrtime_t, void*);
|
||||
extern hrtime_t (*__collector_gethrtime)();
|
||||
extern int (*__collector_mpi_stack_trace)(char*, int, hrtime_t);
|
||||
extern int __collector_open_experiment (const char *exp, const char *par, sp_origin_t origin);
|
||||
extern void __collector_suspend_experiment (char *why);
|
||||
extern void __collector_resume_experiment ();
|
||||
extern void __collector_clean_state ();
|
||||
extern void __collector_close_experiment ();
|
||||
extern void __collector_terminate_expt ();
|
||||
extern void __collector_terminate_hook ();
|
||||
extern void __collector_sample (char *name);
|
||||
extern void __collector_pause ();
|
||||
extern void __collector_pause_m ();
|
||||
extern void __collector_resume ();
|
||||
extern int collector_sigemt_sigaction (const struct sigaction*,
|
||||
struct sigaction*);
|
||||
extern int collector_sigchld_sigaction (const struct sigaction*,
|
||||
struct sigaction*);
|
||||
|
||||
extern int
|
||||
__collector_log_write (char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
/* ------- internal global data ----------------- */
|
||||
/* These will not be exported from libcollector.so */
|
||||
extern struct Heap *__collector_heap;
|
||||
|
||||
/* experiment state flag */
|
||||
typedef enum
|
||||
{
|
||||
EXP_INIT, EXP_OPEN, EXP_PAUSED, EXP_CLOSED
|
||||
} sp_state_t;
|
||||
extern volatile sp_state_t __collector_expstate;
|
||||
|
||||
/* global flag, defines whether target is threaded or not
|
||||
* if set, put _lwp_self() for thread id instead of thr_self()
|
||||
* in output packets; should be set before any data packets
|
||||
* are written, i.e., before signal handlers are installed.
|
||||
*/
|
||||
extern int __collector_no_threads;
|
||||
extern int __collector_libthread_T1; /* T1 or not T1 */
|
||||
extern int __collector_sample_sig; /* set to signal used to trigger a sample */
|
||||
extern int __collector_sample_sig_warn; /* if 1, warning given on target use */
|
||||
extern int __collector_pause_sig; /* set to signal used to toggle pause-resume */
|
||||
extern int __collector_pause_sig_warn; /* if 1, warning given on target use */
|
||||
extern hrtime_t __collector_delay_start;
|
||||
extern int __collector_exp_active;
|
||||
|
||||
/* global hrtime_t for next periodic sample */
|
||||
extern hrtime_t __collector_next_sample;
|
||||
extern int __collector_sample_period;
|
||||
|
||||
/* global hrtime_t for experiment termination (-t) */
|
||||
extern hrtime_t __collector_terminate_time;
|
||||
extern int __collector_terminate_duration;
|
||||
extern char __collector_exp_dir_name[];
|
||||
extern int __collector_java_mode;
|
||||
extern int __collector_java_asyncgetcalltrace_loaded;
|
||||
extern int __collector_jprofile_start_attach ();
|
||||
|
||||
/* --------- information controlling debug tracing ------------- */
|
||||
|
||||
/* global flag, defines level of trace information */
|
||||
extern void __collector_dlog (int, int, char *, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
#define STR(x) ((x) ? (x) : "NULL")
|
||||
|
||||
// To set collector_debug_opt use:
|
||||
// SP_COLLECTOR_DEBUG=4 ; export SP_COLLECTOR_DEBUG ; collect ...
|
||||
enum
|
||||
{
|
||||
SP_DUMP_TIME = 1,
|
||||
SP_DUMP_FLAG = 2,
|
||||
SP_DUMP_JAVA = 4,
|
||||
SP_DUMP_NOHEADER = 8,
|
||||
SP_DUMP_UNWIND = 16,
|
||||
SP_DUMP_STACK = 32,
|
||||
};
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DprintfT(flag, ...)
|
||||
#define tprintf(...)
|
||||
#define Tprintf(...)
|
||||
#define TprintfT(...)
|
||||
|
||||
#else
|
||||
#define DprintfT(flag, ...) __collector_dlog(SP_DUMP_FLAG | (flag), 0, __VA_ARGS__ )
|
||||
#define tprintf(...) __collector_dlog( SP_DUMP_NOHEADER, __VA_ARGS__ )
|
||||
#define Tprintf(...) __collector_dlog( 0, __VA_ARGS__ )
|
||||
#define TprintfT(...) __collector_dlog( SP_DUMP_TIME, __VA_ARGS__ )
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
// To find the glibc version:
|
||||
// objdump -T /lib*/*so /lib*/*/*.so | grep popen
|
||||
// IMPORTANT: The GLIBC_* versions below must match those in mapfile.<variant>
|
||||
#if ARCH(Aarch64)
|
||||
#define SYS_LIBC_NAME "libc.so.6"
|
||||
#define SYS_PTHREAD_CREATE_VERSION "GLIBC_2.17"
|
||||
#define SYS_DLOPEN_VERSION "GLIBC_2.17"
|
||||
#define SYS_POPEN_VERSION "GLIBC_2.17"
|
||||
#define SYS_FOPEN_X_VERSION "GLIBC_2.17"
|
||||
#define SYS_FGETPOS_X_VERSION "GLIBC_2.17"
|
||||
|
||||
#elif ARCH(Intel)
|
||||
#define SYS_LIBC_NAME "libc.so.6"
|
||||
#define SYS_POSIX_SPAWN_VERSION "GLIBC_2.15"
|
||||
#if WSIZE(32)
|
||||
#define SYS_PTHREAD_CREATE_VERSION "GLIBC_2.1"
|
||||
#define SYS_DLOPEN_VERSION "GLIBC_2.1"
|
||||
#define SYS_POPEN_VERSION "GLIBC_2.1"
|
||||
#define SYS_TIMER_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_FOPEN_X_VERSION "GLIBC_2.1"
|
||||
#define SYS_FGETPOS_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_FGETPOS64_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_OPEN64_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_PREAD_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_PWRITE_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_PWRITE64_X_VERSION "GLIBC_2.2"
|
||||
#else /* WSIZE(64) */
|
||||
#define SYS_PTHREAD_CREATE_VERSION "GLIBC_2.2.5"
|
||||
#define SYS_DLOPEN_VERSION "GLIBC_2.2.5"
|
||||
#define SYS_POPEN_VERSION "GLIBC_2.2.5"
|
||||
#define SYS_TIMER_X_VERSION "GLIBC_2.3.3"
|
||||
#define SYS_FOPEN_X_VERSION "GLIBC_2.2.5"
|
||||
#define SYS_FGETPOS_X_VERSION "GLIBC_2.2.5"
|
||||
#endif
|
||||
|
||||
#elif ARCH(SPARC)
|
||||
#define SYS_LIBC_NAME "libc.so.6"
|
||||
#define SYS_DLOPEN_VERSION "GLIBC_2.1"
|
||||
#if WSIZE(32)
|
||||
#define SYS_PTHREAD_CREATE_VERSION "GLIBC_2.1"
|
||||
#define SYS_POPEN_VERSION "GLIBC_2.1"
|
||||
#define SYS_FOPEN_X_VERSION "GLIBC_2.1"
|
||||
#define SYS_FGETPOS_X_VERSION "GLIBC_2.2"
|
||||
#else /* WSIZE(64) */
|
||||
#define SYS_PTHREAD_CREATE_VERSION "GLIBC_2.2"
|
||||
#define SYS_POPEN_VERSION "GLIBC_2.2"
|
||||
#define SYS_TIMER_X_VERSION "GLIBC_2.3.3"
|
||||
#define SYS_FOPEN_X_VERSION "GLIBC_2.2"
|
||||
#define SYS_FGETPOS_X_VERSION "GLIBC_2.2"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
140
gprofng/libcollector/collectorAPI.c
Normal file
140
gprofng/libcollector/collectorAPI.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* C and Fortran stubs for collector API */
|
||||
|
||||
#include "config.h"
|
||||
#include <dlfcn.h>
|
||||
#include "gp-defs.h"
|
||||
#include "collectorAPI.h"
|
||||
#include "gp-experiment.h"
|
||||
|
||||
static void *__real_collector_sample = NULL;
|
||||
static void *__real_collector_pause = NULL;
|
||||
static void *__real_collector_resume = NULL;
|
||||
static void *__real_collector_terminate_expt = NULL;
|
||||
static void *__real_collector_func_load = NULL;
|
||||
static void *__real_collector_func_unload = NULL;
|
||||
|
||||
#define INIT_API if (init_API == 0) collectorAPI_initAPI()
|
||||
#define NULL_PTR(x) (__real_##x == NULL)
|
||||
#define CALL_REAL(x) (*(void(*)())__real_##x)
|
||||
#define CALL_IF_REAL(x) INIT_API; if (!NULL_PTR(x)) CALL_REAL(x)
|
||||
|
||||
static int init_API = 0;
|
||||
|
||||
void
|
||||
collectorAPI_initAPI (void)
|
||||
{
|
||||
void *libcollector = dlopen (SP_LIBCOLLECTOR_NAME, RTLD_NOLOAD);
|
||||
if (libcollector == NULL)
|
||||
libcollector = RTLD_DEFAULT;
|
||||
__real_collector_sample = dlsym (libcollector, "__collector_sample");
|
||||
__real_collector_pause = dlsym (libcollector, "__collector_pause");
|
||||
__real_collector_resume = dlsym (libcollector, "__collector_resume");
|
||||
__real_collector_terminate_expt = dlsym (libcollector, "__collector_terminate_expt");
|
||||
__real_collector_func_load = dlsym (libcollector, "__collector_func_load");
|
||||
__real_collector_func_unload = dlsym (libcollector, "__collector_func_unload");
|
||||
init_API = 1;
|
||||
}
|
||||
|
||||
/* initialization -- init section routine */
|
||||
static void collectorAPI_init () __attribute__ ((constructor));
|
||||
|
||||
static void
|
||||
collectorAPI_init (void)
|
||||
{
|
||||
collectorAPI_initAPI ();
|
||||
}
|
||||
|
||||
/* C API */
|
||||
void
|
||||
collector_pause (void)
|
||||
{
|
||||
CALL_IF_REAL (collector_pause)();
|
||||
}
|
||||
|
||||
void
|
||||
collector_resume (void)
|
||||
{
|
||||
CALL_IF_REAL (collector_resume)();
|
||||
}
|
||||
|
||||
void
|
||||
collector_sample (const char *name)
|
||||
{
|
||||
CALL_IF_REAL (collector_sample)(name);
|
||||
}
|
||||
|
||||
void
|
||||
collector_terminate_expt (void)
|
||||
{
|
||||
CALL_IF_REAL (collector_terminate_expt)();
|
||||
}
|
||||
|
||||
void
|
||||
collector_func_load (const char *name, const char *alias, const char *sourcename,
|
||||
void *vaddr, int size, int lntsize, Lineno *lntable)
|
||||
{
|
||||
CALL_IF_REAL (collector_func_load)(name, alias, sourcename,
|
||||
vaddr, size, lntsize, lntable);
|
||||
}
|
||||
|
||||
void
|
||||
collector_func_unload (void *vaddr)
|
||||
{
|
||||
CALL_IF_REAL (collector_func_unload)(vaddr);
|
||||
}
|
||||
|
||||
/* Fortran API */
|
||||
void
|
||||
collector_pause_ (void)
|
||||
{
|
||||
CALL_IF_REAL (collector_pause)();
|
||||
}
|
||||
|
||||
void
|
||||
collector_resume_ (void)
|
||||
{
|
||||
CALL_IF_REAL (collector_resume)();
|
||||
}
|
||||
|
||||
void
|
||||
collector_terminate_expt_ (void)
|
||||
{
|
||||
CALL_IF_REAL (collector_terminate_expt)();
|
||||
}
|
||||
|
||||
void
|
||||
collector_sample_ (char *name, long name_length)
|
||||
{
|
||||
INIT_API;
|
||||
if (!NULL_PTR (collector_sample))
|
||||
{
|
||||
char name_string[256];
|
||||
long length = sizeof (name_string) - 1;
|
||||
if (name_length < length)
|
||||
length = name_length;
|
||||
for (long i = 0; i < length; i++)
|
||||
name_string[i] = name[i];
|
||||
name_string[length] = '\0';
|
||||
CALL_REAL (collector_sample)(name_string);
|
||||
}
|
||||
}
|
18081
gprofng/libcollector/configure
vendored
Executable file
18081
gprofng/libcollector/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
60
gprofng/libcollector/configure.ac
Normal file
60
gprofng/libcollector/configure.ac
Normal file
|
@ -0,0 +1,60 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl This file is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 3 of the License, or
|
||||
dnl (at your option) any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
dnl GNU General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; see the file COPYING3. If not see
|
||||
dnl <http://www.gnu.org/licenses/>.
|
||||
|
||||
m4_include([../../bfd/version.m4])
|
||||
AC_INIT([gprofng], BFD_VERSION)
|
||||
AC_CONFIG_MACRO_DIRS([../../config ../..])
|
||||
AC_CONFIG_AUX_DIR(../..)
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_CONFIG_SRCDIR(libcol_util.c)
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
AM_PROG_AR
|
||||
|
||||
LT_INIT
|
||||
AC_ENABLE_SHARED
|
||||
AC_DISABLE_STATIC
|
||||
|
||||
if test "$enable_shared" != "yes"; then
|
||||
AC_MSG_ERROR([Cannot set --enable-shared for gprofng/libcollector.])
|
||||
fi
|
||||
|
||||
GPROFNG_VARIANT=unknown
|
||||
case "${target}" in
|
||||
x86_64-*-linux*)
|
||||
GPROFNG_VARIANT=amd64-Linux
|
||||
;;
|
||||
i?86-*-linux*)
|
||||
GPROFNG_VARIANT=intel-Linux
|
||||
;;
|
||||
aarch64-*-linux*)
|
||||
GPROFNG_VARIANT=aarch64-Linux
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(GPROFNG_VARIANT)
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_HEADERS([lib-config.h:../common/config.h.in])
|
||||
AC_OUTPUT
|
||||
|
81
gprofng/libcollector/descendants.h
Normal file
81
gprofng/libcollector/descendants.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Lineage events for process fork, exec, etc. */
|
||||
|
||||
#ifndef DESCENDANTS_H
|
||||
#define DESCENDANTS_H
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gp-defs.h"
|
||||
#include "gp-experiment.h"
|
||||
#include "collector.h"
|
||||
#include "memmgr.h"
|
||||
#include "cc_libcollector.h"
|
||||
#include "tsd.h"
|
||||
|
||||
/* configuration, not changed after init. */
|
||||
typedef enum
|
||||
{
|
||||
LM_DORMANT = -2, /* env vars preserved, not recording */
|
||||
LM_CLOSED = -1, /* env vars cleared, not recording */
|
||||
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 */
|
||||
extern unsigned line_key;
|
||||
extern char **sp_env_backup;
|
||||
|
||||
#define INIT_REENTRANCE(x) ((x) = __collector_tsd_get_by_key (line_key))
|
||||
#define CHCK_REENTRANCE(x) (((INIT_REENTRANCE(x)) == NULL) || (*(x) != 0))
|
||||
#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 ();
|
||||
extern void __collector_env_backup_free ();
|
||||
extern void __collector_env_update (char *envp[]);
|
||||
extern void __collector_env_print (char *label);
|
||||
extern void __collector_env_printall (char *label, char *envp[]);
|
||||
extern char ** __collector_env_allocate (char *const old_env[], int allocate_env);
|
||||
|
||||
#endif
|
1263
gprofng/libcollector/dispatcher.c
Normal file
1263
gprofng/libcollector/dispatcher.c
Normal file
File diff suppressed because it is too large
Load diff
840
gprofng/libcollector/envmgmt.c
Normal file
840
gprofng/libcollector/envmgmt.c
Normal file
|
@ -0,0 +1,840 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* Routines for managing the target's environment array
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "descendants.h"
|
||||
|
||||
#define MAX_LD_PRELOADS 2
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
#define DBG_LT4 4
|
||||
|
||||
/* original environment settings to be saved for later restoration */
|
||||
static char *sp_preloads[MAX_LD_PRELOADS];
|
||||
static char *sp_libpaths[MAX_LD_PRELOADS];
|
||||
char **sp_env_backup;
|
||||
|
||||
static const char *SP_ENV[];
|
||||
static const char *LD_ENV[];
|
||||
static const char *SP_PRELOAD[];
|
||||
static const char *LD_PRELOAD[];
|
||||
static const char *SP_LIBRARY_PATH[];
|
||||
static const char *LD_LIBRARY_PATH[];
|
||||
static int NUM_SP_ENV_VARS;
|
||||
static int NUM_LD_ENV_VARS;
|
||||
static int NUM_SP_PRELOADS;
|
||||
static int NUM_LD_PRELOADS;
|
||||
static int NUM_SP_LIBPATHS;
|
||||
static int NUM_LD_LIBPATHS;
|
||||
|
||||
static const char *SP_ENV[] = {
|
||||
SP_COLLECTOR_PARAMS, /* data descriptor */
|
||||
SP_COLLECTOR_EXPNAME, /* experiment name */
|
||||
SP_COLLECTOR_FOLLOW_SPEC, /* linetrace */
|
||||
SP_COLLECTOR_FOUNDER, /* determine founder exp */
|
||||
SP_PRELOAD_STRINGS, /* LD_PRELOADs for data collection */
|
||||
SP_LIBPATH_STRINGS, /* LD_LIBRARY_PATHs for data collection */
|
||||
"SP_COLLECTOR_TRACELEVEL", /* tprintf */
|
||||
#if DEBUG
|
||||
"SP_COLLECTOR_SIGACTION", /* dispatcher, hwprofile */
|
||||
#endif
|
||||
/* JAVA* */
|
||||
/* LD_DEBUG=audit,bindings,detail */
|
||||
/* LD_ORIGIN=yes */
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *LD_ENV[] = {
|
||||
LD_PRELOAD_STRINGS, /* LD_PRELOADs */
|
||||
LD_LIBPATH_STRINGS, /* LD_LIBRARY_PATHs */
|
||||
JAVA_TOOL_OPTIONS, /* enable -agentlib:collector for JVMTI */
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *SP_PRELOAD[] = {
|
||||
SP_PRELOAD_STRINGS,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *LD_PRELOAD[] = {
|
||||
LD_PRELOAD_STRINGS,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *SP_LIBRARY_PATH[] = {
|
||||
SP_LIBPATH_STRINGS,
|
||||
NULL
|
||||
};
|
||||
static const char *LD_LIBRARY_PATH[] = {
|
||||
LD_LIBPATH_STRINGS,
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
__collector_env_save_preloads ()
|
||||
{
|
||||
/* save the list of SP_PRELOADs */
|
||||
int v;
|
||||
for (v = 0; SP_PRELOAD[v]; v++)
|
||||
{
|
||||
sp_preloads[v] = __collector_strdup (CALL_UTIL (getenv)(SP_PRELOAD[v]));
|
||||
TprintfT (DBG_LT3, "__collector_env_save_preloads: %s=%s\n", SP_PRELOAD[v], sp_preloads[v]);
|
||||
}
|
||||
NUM_SP_PRELOADS = v;
|
||||
for (v = 0; SP_LIBRARY_PATH[v]; v++)
|
||||
{
|
||||
sp_libpaths[v] = __collector_strdup (CALL_UTIL (getenv)(SP_LIBRARY_PATH[v]));
|
||||
TprintfT (DBG_LT4, "__collector_env_save_preloads: %s=%s\n", SP_LIBRARY_PATH[v],
|
||||
sp_libpaths[v] ? sp_libpaths[v] : "NULL");
|
||||
}
|
||||
NUM_SP_LIBPATHS = v;
|
||||
for (v = 0; LD_PRELOAD[v]; v++)
|
||||
;
|
||||
NUM_LD_PRELOADS = v;
|
||||
for (v = 0; LD_LIBRARY_PATH[v]; v++)
|
||||
;
|
||||
NUM_LD_LIBPATHS = v;
|
||||
for (v = 0; SP_ENV[v]; v++)
|
||||
;
|
||||
NUM_SP_ENV_VARS = v;
|
||||
for (v = 0; LD_ENV[v]; v++)
|
||||
;
|
||||
NUM_LD_ENV_VARS = v;
|
||||
}
|
||||
|
||||
/* free the memory involved in backing up the environment */
|
||||
void
|
||||
__collector_env_backup_free ()
|
||||
{
|
||||
int v = 0;
|
||||
TprintfT (DBG_LT2, "env_backup_free()\n");
|
||||
for (v = 0; sp_env_backup[v]; v++)
|
||||
{
|
||||
TprintfT (DBG_LT2, "env_backup_free():sp_env_backup[%d]=%s \n", v, sp_env_backup[v]);
|
||||
__collector_freeCSize (__collector_heap, (char *) sp_env_backup[v], __collector_strlen (sp_env_backup[v]) + 1);
|
||||
}
|
||||
__collector_freeCSize (__collector_heap, (char**) sp_env_backup,
|
||||
(NUM_SP_ENV_VARS + NUM_LD_ENV_VARS + 1) * sizeof (char*));
|
||||
}
|
||||
|
||||
char **
|
||||
__collector_env_backup ()
|
||||
{
|
||||
TprintfT (DBG_LT2, "env_backup_()\n");
|
||||
char **backup = __collector_env_allocate (NULL, 1);
|
||||
__collector_env_update (backup);
|
||||
TprintfT (DBG_LT2, "env_backup_()\n");
|
||||
return backup;
|
||||
}
|
||||
|
||||
/*
|
||||
function: env_prepend()
|
||||
given an <old_str>, check to see if <str>
|
||||
is already defined by it. If not, allocate
|
||||
a new string and concat <envvar>=<str><separator><old_str>
|
||||
params:
|
||||
old_str: original string
|
||||
str: substring to prepend
|
||||
return: pointer to updated string or NULL if string was not updated.
|
||||
*/
|
||||
static char *
|
||||
env_prepend (const char *envvar, const char *str, const char *separator,
|
||||
const char *old_str)
|
||||
{
|
||||
if (!envvar || *envvar == 0 || !str || *str == 0)
|
||||
{
|
||||
/* nothing to do */
|
||||
TprintfT (DBG_LT2, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\") -- nothing to do\n",
|
||||
envvar, str, separator, old_str);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
TprintfT (DBG_LT2, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\")\n",
|
||||
envvar, str, separator, old_str);
|
||||
char *ev;
|
||||
size_t strsz;
|
||||
if (!old_str || *old_str == 0)
|
||||
{
|
||||
strsz = __collector_strlen (envvar) + 1 + __collector_strlen (str) + 1;
|
||||
ev = (char*) __collector_allocCSize (__collector_heap, strsz, 1);
|
||||
if (ev)
|
||||
{
|
||||
CALL_UTIL (snprintf)(ev, strsz, "%s=%s", envvar, str);
|
||||
assert (__collector_strlen (ev) + 1 == strsz);
|
||||
}
|
||||
else
|
||||
TprintfT (DBG_LT2, "env_prepend(): could not allocate memory\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p = CALL_UTIL (strstr)(old_str, str);
|
||||
if (p)
|
||||
{
|
||||
TprintfT (DBG_LT2, "env_prepend(): %s=%s was already set\n",
|
||||
envvar, old_str);
|
||||
return NULL;
|
||||
}
|
||||
strsz = __collector_strlen (envvar) + 1 + __collector_strlen (str) +
|
||||
__collector_strlen (separator) + __collector_strlen (old_str) + 1;
|
||||
ev = (char*) __collector_allocCSize (__collector_heap, strsz, 1);
|
||||
if (ev)
|
||||
{
|
||||
CALL_UTIL (snprintf)(ev, strsz, "%s=%s%s%s", envvar, str, separator, old_str);
|
||||
assert (__collector_strlen (ev) + 1 == strsz);
|
||||
}
|
||||
else
|
||||
TprintfT (DBG_LT2, "env_prepend(): could not allocate memory\n");
|
||||
}
|
||||
TprintfT (DBG_LT2, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\") returns \"%s\"\n",
|
||||
envvar, str, separator, old_str, (ev == NULL ? "NULL" : ev));
|
||||
return ev;
|
||||
}
|
||||
|
||||
/*
|
||||
function: putenv_prepend()
|
||||
get environment variable <envvar>, check to see if <str>
|
||||
is already defined by it. If not prepend <str>
|
||||
and put it back to environment.
|
||||
params:
|
||||
envvar: environment variable
|
||||
str: substring to find
|
||||
return: 0==success, nonzero on failure.
|
||||
*/
|
||||
int
|
||||
putenv_prepend (const char *envvar, const char *str, const char *separator)
|
||||
{
|
||||
if (!envvar || *envvar == 0)
|
||||
return 1;
|
||||
const char * old_str = CALL_UTIL (getenv)(envvar);
|
||||
char * newstr = env_prepend (envvar, str, separator, old_str);
|
||||
if (newstr)
|
||||
// now put the new variable into the environment
|
||||
if (CALL_UTIL (putenv)(newstr) != 0)
|
||||
{
|
||||
TprintfT (DBG_LT2, "putenv_prepend(): ERROR %s is not set!\n", newstr);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
function: env_strip()
|
||||
Finds substr in origstr; Removes
|
||||
all characters from previous ':' or ' '
|
||||
up to and including any trailing ':' or ' '.
|
||||
params:
|
||||
env: environment variable contents
|
||||
str: substring to find
|
||||
return: count of instances removed from env
|
||||
*/
|
||||
static int
|
||||
env_strip (char *origstr, const char *substr)
|
||||
{
|
||||
int removed = 0;
|
||||
char *p, *q;
|
||||
if (origstr == NULL || substr == NULL || *substr == 0)
|
||||
return 0;
|
||||
while ((p = q = CALL_UTIL (strstr)(origstr, substr)))
|
||||
{
|
||||
p += __collector_strlen (substr);
|
||||
while (*p == ':' || *p == ' ') /* strip trailing separator */
|
||||
p++;
|
||||
while (*q != ':' && *q != ' ' && *q != '=' && q != origstr) /* strip path */
|
||||
q--;
|
||||
if (q != origstr) /* restore leading separator (if any) */
|
||||
q++;
|
||||
__collector_strlcpy (q, p, __collector_strlen (p) + 1);
|
||||
removed++;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
/*
|
||||
function: env_ld_preload_strip()
|
||||
Removes known libcollector shared objects from envv.
|
||||
params:
|
||||
var: shared object name (leading characters don't have to match)
|
||||
return: 0 = so's removed, non-zero = so's not found.
|
||||
*/
|
||||
static int
|
||||
env_ld_preload_strip (char *envv)
|
||||
{
|
||||
if (!envv || *envv == 0)
|
||||
{
|
||||
TprintfT (DBG_LT2, "env_ld_preload_strip(): WARNING - envv is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_env_print (char * label)
|
||||
{
|
||||
#if DEBUG
|
||||
TprintfT (DBG_LT2, "__collector_env_print(%s)\n", label);
|
||||
for (int v = 0; v < MAX_LD_PRELOADS; v++)
|
||||
TprintfT (DBG_LT2, " %s sp_preloads[%d] (0x%p)=%s\n", label,
|
||||
v, sp_preloads[v], (sp_preloads[v] == NULL ? "NULL" : sp_preloads[v]));
|
||||
for (int v = 0; SP_ENV[v]; v++)
|
||||
{
|
||||
char *s = CALL_UTIL (getenv)(SP_ENV[v]);
|
||||
if (s == NULL)
|
||||
s = "<null>";
|
||||
TprintfT (DBG_LT2, " %s SP_ENV[%d] (0x%p): %s=\"%s\"\n", label, v, SP_ENV[v], SP_ENV[v], s);
|
||||
}
|
||||
for (int v = 0; LD_ENV[v]; v++)
|
||||
{
|
||||
char *s = CALL_UTIL (getenv)(LD_ENV[v]);
|
||||
if (s == NULL)
|
||||
s = "<null>";
|
||||
TprintfT (DBG_LT2, " %s LD_ENV[%d] (0x%p): %s=\"%s\"\n", label, v, LD_ENV[v], LD_ENV[v], s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
__collector_env_printall (char *label, char *envp[])
|
||||
{
|
||||
#if DEBUG
|
||||
TprintfT (DBG_LT2, "__collector_env_printall(%s): environment @ 0x%p\n", label, envp);
|
||||
for (int i = 0; envp[i]; i++)
|
||||
Tprintf (DBG_LT2, "\tenv[%d]@0x%p == %s\n", i, envp[i], envp[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* match collector environment variable */
|
||||
int
|
||||
env_match (char *envp[], const char *envvar)
|
||||
{
|
||||
int match = -1;
|
||||
if (envp == NULL)
|
||||
TprintfT (DBG_LT1, "env_match(%s): NULL envp!\n", envvar);
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
while ((envp[i] != NULL) && (__collector_strStartWith (envp[i], envvar)))
|
||||
i++;
|
||||
if ((envp[i] == NULL) || (envp[i][__collector_strlen (envvar)] != '='))
|
||||
TprintfT (DBG_LT4, "env_match(): @%p []%s not defined in envp\n", envp, envvar);
|
||||
else
|
||||
{
|
||||
TprintfT (DBG_LT4, "env_match(): @%p [%d]%s defined in envp\n", envp, i, envp[i]);
|
||||
match = i;
|
||||
}
|
||||
}
|
||||
TprintfT (DBG_LT1, "env_match(%s): found in slot %d\n", envvar, match);
|
||||
return (match);
|
||||
}
|
||||
|
||||
/* allocate new environment with collector variables */
|
||||
/* 1) copy all current envp[] ptrs into a new array, coll_env[] */
|
||||
/* 2) if collector-related env ptrs not in envp[], append them to coll_env */
|
||||
/* from processes' "environ" (allocate_env==1) */
|
||||
/* or from sp_env_backup (allocate_env==0)*/
|
||||
/* If they already exist in envp, probably is an error... */
|
||||
/* 3) return coll_env */
|
||||
|
||||
/* __collector__env_update() need be called after this to set LD_ENV*/
|
||||
char **
|
||||
__collector_env_allocate (char *const old_env[], int allocate_env)
|
||||
{
|
||||
extern char **environ; /* the process' actual environment */
|
||||
char **new_env; /* a new environment for collection */
|
||||
TprintfT (DBG_LT3, "__collector_env_allocate(old_env=0x%p %s environ=0x%p)\n",
|
||||
old_env, (old_env == environ) ? "==" : "!=", environ);
|
||||
/* set up a copy of the provided old_env for collector use */
|
||||
int old_env_size = 0;
|
||||
|
||||
/* determine number of (used) slots in old_env */
|
||||
if (old_env)
|
||||
while (old_env[old_env_size] != NULL)
|
||||
old_env_size++;
|
||||
/* allocate a new vector with additional slots */
|
||||
int new_env_alloc_sz = old_env_size + NUM_SP_ENV_VARS + NUM_LD_ENV_VARS + 1;
|
||||
new_env = (char**) __collector_allocCSize (__collector_heap, new_env_alloc_sz * sizeof (char*), 1);
|
||||
if (new_env == NULL)
|
||||
return NULL;
|
||||
TprintfT (DBG_LT4, "__collector_env_allocate(): old_env has %d entries, new_env @ 0x%p\n", old_env_size, new_env);
|
||||
|
||||
/* copy provided old_env pointers to new collector environment */
|
||||
int new_env_size = 0;
|
||||
for (new_env_size = 0; new_env_size < old_env_size; new_env_size++)
|
||||
new_env[new_env_size] = old_env[new_env_size];
|
||||
|
||||
/* check each required environment variable, adding as required */
|
||||
const char * env_var;
|
||||
int v;
|
||||
for (v = 0; (env_var = SP_ENV[v]) != NULL; v++)
|
||||
{
|
||||
if (env_match ((char**) old_env, env_var) == -1)
|
||||
{
|
||||
int idx;
|
||||
/* not found in old_env */
|
||||
if (allocate_env)
|
||||
{
|
||||
if ((idx = env_match (environ, env_var)) != -1)
|
||||
{
|
||||
/* found in environ */
|
||||
TprintfT (DBG_LT4, "__collector_env_allocate(): [%d]%s env restored!\n",
|
||||
new_env_size, environ[idx]);
|
||||
int varsz = __collector_strlen (environ[idx]) + 1;
|
||||
char * var = (char*) __collector_allocCSize (__collector_heap, varsz, 1);
|
||||
if (var == NULL)
|
||||
return NULL;
|
||||
__collector_strlcpy (var, environ[idx], varsz);
|
||||
new_env[new_env_size++] = var;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not found in environ */
|
||||
if ((__collector_strcmp (env_var, SP_COLLECTOR_PARAMS) == 0) ||
|
||||
(__collector_strcmp (env_var, SP_COLLECTOR_EXPNAME) == 0))
|
||||
TprintfT (DBG_LT1, "__collector_env_allocate(): note: %s environment variable not found\n",
|
||||
env_var);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((idx = env_match (sp_env_backup, env_var)) != -1)
|
||||
{
|
||||
/* found in backup */
|
||||
TprintfT (DBG_LT4, "__collector_env_allocate(): [%d]%s env restored!\n",
|
||||
new_env_size, sp_env_backup[idx]);
|
||||
new_env[new_env_size++] = sp_env_backup[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not found in environ */
|
||||
if ((__collector_strcmp (env_var, SP_COLLECTOR_PARAMS) == 0) ||
|
||||
(__collector_strcmp (env_var, SP_COLLECTOR_EXPNAME) == 0))
|
||||
TprintfT (DBG_LT1, "__collector_env_allocate(): note: %s environment variable not found\n",
|
||||
env_var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (v = 0; (env_var = LD_ENV[v]) != NULL; v++)
|
||||
{
|
||||
if (env_match ((char**) old_env, env_var) == -1)
|
||||
{
|
||||
int idx;
|
||||
/* not found in old_env */
|
||||
if (allocate_env)
|
||||
{
|
||||
if ((idx = env_match (environ, env_var)) != -1)
|
||||
{
|
||||
/* found in environ */
|
||||
TprintfT (DBG_LT4, "__collector_env_allocate(): [%d]%s env restored!\n",
|
||||
new_env_size, environ[idx]);
|
||||
|
||||
int varsz = __collector_strlen (env_var) + 2;
|
||||
char * var = (char*) __collector_allocCSize (__collector_heap, varsz, 1);
|
||||
if (var == NULL)
|
||||
return NULL;
|
||||
// assume __collector_env_update() will fill content of env_var
|
||||
CALL_UTIL (snprintf)(var, varsz, "%s=", env_var);
|
||||
new_env[new_env_size++] = var;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((idx = env_match (sp_env_backup, env_var)) != -1)
|
||||
{
|
||||
/* found in backup */
|
||||
TprintfT (DBG_LT4, "__collector_env_allocate(): [%d]%s env restored!\n",
|
||||
new_env_size, sp_env_backup[idx]);
|
||||
new_env[new_env_size++] = sp_env_backup[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ensure new_env vector ends with NULL */
|
||||
new_env[new_env_size] = NULL;
|
||||
assert (new_env_size <= new_env_alloc_sz);
|
||||
TprintfT (DBG_LT4, "__collector_env_allocate(): new_env has %d entries (%d added), new_env=0x%p\n",
|
||||
new_env_size, new_env_size - old_env_size, new_env);
|
||||
if (new_env_size != old_env_size && !allocate_env)
|
||||
__collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
|
||||
SP_JCMD_CWARN, COL_WARN_EXECENV, new_env_size - old_env_size);
|
||||
__collector_env_printall ("__collector_env_allocate", new_env);
|
||||
return (new_env);
|
||||
}
|
||||
|
||||
/* unset collection environment variables */
|
||||
/* if they exist in env... */
|
||||
/* 1) push non-collectorized version to env */
|
||||
|
||||
/* Not mt safe */
|
||||
void
|
||||
__collector_env_unset (char *envp[])
|
||||
{
|
||||
int v;
|
||||
const char * env_name;
|
||||
TprintfT (DBG_LT3, "env_unset(envp=0x%p)\n", envp);
|
||||
if (envp == NULL)
|
||||
{
|
||||
for (v = 0; (env_name = LD_PRELOAD[v]); v++)
|
||||
{
|
||||
const char *env_val = CALL_UTIL (getenv)(env_name);
|
||||
if (env_val && CALL_UTIL (strstr)(env_val, sp_preloads[v]))
|
||||
{
|
||||
size_t sz = __collector_strlen (env_name) + 1 + __collector_strlen (env_val) + 1;
|
||||
char * ev = (char*) __collector_allocCSize (__collector_heap, sz, 1);
|
||||
if (ev == NULL)
|
||||
return;
|
||||
CALL_UTIL (snprintf)(ev, sz, "%s=%s", env_name, env_val);
|
||||
assert (__collector_strlen (ev) + 1 == sz);
|
||||
TprintfT (DBG_LT4, "env_unset(): old %s\n", ev);
|
||||
env_ld_preload_strip (ev);
|
||||
CALL_UTIL (putenv)(ev);
|
||||
TprintfT (DBG_LT4, "env_unset(): new %s\n", ev);
|
||||
}
|
||||
}
|
||||
// unset JAVA_TOOL_OPTIONS
|
||||
env_name = JAVA_TOOL_OPTIONS;
|
||||
const char * env_val = CALL_UTIL (getenv)(env_name);
|
||||
if (env_val && CALL_UTIL (strstr)(env_val, COLLECTOR_JVMTI_OPTION))
|
||||
{
|
||||
size_t sz = __collector_strlen (env_name) + 1 + __collector_strlen (env_val) + 1;
|
||||
char * ev = (char*) __collector_allocCSize (__collector_heap, sz, 1);
|
||||
if (ev == NULL)
|
||||
return;
|
||||
CALL_UTIL (snprintf)(ev, sz, "%s=%s", env_name, env_val);
|
||||
assert (__collector_strlen (ev) + 1 == sz);
|
||||
TprintfT (DBG_LT4, "env_unset(): old %s\n", ev);
|
||||
env_strip (ev, COLLECTOR_JVMTI_OPTION);
|
||||
CALL_UTIL (putenv)(ev);
|
||||
TprintfT (DBG_LT4, "env_unset(): new %s\n", ev);
|
||||
}
|
||||
__collector_env_print ("__collector_env_unset");
|
||||
}
|
||||
else
|
||||
{
|
||||
__collector_env_printall ("__collector_env_unset, before", envp);
|
||||
for (v = 0; (env_name = LD_PRELOAD[v]); v++)
|
||||
{
|
||||
int idx = env_match (envp, env_name);
|
||||
if (idx != -1)
|
||||
{
|
||||
char *env_val = envp[idx];
|
||||
TprintfT (DBG_LT4, "env_unset(): old %s\n", env_val);
|
||||
envp[idx] = "junk="; /* xxxx is it ok to use original string? */
|
||||
env_ld_preload_strip (env_val);
|
||||
envp[idx] = env_val;
|
||||
TprintfT (DBG_LT4, "env_unset(): new %s\n", envp[idx]);
|
||||
}
|
||||
}
|
||||
// unset JAVA_TOOL_OPTIONS
|
||||
env_name = JAVA_TOOL_OPTIONS;
|
||||
int idx = env_match(envp, env_name);
|
||||
if (idx != -1) {
|
||||
char *env_val = envp[idx];
|
||||
TprintfT(DBG_LT4, "env_unset(): old %s\n", env_val);
|
||||
envp[idx] = "junk="; /* xxxx is it ok to use original string? */
|
||||
env_strip(env_val, COLLECTOR_JVMTI_OPTION);
|
||||
envp[idx] = env_val;
|
||||
TprintfT(DBG_LT4, "env_unset(): new %s\n", envp[idx]);
|
||||
}
|
||||
__collector_env_printall ("__collector_env_unset, after", envp );
|
||||
}
|
||||
}
|
||||
|
||||
/* update collection environment variables */
|
||||
/* update LD_PRELOADs and push them */
|
||||
/* not mt safe */
|
||||
void
|
||||
__collector_env_update (char *envp[])
|
||||
{
|
||||
const char *env_name;
|
||||
TprintfT (DBG_LT1, "__collector_env_update(envp=0x%p)\n", envp);
|
||||
extern char **environ;
|
||||
if (envp == NULL)
|
||||
{
|
||||
int v;
|
||||
TprintfT (DBG_LT2, "__collector_env_update(envp=NULL)\n");
|
||||
__collector_env_printall (" environ array, before", environ);
|
||||
__collector_env_print (" env_update at entry ");
|
||||
|
||||
/* SP_ENV */
|
||||
for (v = 0; (env_name = SP_ENV[v]) != NULL; v++)
|
||||
{
|
||||
if (env_match (environ, env_name) == -1)
|
||||
{
|
||||
int idx;
|
||||
if ((idx = env_match (sp_env_backup, env_name)) != -1)
|
||||
{
|
||||
unsigned strsz = __collector_strlen (sp_env_backup[idx]) + 1;
|
||||
char *ev = (char*) __collector_allocCSize (__collector_heap, strsz, 1);
|
||||
CALL_UTIL (snprintf)(ev, strsz, "%s", sp_env_backup[idx]);
|
||||
if (CALL_UTIL (putenv)(ev) != 0)
|
||||
TprintfT (DBG_LT2, "__collector_env_update(): ERROR %s is not set!\n",
|
||||
sp_env_backup[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
__collector_env_print (" env_update after SP_ENV settings ");
|
||||
|
||||
/* LD_LIBRARY_PATH */
|
||||
for (v = 0; (env_name = LD_LIBRARY_PATH[v]); v++)
|
||||
/* assumes same index used between LD and SP vars */
|
||||
if (putenv_prepend (env_name, sp_libpaths[v], ":"))
|
||||
TprintfT (DBG_LT2, "collector: ERROR %s=%s could not be set\n",
|
||||
env_name, sp_libpaths[v]);
|
||||
__collector_env_print (" env_update after LD_LIBRARY_PATH settings ");
|
||||
|
||||
/* LD_PRELOAD */
|
||||
for (v = 0; (env_name = LD_PRELOAD[v]); v++)
|
||||
/* assumes same index used between LD and SP vars */
|
||||
if (putenv_prepend (env_name, sp_preloads[v], " "))
|
||||
TprintfT (DBG_LT2, "collector: ERROR %s=%s could not be set\n",
|
||||
env_name, sp_preloads[v]);
|
||||
__collector_env_print (" env_update after LD_PRELOAD settings ");
|
||||
|
||||
/* JAVA_TOOL_OPTIONS */
|
||||
if (java_mode)
|
||||
if (putenv_prepend (JAVA_TOOL_OPTIONS, COLLECTOR_JVMTI_OPTION, " "))
|
||||
TprintfT (DBG_LT2, "collector: ERROR %s=%s could not be set\n",
|
||||
JAVA_TOOL_OPTIONS, COLLECTOR_JVMTI_OPTION);
|
||||
__collector_env_print (" env_update after JAVA_TOOL settings ");
|
||||
}
|
||||
else
|
||||
{
|
||||
int v;
|
||||
int idx;
|
||||
TprintfT (DBG_LT2, "__collector_env_update(envp=0x%p) not NULL\n", envp);
|
||||
__collector_env_printall ("__collector_env_update, before", envp);
|
||||
/* LD_LIBRARY_PATH */
|
||||
for (v = 0; (env_name = LD_LIBRARY_PATH[v]); v++)
|
||||
{
|
||||
int idx = env_match (envp, env_name);
|
||||
if (idx != -1)
|
||||
{
|
||||
char *env_val = __collector_strchr (envp[idx], '=');
|
||||
if (env_val)
|
||||
env_val++; /* skip '=' */
|
||||
/* assumes same index used between LD and SP vars */
|
||||
char *new_str = env_prepend (env_name, sp_libpaths[v],
|
||||
":", env_val);
|
||||
if (new_str)
|
||||
envp[idx] = new_str;
|
||||
}
|
||||
}
|
||||
|
||||
/* LD_PRELOAD */
|
||||
for (v = 0; (env_name = LD_PRELOAD[v]); v++)
|
||||
{
|
||||
int idx = env_match (envp, env_name);
|
||||
if (idx != -1)
|
||||
{
|
||||
char *env_val = __collector_strchr (envp[idx], '=');
|
||||
if (env_val)
|
||||
env_val++; /* skip '=' */
|
||||
/* assumes same index used between LD and SP vars */
|
||||
char *new_str = env_prepend (env_name, sp_preloads[v],
|
||||
" ", env_val);
|
||||
if (new_str)
|
||||
envp[idx] = new_str;
|
||||
}
|
||||
}
|
||||
|
||||
/* JAVA_TOOL_OPTIONS */
|
||||
if (java_mode)
|
||||
{
|
||||
env_name = JAVA_TOOL_OPTIONS;
|
||||
idx = env_match (envp, env_name);
|
||||
if (idx != -1)
|
||||
{
|
||||
char *env_val = __collector_strchr (envp[idx], '=');
|
||||
if (env_val)
|
||||
env_val++; /* skip '=' */
|
||||
char *new_str = env_prepend (env_name, COLLECTOR_JVMTI_OPTION,
|
||||
" ", env_val);
|
||||
if (new_str)
|
||||
envp[idx] = new_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
__collector_env_printall ("__collector_env_update, after", environ);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------- putenv */
|
||||
int putenv () __attribute__ ((weak, alias ("__collector_putenv")));
|
||||
int _putenv () __attribute__ ((weak, alias ("__collector_putenv")));
|
||||
|
||||
int
|
||||
__collector_putenv (char * string)
|
||||
{
|
||||
if (CALL_UTIL (putenv) == __collector_putenv ||
|
||||
CALL_UTIL (putenv) == NULL)
|
||||
{ // __collector_libc_funcs_init failed
|
||||
CALL_UTIL (putenv) = (int(*)())dlsym (RTLD_NEXT, "putenv");
|
||||
if (CALL_UTIL (putenv) == NULL || CALL_UTIL (putenv) == __collector_putenv)
|
||||
CALL_UTIL (putenv) = (int(*)())dlsym (RTLD_DEFAULT, "putenv");
|
||||
if (CALL_UTIL (putenv) == NULL || CALL_UTIL (putenv) == __collector_putenv)
|
||||
{
|
||||
TprintfT (DBG_LT2, "__collector_putenv(): ERROR: no pointer found.\n");
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (user_follow_mode == FOLLOW_NONE)
|
||||
return CALL_UTIL (putenv)(string);
|
||||
char * envp[] = {string, NULL};
|
||||
__collector_env_update (envp);
|
||||
return CALL_UTIL (putenv)(envp[0]);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- setenv */
|
||||
int setenv () __attribute__ ((weak, alias ("__collector_setenv")));
|
||||
int _setenv () __attribute__ ((weak, alias ("__collector_setenv")));
|
||||
|
||||
int
|
||||
__collector_setenv (const char *name, const char *value, int overwrite)
|
||||
{
|
||||
if (CALL_UTIL (setenv) == __collector_setenv ||
|
||||
CALL_UTIL (setenv) == NULL)
|
||||
{ // __collector_libc_funcs_init failed
|
||||
CALL_UTIL (setenv) = (int(*)())dlsym (RTLD_NEXT, "setenv");
|
||||
if (CALL_UTIL (setenv) == NULL || CALL_UTIL (setenv) == __collector_setenv)
|
||||
CALL_UTIL (setenv) = (int(*)())dlsym (RTLD_DEFAULT, "setenv");
|
||||
if (CALL_UTIL (setenv) == NULL || CALL_UTIL (setenv) == __collector_setenv)
|
||||
{
|
||||
TprintfT (DBG_LT2, "__collector_setenv(): ERROR: no pointer found.\n");
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (user_follow_mode == FOLLOW_NONE || !overwrite)
|
||||
return CALL_UTIL (setenv)(name, value, overwrite);
|
||||
size_t sz = __collector_strlen (name) + 1 + __collector_strlen (value) + 1;
|
||||
char *ev = (char*) __collector_allocCSize (__collector_heap, sz, 1);
|
||||
if (ev == NULL)
|
||||
return CALL_UTIL (setenv)(name, value, overwrite);
|
||||
CALL_UTIL (snprintf)(ev, sz, "%s=%s", name, value);
|
||||
char * envp[] = {ev, NULL};
|
||||
__collector_env_update (envp);
|
||||
if (envp[0] == ev)
|
||||
{
|
||||
__collector_freeCSize (__collector_heap, ev, sz);
|
||||
return CALL_UTIL (setenv)(name, value, overwrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *env_val = __collector_strchr (envp[0], '=');
|
||||
if (env_val)
|
||||
{
|
||||
*env_val = '\0';
|
||||
env_val++; /* skip '=' */
|
||||
}
|
||||
return CALL_UTIL (setenv)(envp[0], env_val, overwrite);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- unsetenv */
|
||||
int unsetenv () __attribute__ ((weak, alias ("__collector_unsetenv")));
|
||||
int _unsetenv () __attribute__ ((weak, alias ("__collector_unsetenv")));
|
||||
|
||||
int
|
||||
__collector_unsetenv (const char *name)
|
||||
{
|
||||
if (CALL_UTIL (unsetenv) == __collector_unsetenv ||
|
||||
CALL_UTIL (unsetenv) == NULL)
|
||||
{ // __collector_libc_funcs_init failed
|
||||
CALL_UTIL (unsetenv) = (int(*)())dlsym (RTLD_NEXT, "unsetenv");
|
||||
if (CALL_UTIL (unsetenv) == NULL || CALL_UTIL (unsetenv) == __collector_unsetenv)
|
||||
CALL_UTIL (unsetenv) = (int(*)())dlsym (RTLD_DEFAULT, "unsetenv");
|
||||
if (CALL_UTIL (unsetenv) == NULL || CALL_UTIL (unsetenv) == __collector_unsetenv)
|
||||
{
|
||||
TprintfT (DBG_LT2, "__collector_unsetenv(): ERROR: no pointer found.\n");
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int ret = CALL_UTIL (unsetenv)(name);
|
||||
if (user_follow_mode == FOLLOW_NONE)
|
||||
return ret;
|
||||
TprintfT (DBG_LT2, "__collector_unsetenv(): %d.\n", user_follow_mode);
|
||||
size_t sz = __collector_strlen (name) + 1 + 1;
|
||||
char *ev = (char*) __collector_allocCSize (__collector_heap, sz, 1);
|
||||
if (ev == NULL)
|
||||
return ret;
|
||||
CALL_UTIL (snprintf)(ev, sz, "%s=", name);
|
||||
char * envp[] = {ev, NULL};
|
||||
__collector_env_update (envp);
|
||||
if (envp[0] == ev)
|
||||
__collector_freeCSize (__collector_heap, ev, sz);
|
||||
else
|
||||
CALL_UTIL (putenv)(envp[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- clearenv */
|
||||
int clearenv () __attribute__ ((weak, alias ("__collector_clearenv")));
|
||||
|
||||
int
|
||||
__collector_clearenv (void)
|
||||
{
|
||||
if (CALL_UTIL (clearenv) == __collector_clearenv || CALL_UTIL (clearenv) == NULL)
|
||||
{
|
||||
/* __collector_libc_funcs_init failed; look up clearenv now */
|
||||
CALL_UTIL (clearenv) = (int(*)())dlsym (RTLD_NEXT, "clearenv");
|
||||
if (CALL_UTIL (clearenv) == NULL || CALL_UTIL (clearenv) == __collector_clearenv)
|
||||
/* still not found; try again */
|
||||
CALL_UTIL (clearenv) = (int(*)())dlsym (RTLD_DEFAULT, "clearenv");
|
||||
if (CALL_UTIL (clearenv) == NULL || CALL_UTIL (clearenv) == __collector_clearenv)
|
||||
{
|
||||
/* still not found -- a fatal error */
|
||||
TprintfT (DBG_LT2, "__collector_clearenv(): ERROR: %s\n", dlerror ());
|
||||
CALL_UTIL (fprintf)(stderr, "__collector_clearenv(): ERROR: %s\n", dlerror ());
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int ret = CALL_UTIL (clearenv)();
|
||||
if (user_follow_mode == FOLLOW_NONE)
|
||||
return ret;
|
||||
if (sp_env_backup == NULL)
|
||||
{
|
||||
TprintfT (DBG_LT2, "__collector_clearenv: ERROR sp_env_backup is not set!\n");
|
||||
return ret;
|
||||
}
|
||||
for (int v = 0; v < NUM_SP_ENV_VARS + NUM_LD_ENV_VARS; v++)
|
||||
if (sp_env_backup[v] && CALL_UTIL (putenv)(sp_env_backup[v]) != 0)
|
||||
TprintfT (DBG_LT2, "__collector_clearenv: ERROR %s is not set!\n",
|
||||
sp_env_backup[v]);
|
||||
return ret;
|
||||
}
|
41
gprofng/libcollector/gethrtime.c
Normal file
41
gprofng/libcollector/gethrtime.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (C) 2021 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 <time.h>
|
||||
#include "gp-time.h"
|
||||
|
||||
/*
|
||||
* CLOCK_MONOTONIC
|
||||
* Clock that cannot be set and represents monotonic time since some
|
||||
* unspecified starting point.
|
||||
*/
|
||||
static hrtime_t
|
||||
linux_gethrtime ()
|
||||
{
|
||||
struct timespec tp;
|
||||
hrtime_t rc = 0;
|
||||
int r = clock_gettime (CLOCK_MONOTONIC_RAW, &tp);
|
||||
if (r == 0)
|
||||
rc = ((hrtime_t) tp.tv_sec)*1000000000 + (hrtime_t) tp.tv_nsec;
|
||||
return rc;
|
||||
}
|
||||
|
||||
hrtime_t (*__collector_gethrtime)() = linux_gethrtime;
|
503
gprofng/libcollector/heaptrace.c
Normal file
503
gprofng/libcollector/heaptrace.c
Normal file
|
@ -0,0 +1,503 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* Heap tracing events
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "gp-defs.h"
|
||||
#include "collector_module.h"
|
||||
#include "gp-experiment.h"
|
||||
#include "data_pckts.h"
|
||||
#include "tsd.h"
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
#define DBG_LT4 4
|
||||
|
||||
/* define the packets to be written out */
|
||||
typedef struct Heap_packet
|
||||
{ /* Malloc/free tracing packet */
|
||||
Common_packet comm;
|
||||
Heap_type mtype; /* subtype of packet */
|
||||
Size_type size; /* size of malloc/realloc request */
|
||||
Vaddr_type vaddr; /* vaddr given to free or returned from malloc/realloc */
|
||||
Vaddr_type ovaddr; /* Previous vaddr given to realloc */
|
||||
} Heap_packet;
|
||||
|
||||
static int init_heap_intf ();
|
||||
static int open_experiment (const char *);
|
||||
static int start_data_collection (void);
|
||||
static int stop_data_collection (void);
|
||||
static int close_experiment (void);
|
||||
static int detach_experiment (void);
|
||||
|
||||
static ModuleInterface module_interface = {
|
||||
SP_HEAPTRACE_FILE, /* description */
|
||||
NULL, /* initInterface */
|
||||
open_experiment, /* openExperiment */
|
||||
start_data_collection, /* startDataCollection */
|
||||
stop_data_collection, /* stopDataCollection */
|
||||
close_experiment, /* closeExperiment */
|
||||
detach_experiment /* detachExperiment (fork child) */
|
||||
};
|
||||
|
||||
static CollectorInterface *collector_interface = NULL;
|
||||
static int heap_mode = 0;
|
||||
static CollectorModule heap_hndl = COLLECTOR_MODULE_ERR;
|
||||
static unsigned heap_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
|
||||
#define CHCK_REENTRANCE(x) ( !heap_mode || ((x) = collector_interface->getKey( heap_key )) == NULL || (*(x) != 0) )
|
||||
#define PUSH_REENTRANCE(x) ((*(x))++)
|
||||
#define POP_REENTRANCE(x) ((*(x))--)
|
||||
#define CALL_REAL(x) (__real_##x)
|
||||
#define NULL_PTR(x) (__real_##x == NULL)
|
||||
#define gethrtime collector_interface->getHiResTime
|
||||
|
||||
#ifdef DEBUG
|
||||
#define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
|
||||
#define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
|
||||
#else
|
||||
#define Tprintf(...)
|
||||
#define TprintfT(...)
|
||||
#endif
|
||||
|
||||
static void *(*__real_malloc)(size_t) = NULL;
|
||||
static void (*__real_free)(void *);
|
||||
static void *(*__real_realloc)(void *, size_t);
|
||||
static void *(*__real_memalign)(size_t, size_t);
|
||||
static void *(*__real_calloc)(size_t, size_t);
|
||||
static void *(*__real_valloc)(size_t);
|
||||
static char *(*__real_strchr)(const char *, int);
|
||||
|
||||
void *__libc_malloc (size_t);
|
||||
void __libc_free (void *);
|
||||
void *__libc_realloc (void *, size_t);
|
||||
|
||||
static void
|
||||
collector_memset (void *s, int c, size_t n)
|
||||
{
|
||||
unsigned char *s1 = s;
|
||||
while (n--)
|
||||
*s1++ = (unsigned char) c;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_module_init (CollectorInterface *_collector_interface)
|
||||
{
|
||||
if (_collector_interface == NULL)
|
||||
return;
|
||||
collector_interface = _collector_interface;
|
||||
Tprintf (0, "heaptrace: __collector_module_init\n");
|
||||
heap_hndl = collector_interface->registerModule (&module_interface);
|
||||
|
||||
/* Initialize next module */
|
||||
ModuleInitFunc next_init = (ModuleInitFunc) dlsym (RTLD_NEXT, "__collector_module_init");
|
||||
if (next_init != NULL)
|
||||
next_init (_collector_interface);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
open_experiment (const char *exp)
|
||||
{
|
||||
if (collector_interface == NULL)
|
||||
{
|
||||
Tprintf (0, "heaptrace: collector_interface is null.\n");
|
||||
return COL_ERROR_HEAPINIT;
|
||||
}
|
||||
if (heap_hndl == COLLECTOR_MODULE_ERR)
|
||||
{
|
||||
Tprintf (0, "heaptrace: handle create failed.\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HEAPINIT);
|
||||
return COL_ERROR_HEAPINIT;
|
||||
}
|
||||
TprintfT (0, "heaptrace: open_experiment %s\n", exp);
|
||||
if (NULL_PTR (malloc))
|
||||
init_heap_intf ();
|
||||
|
||||
const char *params = collector_interface->getParams ();
|
||||
while (params)
|
||||
{
|
||||
if ((params[0] == 'H') && (params[1] == ':'))
|
||||
{
|
||||
params += 2;
|
||||
break;
|
||||
}
|
||||
params = CALL_REAL (strchr)(params, ';');
|
||||
if (params)
|
||||
params++;
|
||||
}
|
||||
if (params == NULL) /* Heap data collection not specified */
|
||||
return COL_ERROR_HEAPINIT;
|
||||
|
||||
heap_key = collector_interface->createKey (sizeof ( int), NULL, NULL);
|
||||
if (heap_key == (unsigned) - 1)
|
||||
{
|
||||
Tprintf (0, "heaptrace: TSD key create failed.\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HEAPINIT);
|
||||
return COL_ERROR_HEAPINIT;
|
||||
}
|
||||
collector_interface->writeLog ("<profile name=\"%s\">\n", SP_JCMD_HEAPTRACE);
|
||||
collector_interface->writeLog (" <profdata fname=\"%s\"/>\n",
|
||||
module_interface.description);
|
||||
|
||||
/* Record Heap_packet description */
|
||||
Heap_packet *pp = NULL;
|
||||
collector_interface->writeLog (" <profpckt kind=\"%d\" uname=\"Heap tracing data\">\n", HEAP_PCKT);
|
||||
collector_interface->writeLog (" <field name=\"LWPID\" uname=\"Lightweight process id\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.lwp_id, sizeof (pp->comm.lwp_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"THRID\" uname=\"Thread number\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.thr_id, sizeof (pp->comm.thr_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"CPUID\" uname=\"CPU id\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.cpu_id, sizeof (pp->comm.cpu_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"High resolution timestamp\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.tstamp, sizeof (pp->comm.tstamp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.frinfo, sizeof (pp->comm.frinfo) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"HTYPE\" uname=\"Heap trace function type\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->mtype, sizeof (pp->mtype) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"HSIZE\" uname=\"Memory size\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->size, sizeof (pp->size) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" <field name=\"HVADDR\" uname=\"Memory address\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->vaddr, sizeof (pp->vaddr) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" <field name=\"HOVADDR\" uname=\"Previous memory address\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->ovaddr, sizeof (pp->ovaddr) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" </profpckt>\n");
|
||||
collector_interface->writeLog ("</profile>\n");
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
start_data_collection (void)
|
||||
{
|
||||
heap_mode = 1;
|
||||
Tprintf (0, "heaptrace: start_data_collection\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
stop_data_collection (void)
|
||||
{
|
||||
heap_mode = 0;
|
||||
Tprintf (0, "heaptrace: stop_data_collection\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
close_experiment (void)
|
||||
{
|
||||
heap_mode = 0;
|
||||
heap_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
Tprintf (0, "heaptrace: close_experiment\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
detach_experiment (void)
|
||||
/* fork child. Clean up state but don't write to experiment */
|
||||
{
|
||||
heap_mode = 0;
|
||||
heap_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
Tprintf (0, "heaptrace: detach_experiment\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int in_init_heap_intf = 0; // Flag that we are in init_heap_intf()
|
||||
|
||||
static int
|
||||
init_heap_intf ()
|
||||
{
|
||||
void *dlflag;
|
||||
in_init_heap_intf = 1;
|
||||
__real_malloc = (void*(*)(size_t))dlsym (RTLD_NEXT, "malloc");
|
||||
if (__real_malloc == NULL)
|
||||
{
|
||||
/* We are probably dlopened after libthread/libc,
|
||||
* try to search in the previously loaded objects
|
||||
*/
|
||||
__real_malloc = (void*(*)(size_t))dlsym (RTLD_DEFAULT, "malloc");
|
||||
if (__real_malloc == NULL)
|
||||
{
|
||||
Tprintf (0, "heaptrace: ERROR: real malloc not found\n");
|
||||
in_init_heap_intf = 0;
|
||||
return 1;
|
||||
}
|
||||
Tprintf (DBG_LT1, "heaptrace: real malloc found with RTLD_DEFAULT\n");
|
||||
dlflag = RTLD_DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tprintf (DBG_LT1, "heaptrace: real malloc found with RTLD_NEXT\n");
|
||||
dlflag = RTLD_NEXT;
|
||||
}
|
||||
__real_free = (void(*)(void *))dlsym (dlflag, "free");
|
||||
__real_realloc = (void*(*)(void *, size_t))dlsym (dlflag, "realloc");
|
||||
__real_memalign = (void*(*)(size_t, size_t))dlsym (dlflag, "memalign");
|
||||
__real_calloc = (void*(*)(size_t, size_t))dlsym (dlflag, "calloc");
|
||||
__real_valloc = (void*(*)(size_t))dlsym (dlflag, "valloc");
|
||||
__real_strchr = (char*(*)(const char *, int))dlsym (dlflag, "strchr");
|
||||
Tprintf (0, "heaptrace: init_heap_intf done\n");
|
||||
in_init_heap_intf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- malloc */
|
||||
|
||||
void *
|
||||
malloc (size_t size)
|
||||
{
|
||||
void *ret;
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
/* Linux startup workaround */
|
||||
if (!heap_mode)
|
||||
{
|
||||
void *ppp = (void *) __libc_malloc (size);
|
||||
Tprintf (DBG_LT4, "heaptrace: LINUX malloc(%ld, %p)...\n", (long) size, ppp);
|
||||
return ppp;
|
||||
}
|
||||
if (NULL_PTR (malloc))
|
||||
init_heap_intf ();
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
ret = (void *) CALL_REAL (malloc)(size);
|
||||
Tprintf (DBG_LT4, "heaptrace: real malloc(%ld) = %p\n", (long) size, ret);
|
||||
return ret;
|
||||
}
|
||||
PUSH_REENTRANCE (guard);
|
||||
|
||||
ret = (void *) CALL_REAL (malloc)(size);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = gethrtime ();
|
||||
hpacket.mtype = MALLOC_TRACE;
|
||||
hpacket.size = (Size_type) size;
|
||||
hpacket.vaddr = (Vaddr_type) ret;
|
||||
hpacket.ovaddr = (Vaddr_type) 0;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return (void *) ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- free */
|
||||
|
||||
void
|
||||
free (void *ptr)
|
||||
{
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
/* Linux startup workaround */
|
||||
if (!heap_mode)
|
||||
{
|
||||
// Tprintf(DBG_LT4,"heaptrace: LINUX free(%p)...\n",ptr);
|
||||
__libc_free (ptr);
|
||||
return;
|
||||
}
|
||||
if (NULL_PTR (malloc))
|
||||
init_heap_intf ();
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
CALL_REAL (free)(ptr);
|
||||
return;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
PUSH_REENTRANCE (guard);
|
||||
|
||||
/* Get a timestamp before 'free' to enforce consistency */
|
||||
hrtime_t ts = gethrtime ();
|
||||
CALL_REAL (free)(ptr);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = ts;
|
||||
hpacket.mtype = FREE_TRACE;
|
||||
hpacket.size = (Size_type) 0;
|
||||
hpacket.vaddr = (Vaddr_type) ptr;
|
||||
hpacket.ovaddr = (Vaddr_type) 0;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- realloc */
|
||||
void *
|
||||
realloc (void *ptr, size_t size)
|
||||
{
|
||||
void *ret;
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
|
||||
/* Linux startup workaround */
|
||||
if (!heap_mode)
|
||||
{
|
||||
void * ppp = (void *) __libc_realloc (ptr, size);
|
||||
Tprintf (DBG_LT4, "heaptrace: LINUX realloc(%ld, %p->%p)...\n",
|
||||
(long) size, ptr, ppp);
|
||||
return ppp;
|
||||
}
|
||||
if (NULL_PTR (realloc))
|
||||
init_heap_intf ();
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
ret = (void *) CALL_REAL (realloc)(ptr, size);
|
||||
return ret;
|
||||
}
|
||||
PUSH_REENTRANCE (guard);
|
||||
hrtime_t ts = gethrtime ();
|
||||
ret = (void *) CALL_REAL (realloc)(ptr, size);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = ts;
|
||||
hpacket.mtype = REALLOC_TRACE;
|
||||
hpacket.size = (Size_type) size;
|
||||
hpacket.vaddr = (Vaddr_type) ret;
|
||||
hpacket.ovaddr = (Vaddr_type) ptr;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return (void *) ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- memalign */
|
||||
void *
|
||||
memalign (size_t align, size_t size)
|
||||
{
|
||||
void *ret;
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
if (NULL_PTR (memalign))
|
||||
init_heap_intf ();
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
ret = (void *) CALL_REAL (memalign)(align, size);
|
||||
return ret;
|
||||
}
|
||||
PUSH_REENTRANCE (guard);
|
||||
ret = (void *) CALL_REAL (memalign)(align, size);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = gethrtime ();
|
||||
hpacket.mtype = MALLOC_TRACE;
|
||||
hpacket.size = (Size_type) size;
|
||||
hpacket.vaddr = (Vaddr_type) ret;
|
||||
hpacket.ovaddr = (Vaddr_type) 0;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- valloc */
|
||||
|
||||
void *
|
||||
valloc (size_t size)
|
||||
{
|
||||
void *ret;
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
if (NULL_PTR (memalign))
|
||||
init_heap_intf ();
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
ret = (void *) CALL_REAL (valloc)(size);
|
||||
return ret;
|
||||
}
|
||||
PUSH_REENTRANCE (guard);
|
||||
ret = (void *) CALL_REAL (valloc)(size);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = gethrtime ();
|
||||
hpacket.mtype = MALLOC_TRACE;
|
||||
hpacket.size = (Size_type) size;
|
||||
hpacket.vaddr = (Vaddr_type) ret;
|
||||
hpacket.ovaddr = (Vaddr_type) 0;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------- calloc */
|
||||
void *
|
||||
calloc (size_t size, size_t esize)
|
||||
{
|
||||
void *ret;
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
if (NULL_PTR (calloc))
|
||||
{
|
||||
if (in_init_heap_intf != 0)
|
||||
return NULL; // Terminate infinite loop
|
||||
init_heap_intf ();
|
||||
}
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
ret = (void *) CALL_REAL (calloc)(size, esize);
|
||||
return ret;
|
||||
}
|
||||
PUSH_REENTRANCE (guard);
|
||||
ret = (void *) CALL_REAL (calloc)(size, esize);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = gethrtime ();
|
||||
hpacket.mtype = MALLOC_TRACE;
|
||||
hpacket.size = (Size_type) (size * esize);
|
||||
hpacket.vaddr = (Vaddr_type) ret;
|
||||
hpacket.ovaddr = (Vaddr_type) 0;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* __collector_heap_record is used to record java allocations/deallocations.
|
||||
* It uses the same facilities as regular heap tracing for now.
|
||||
*/
|
||||
void
|
||||
__collector_heap_record (int mtype, size_t size, void *vaddr)
|
||||
{
|
||||
int *guard;
|
||||
Heap_packet hpacket;
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
return;
|
||||
PUSH_REENTRANCE (guard);
|
||||
collector_memset (&hpacket, 0, sizeof ( Heap_packet));
|
||||
hpacket.comm.tsize = sizeof ( Heap_packet);
|
||||
hpacket.comm.tstamp = gethrtime ();
|
||||
hpacket.mtype = mtype;
|
||||
hpacket.size = (Size_type) size;
|
||||
hpacket.vaddr = (Vaddr_type) vaddr;
|
||||
hpacket.ovaddr = (Vaddr_type) 0;
|
||||
hpacket.comm.frinfo = collector_interface->getFrameInfo (heap_hndl, hpacket.comm.tstamp, FRINFO_FROM_STACK, &hpacket);
|
||||
collector_interface->writeDataRecord (heap_hndl, (Common_packet*) & hpacket);
|
||||
POP_REENTRANCE (guard);
|
||||
return;
|
||||
}
|
905
gprofng/libcollector/hwprofile.c
Normal file
905
gprofng/libcollector/hwprofile.c
Normal file
|
@ -0,0 +1,905 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Hardware counter profiling */
|
||||
|
||||
#include "config.h"
|
||||
#include <alloca.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include "gp-defs.h"
|
||||
#define _STRING_H 1 /* XXX MEZ: temporary workaround */
|
||||
#include "hwcdrv.h"
|
||||
#include "collector_module.h"
|
||||
#include "gp-experiment.h"
|
||||
#include "libcol_util.h"
|
||||
#include "hwprofile.h"
|
||||
#include "ABS.h"
|
||||
#include "tsd.h"
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
#define DBG_LT4 4
|
||||
#define DBG_LT5 5
|
||||
|
||||
#define SD_OFF 0 /* before start or after close she shut down process */
|
||||
#define SD_PENDING 1 /* before running real_detach_experiment() */
|
||||
#define SD_COMPLETE 2 /* after running real_detach_experiment() */
|
||||
|
||||
static int init_interface (CollectorInterface*);
|
||||
static int open_experiment (const char *);
|
||||
static int start_data_collection (void);
|
||||
static int stop_data_collection (void);
|
||||
static int close_experiment (void);
|
||||
static int detach_experiment (void);
|
||||
static int real_detach_experiment (void);
|
||||
|
||||
static ModuleInterface module_interface ={
|
||||
SP_HWCNTR_FILE, /* description */
|
||||
init_interface, /* initInterface */
|
||||
open_experiment, /* openExperiment */
|
||||
start_data_collection, /* startDataCollection */
|
||||
stop_data_collection, /* stopDataCollection */
|
||||
close_experiment, /* closeExperiment */
|
||||
detach_experiment /* detachExperiment (fork child) */
|
||||
};
|
||||
|
||||
static CollectorInterface *collector_interface = NULL;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* compile options and workarounds */
|
||||
|
||||
/* Solaris: We set ITIMER_REALPROF to ensure that counters get started on
|
||||
* LWPs that existed before the collector initialization.
|
||||
*
|
||||
* In addition, if the appropriate #define's are set, we check for:
|
||||
* lost-hw-overflow -- the HW counters rollover, but the overflow
|
||||
* interrupt is not generated (counters keep running)
|
||||
* lost-sigemt -- the interrupt is received by the kernel,
|
||||
* which stops the counters, but the kernel fails
|
||||
* to deliver the signal.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* typedefs */
|
||||
|
||||
typedef enum {
|
||||
HWCMODE_OFF, /* before start or after close */
|
||||
HWCMODE_SUSPEND, /* stop_data_collection called */
|
||||
HWCMODE_ACTIVE, /* counters are defined and after start_data_collection() */
|
||||
HWCMODE_ABORT /* fatal error occured. Log a message, stop recording */
|
||||
} hwc_mode_t;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* prototypes */
|
||||
static void init_ucontexts (void);
|
||||
static int hwc_initialize_handlers (void);
|
||||
static void collector_record_counter (ucontext_t*,
|
||||
int timecvt,
|
||||
ABST_type, hrtime_t,
|
||||
unsigned, uint64_t);
|
||||
static void collector_hwc_ABORT (int errnum, const char *msg);
|
||||
static void hwclogwrite0 ();
|
||||
static void hwclogwrite (Hwcentry *);
|
||||
static void set_hwc_mode (hwc_mode_t);
|
||||
static void collector_sigemt_handler (int sig, siginfo_t *si, void *puc);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* static variables */
|
||||
|
||||
/* --- user counter selections and options */
|
||||
static int hwcdef_has_memspace; /* true to indicate use of extened packets */
|
||||
static unsigned hwcdef_cnt; /* number of *active* hardware counters */
|
||||
static unsigned hwcdef_num_sampling_ctrdefs; /* ctrs that use sampling */
|
||||
static unsigned hwcdef_num_overflow_ctrdefs; /* ctrs that use overflow */
|
||||
static Hwcentry **hwcdef; /* HWC definitions */
|
||||
static int cpcN_cpuver = CPUVER_UNDEFINED;
|
||||
static int hwcdrv_inited; /* Don't call hwcdrv_init() in fork_child */
|
||||
static hwcdrv_api_t *hwc_driver = NULL;
|
||||
static unsigned hwprofile_tsd_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
static int hwprofile_tsd_sz = 0;
|
||||
static volatile hwc_mode_t hwc_mode = HWCMODE_OFF;
|
||||
static volatile unsigned int nthreads_in_sighandler = 0;
|
||||
static volatile unsigned int sd_state = SD_OFF;
|
||||
|
||||
/* --- experiment logging state */
|
||||
static CollectorModule expr_hndl = COLLECTOR_MODULE_ERR;
|
||||
static ucontext_t expr_dummy_uc; // used for hacked "collector" frames
|
||||
static ucontext_t expr_out_of_range_uc; // used for "out-of-range" frames
|
||||
static ucontext_t expr_frozen_uc; // used for "frozen" frames
|
||||
static ucontext_t expr_nopc_uc; // used for not-program-related frames
|
||||
static ucontext_t expr_lostcounts_uc; // used for lost_counts frames
|
||||
|
||||
/* --- signal handler state */
|
||||
static struct sigaction old_sigemt_handler; //overwritten in fork-child
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* macros */
|
||||
#define COUNTERS_ENABLED() (hwcdef_cnt)
|
||||
#define gethrtime collector_interface->getHiResTime
|
||||
|
||||
#ifdef DEBUG
|
||||
#define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
|
||||
#define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
|
||||
#else
|
||||
#define Tprintf(...)
|
||||
#define TprintfT(...)
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Initialization routines */
|
||||
static hwcdrv_api_t *
|
||||
get_hwc_driver ()
|
||||
{
|
||||
if (hwc_driver == NULL)
|
||||
hwc_driver = __collector_get_hwcdrv ();
|
||||
return hwc_driver;
|
||||
}
|
||||
|
||||
static void init_module () __attribute__ ((constructor));
|
||||
static void
|
||||
init_module ()
|
||||
{
|
||||
__collector_dlsym_guard = 1;
|
||||
RegModuleFunc reg_module = (RegModuleFunc) dlsym (RTLD_DEFAULT, "__collector_register_module");
|
||||
__collector_dlsym_guard = 0;
|
||||
if (reg_module == NULL)
|
||||
{
|
||||
TprintfT (0, "hwprofile: init_module FAILED - reg_module = NULL\n");
|
||||
return;
|
||||
}
|
||||
expr_hndl = reg_module (&module_interface);
|
||||
if (expr_hndl == COLLECTOR_MODULE_ERR)
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: handle not created.\n");
|
||||
if (collector_interface)
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCINIT);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
init_interface (CollectorInterface *_collector_interface)
|
||||
{
|
||||
collector_interface = _collector_interface;
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
static void *
|
||||
hwprofile_get_tsd ()
|
||||
{
|
||||
return collector_interface->getKey (hwprofile_tsd_key);
|
||||
}
|
||||
|
||||
static int
|
||||
open_experiment (const char *exp)
|
||||
{
|
||||
if (collector_interface == NULL)
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: collector_interface is null.\n");
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
const char *params = collector_interface->getParams ();
|
||||
while (params)
|
||||
{
|
||||
if (__collector_strStartWith (params, "h:*") == 0)
|
||||
{
|
||||
/* HWC counters set by default */
|
||||
collector_interface->writeLog ("<%s %s=\"1\"/>\n",
|
||||
SP_TAG_SETTING, SP_JCMD_HWC_DEFAULT);
|
||||
params += 3;
|
||||
break;
|
||||
}
|
||||
else if (__collector_strStartWith (params, "h:") == 0)
|
||||
{
|
||||
params += 2;
|
||||
break;
|
||||
}
|
||||
params = CALL_UTIL (strchr)(params, ';');
|
||||
if (params)
|
||||
params++;
|
||||
}
|
||||
if (params == NULL) /* HWC profiling not specified */
|
||||
return COL_ERROR_HWCINIT;
|
||||
char *s = CALL_UTIL (strchr)(params, (int) ';');
|
||||
int sz = s ? s - params : CALL_UTIL (strlen)(params);
|
||||
char *defstring = (char*) alloca (sz + 1);
|
||||
CALL_UTIL (strlcpy)(defstring, params, sz + 1);
|
||||
TprintfT (0, "hwprofile: open_experiment %s -- %s\n", exp, defstring);
|
||||
|
||||
int err = COL_ERROR_NONE;
|
||||
/* init counter library */
|
||||
if (!hwcdrv_inited)
|
||||
{ /* do not call hwcdrv_init() from fork-child */
|
||||
hwcdrv_inited = 1;
|
||||
get_hwc_driver ();
|
||||
if (hwc_driver->hwcdrv_init (collector_hwc_ABORT, &hwprofile_tsd_sz) == 0)
|
||||
{
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
|
||||
TprintfT (0, "hwprofile: ERROR: hwcfuncs_init() failed\n");
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
|
||||
if (hwc_driver->hwcdrv_enable_mt (hwprofile_get_tsd))
|
||||
{
|
||||
// It is OK to call hwcdrv_enable_mt() before tsd key is created
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
|
||||
TprintfT (0, "hwprofile: ERROR: hwcdrv_enable_mt() failed\n");
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
|
||||
hwc_driver->hwcdrv_get_info (&cpcN_cpuver, NULL, NULL, NULL, NULL);
|
||||
if (cpcN_cpuver < 0)
|
||||
{
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
|
||||
TprintfT (0, "hwprofile: ERROR: hwcdrv_get_info() failed\n");
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (hwprofile_tsd_sz)
|
||||
{
|
||||
hwprofile_tsd_key = collector_interface->createKey (hwprofile_tsd_sz, NULL, NULL);
|
||||
if (hwprofile_tsd_key == COLLECTOR_TSD_INVALID_KEY)
|
||||
{
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
|
||||
TprintfT (0, "hwprofile: ERROR: TSD createKey failed\n");
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
}
|
||||
hwcdef_cnt = 0;
|
||||
hwcdef_has_memspace = 0;
|
||||
|
||||
/* create counters based on hwcdef[] */
|
||||
err = __collector_hwcfuncs_bind_descriptor (defstring);
|
||||
if (err)
|
||||
{
|
||||
err = err == HWCFUNCS_ERROR_HWCINIT ? COL_ERROR_HWCINIT : COL_ERROR_HWCARGS;
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
|
||||
SP_JCMD_CERROR, err, defstring);
|
||||
TprintfT (0, "hwprofile: ERROR: open_experiment() failed, RC=%d \n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* generate an array of counter structures for each requested counter */
|
||||
hwcdef = __collector_hwcfuncs_get_ctrs (&hwcdef_cnt);
|
||||
hwcdef_num_sampling_ctrdefs = hwcdef_num_overflow_ctrdefs = 0;
|
||||
int idx;
|
||||
for (idx = 0; idx < hwcdef_cnt; idx++)
|
||||
{
|
||||
if (HWCENTRY_USES_SAMPLING (hwcdef[idx]))
|
||||
{
|
||||
hwcdef_num_sampling_ctrdefs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hwcdef_num_overflow_ctrdefs++;
|
||||
}
|
||||
}
|
||||
|
||||
init_ucontexts ();
|
||||
|
||||
/* initialize the SIGEMT handler, and the periodic HWC checker */
|
||||
err = hwc_initialize_handlers ();
|
||||
if (err != COL_ERROR_NONE)
|
||||
{
|
||||
hwcdef_cnt = 0;
|
||||
TprintfT (0, "hwprofile: ERROR: open_experiment() failed, RC=%d \n", err);
|
||||
/* log written by hwc_initialize_handlers() */
|
||||
return err;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < hwcdef_cnt; idx++)
|
||||
if (ABST_BACKTRACK_ENABLED (hwcdef[idx]->memop))
|
||||
hwcdef_has_memspace = 1;
|
||||
|
||||
/* record the hwc definitions in the log, based on the counter array */
|
||||
hwclogwrite0 ();
|
||||
for (idx = 0; idx < hwcdef_cnt; idx++)
|
||||
hwclogwrite (hwcdef[idx]);
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
__collector_ext_hwc_lwp_init ()
|
||||
{
|
||||
return get_hwc_driver ()->hwcdrv_lwp_init ();
|
||||
}
|
||||
|
||||
void
|
||||
__collector_ext_hwc_lwp_fini ()
|
||||
{
|
||||
get_hwc_driver ()->hwcdrv_lwp_fini ();
|
||||
}
|
||||
|
||||
int
|
||||
__collector_ext_hwc_lwp_suspend ()
|
||||
{
|
||||
return get_hwc_driver ()->hwcdrv_lwp_suspend ();
|
||||
}
|
||||
|
||||
int
|
||||
__collector_ext_hwc_lwp_resume ()
|
||||
{
|
||||
return get_hwc_driver ()->hwcdrv_lwp_resume ();
|
||||
}
|
||||
|
||||
/* Dummy routine, used to provide a context for non-program related profiles */
|
||||
void
|
||||
__collector_not_program_related () { }
|
||||
|
||||
/* Dummy routine, used to provide a context for lost counts (perf_events) */
|
||||
void
|
||||
__collector_hwc_samples_lost () { }
|
||||
|
||||
/* Dummy routine, used to provide a context */
|
||||
void
|
||||
__collector_hwcs_frozen () { }
|
||||
|
||||
/* Dummy routine, used to provide a context */
|
||||
void
|
||||
__collector_hwcs_out_of_range () { }
|
||||
/* initialize some structures */
|
||||
static void
|
||||
init_ucontexts (void)
|
||||
{
|
||||
/* initialize dummy context for "collector" frames */
|
||||
getcontext (&expr_dummy_uc);
|
||||
SETFUNCTIONCONTEXT (&expr_dummy_uc, NULL);
|
||||
|
||||
/* initialize dummy context for "out-of-range" frames */
|
||||
getcontext (&expr_out_of_range_uc);
|
||||
SETFUNCTIONCONTEXT (&expr_out_of_range_uc, &__collector_hwcs_out_of_range);
|
||||
|
||||
/* initialize dummy context for "frozen" frames */
|
||||
getcontext (&expr_frozen_uc);
|
||||
SETFUNCTIONCONTEXT (&expr_frozen_uc, &__collector_hwcs_frozen);
|
||||
|
||||
/* initialize dummy context for non-program-related frames */
|
||||
getcontext (&expr_nopc_uc);
|
||||
SETFUNCTIONCONTEXT (&expr_nopc_uc, &__collector_not_program_related);
|
||||
|
||||
/* initialize dummy context for lost-counts-related frames */
|
||||
getcontext (&expr_lostcounts_uc);
|
||||
SETFUNCTIONCONTEXT (&expr_lostcounts_uc, &__collector_hwc_samples_lost);
|
||||
}
|
||||
/* initialize the signal handler */
|
||||
static int
|
||||
hwc_initialize_handlers (void)
|
||||
{
|
||||
/* install the signal handler for SIGEMT */
|
||||
struct sigaction oact;
|
||||
if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &oact) != 0)
|
||||
{
|
||||
TprintfT (0, "hwc_initialize_handlers(): ERROR: hwc_initialize_handlers(): __collector_sigaction() failed to get oact\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">old handler could not be determined</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT);
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
if (oact.sa_sigaction == collector_sigemt_handler)
|
||||
{
|
||||
/* signal handler is already in place; we are probably in a fork-child */
|
||||
TprintfT (DBG_LT1, "hwc_initialize_handlers(): hwc_initialize_handlers() collector_sigemt_handler already installed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set our signal handler */
|
||||
struct sigaction c_act;
|
||||
CALL_UTIL (memset)(&c_act, 0, sizeof c_act);
|
||||
sigemptyset (&c_act.sa_mask);
|
||||
sigaddset (&c_act.sa_mask, SIGPROF); /* block SIGPROF delivery in handler */
|
||||
/* XXXX should probably also block sample_sig & pause_sig */
|
||||
c_act.sa_sigaction = collector_sigemt_handler; /* note: used to set sa_handler instead */
|
||||
c_act.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
if (__collector_sigaction (HWCFUNCS_SIGNAL, &c_act, &old_sigemt_handler) != 0)
|
||||
{
|
||||
TprintfT (0, "hwc_initialize_handlers(): ERROR: hwc_initialize_handlers(): __collector_sigaction() failed to set cact\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">event handler could not be installed</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT);
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
}
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
close_experiment (void)
|
||||
{
|
||||
/* note: stop_data_collection() should have already been called by
|
||||
* collector_close_experiment()
|
||||
*/
|
||||
if (!COUNTERS_ENABLED ())
|
||||
return COL_ERROR_NONE;
|
||||
detach_experiment ();
|
||||
|
||||
/* cpc or libperfctr may still generate sigemts for a while */
|
||||
/* verify that SIGEMT handler is still installed */
|
||||
/* (still required with sigaction interposition and management,
|
||||
since interposition is not done for attach experiments)
|
||||
*/
|
||||
struct sigaction curr;
|
||||
if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &curr) == -1)
|
||||
{
|
||||
TprintfT (0, "hwprofile close_experiment: ERROR: hwc sigaction check failed: errno=%d\n", errno);
|
||||
}
|
||||
else if (curr.sa_sigaction != collector_sigemt_handler)
|
||||
{
|
||||
TprintfT (DBG_LT1, "hwprofile close_experiment: WARNING: collector sigemt handler replaced by 0x%p!\n", curr.sa_handler);
|
||||
(void) collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">0x%p</event>\n",
|
||||
SP_JCMD_CWARN, COL_WARN_SIGEMT, curr.sa_handler);
|
||||
}
|
||||
else
|
||||
TprintfT (DBG_LT1, "hwprofile close_experiment: collector sigemt handler integrity verified!\n");
|
||||
TprintfT (0, "hwprofile: close_experiment\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
detach_experiment (void)
|
||||
{
|
||||
/* fork child. Clean up state but don't write to experiment */
|
||||
/* note: stop_data_collection() has already been called by the fork_prologue */
|
||||
// detach_experiment() can be called asynchronously
|
||||
// from anywhere, even from within a sigemt handler
|
||||
// via DBX detach.
|
||||
// Important: stop_data_collection() _must_ be called
|
||||
// before detach_experiment() is called.
|
||||
if (!COUNTERS_ENABLED ())
|
||||
return COL_ERROR_NONE;
|
||||
TprintfT (0, "hwprofile: detach_experiment()\n");
|
||||
if (SD_OFF != __collector_cas_32 (&sd_state, SD_OFF, SD_PENDING))
|
||||
return 0;
|
||||
// one and only one call should ever make it here here.
|
||||
if (hwc_mode == HWCMODE_ACTIVE)
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: stop_data_collection() should have been called before detach_experiment()\n");
|
||||
stop_data_collection ();
|
||||
}
|
||||
|
||||
// Assumption: The only calls to sigemt_handler
|
||||
// we should see at this point
|
||||
// will be those that were already in-flight before
|
||||
// stop_new_sigemts() was called.
|
||||
if (nthreads_in_sighandler > 0)
|
||||
{
|
||||
// sigemt handlers should see
|
||||
// SD_PENDING and should call real_detach_experiment()
|
||||
// when the last handler is finished.
|
||||
TprintfT (DBG_LT1, "hwprofile: detach in the middle of signal handler.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we get here, there should be no remaining
|
||||
// sigemt handlers. However, we don't really know
|
||||
// if there were ever any in flight, so call
|
||||
// real_detach_experiment() here:
|
||||
return real_detach_experiment (); // multiple calls to this OK
|
||||
}
|
||||
|
||||
static int
|
||||
real_detach_experiment (void)
|
||||
{
|
||||
/*multiple calls to this routine are OK.*/
|
||||
if (SD_PENDING != __collector_cas_32 (&sd_state, SD_PENDING, SD_COMPLETE))
|
||||
return 0;
|
||||
// only the first caller to this routine should get here.
|
||||
hwcdef_cnt = 0; /* since now deinstalled */
|
||||
hwcdef = NULL;
|
||||
set_hwc_mode (HWCMODE_OFF);
|
||||
if (SD_COMPLETE != __collector_cas_32 (&sd_state, SD_COMPLETE, SD_OFF))
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: unexpected sd_state in real_detach_experiment()\n");
|
||||
sd_state = SD_OFF;
|
||||
}
|
||||
hwprofile_tsd_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
TprintfT (DBG_LT0, "hwprofile: real_detach_experiment() detached from experiment.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Record counter values. */
|
||||
|
||||
/* <value> should already be adjusted to be "zero-based" (counting up from 0).*/
|
||||
static void
|
||||
collector_record_counter_internal (ucontext_t *ucp, int timecvt,
|
||||
ABST_type ABS_memop, hrtime_t time,
|
||||
unsigned tag, uint64_t value, uint64_t pc,
|
||||
uint64_t va, uint64_t latency,
|
||||
uint64_t data_source)
|
||||
{
|
||||
MHwcntr_packet pckt;
|
||||
CALL_UTIL (memset)(&pckt, 0, sizeof ( MHwcntr_packet));
|
||||
pckt.comm.tstamp = time;
|
||||
pckt.tag = tag;
|
||||
if (timecvt > 1)
|
||||
{
|
||||
if (HWCVAL_HAS_ERR (value))
|
||||
{
|
||||
value = HWCVAL_CLR_ERR (value);
|
||||
value *= timecvt;
|
||||
value = HWCVAL_SET_ERR (value);
|
||||
}
|
||||
else
|
||||
value *= timecvt;
|
||||
}
|
||||
pckt.interval = value;
|
||||
pckt.comm.type = HW_PCKT;
|
||||
pckt.comm.tsize = sizeof (Hwcntr_packet);
|
||||
TprintfT (DBG_LT4, "hwprofile: %llu sample %lld tag %u recorded\n",
|
||||
(unsigned long long) time, (long long) value, tag);
|
||||
if (ABS_memop == ABST_NOPC)
|
||||
ucp = &expr_nopc_uc;
|
||||
pckt.comm.frinfo = collector_interface->getFrameInfo (expr_hndl, pckt.comm.tstamp, FRINFO_FROM_UC, ucp);
|
||||
collector_interface->writeDataRecord (expr_hndl, (Common_packet*) & pckt);
|
||||
}
|
||||
|
||||
static void
|
||||
collector_record_counter (ucontext_t *ucp, int timecvt, ABST_type ABS_memop,
|
||||
hrtime_t time, unsigned tag, uint64_t value)
|
||||
{
|
||||
collector_record_counter_internal (ucp, timecvt, ABS_memop, time, tag, value,
|
||||
HWCFUNCS_INVALID_U64, HWCFUNCS_INVALID_U64,
|
||||
HWCFUNCS_INVALID_U64, HWCFUNCS_INVALID_U64);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Signal handlers */
|
||||
|
||||
/* SIGEMT -- relayed from libcpc, when the counter overflows */
|
||||
|
||||
/* Generates the appropriate event or events, and resets the counters */
|
||||
static void
|
||||
collector_sigemt_handler (int sig, siginfo_t *si, void *puc)
|
||||
{
|
||||
int rc;
|
||||
hwc_event_t sample, lost_samples;
|
||||
if (sig != HWCFUNCS_SIGNAL)
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: %s: unexpected signal %d\n", "collector_sigemt_handler", sig);
|
||||
return;
|
||||
}
|
||||
if (!COUNTERS_ENABLED ())
|
||||
{ /* apparently deinstalled */
|
||||
TprintfT (0, "hwprofile: WARNING: SIGEMT detected after close_experiment()\n");
|
||||
/* kills future sigemts since hwcdrv_sighlr_restart() not called */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Typically, we expect HWC overflow signals to come from the kernel: si_code > 0.
|
||||
* On Linux, however, dbx might be "forwarding" a signal using tkill()/tgkill().
|
||||
* For more information on what si_code values can be expected on Linux, check:
|
||||
* cmn_components/Collector_Interface/hwcdrv_pcl.c hwcdrv_overflow()
|
||||
* cmn_components/Collector_Interface/hwcdrv_perfctr.c hdrv_perfctr_overflow()
|
||||
*/
|
||||
if (puc == NULL || si == NULL || (si->si_code <= 0 && si->si_code != SI_TKILL))
|
||||
{
|
||||
TprintfT (DBG_LT3, "hwprofile: collector_sigemt_handler SIG%02d\n", sig);
|
||||
if (old_sigemt_handler.sa_handler == SIG_DFL)
|
||||
__collector_SIGDFL_handler (HWCFUNCS_SIGNAL);
|
||||
else if (old_sigemt_handler.sa_handler != SIG_IGN &&
|
||||
old_sigemt_handler.sa_sigaction != &collector_sigemt_handler)
|
||||
{
|
||||
/* Redirect the signal to the previous signal handler */
|
||||
(old_sigemt_handler.sa_sigaction)(sig, si, puc);
|
||||
TprintfT (DBG_LT1, "hwprofile: collector_sigemt_handler SIG%02d redirected to original handler\n", sig);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rc = get_hwc_driver ()->hwcdrv_overflow (si, &sample, &lost_samples);
|
||||
if (rc)
|
||||
{
|
||||
/* hwcdrv_sighlr_restart() should not be called */
|
||||
TprintfT (0, "hwprofile: ERROR: collector_sigemt_handler: hwcdrv_overflow() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (hwc_mode == HWCMODE_ACTIVE)
|
||||
{
|
||||
/* record the event only if counters are active */
|
||||
/* The following has been copied from dispatcher.c */
|
||||
#if ARCH(SPARC)
|
||||
/* 23340823 signal handler third argument should point to a ucontext_t */
|
||||
/* Convert sigcontext to ucontext_t on sparc-Linux */
|
||||
ucontext_t uctxmem;
|
||||
struct sigcontext *sctx = (struct sigcontext*) puc;
|
||||
ucontext_t *uctx = &uctxmem;
|
||||
uctx->uc_link = NULL;
|
||||
#if WSIZE(32)
|
||||
uctx->uc_mcontext.gregs[REG_PC] = sctx->si_regs.pc;
|
||||
__collector_memcpy (&uctx->uc_mcontext.gregs[3],
|
||||
sctx->si_regs.u_regs,
|
||||
sizeof (sctx->si_regs.u_regs));
|
||||
#else
|
||||
uctx->uc_mcontext.mc_gregs[MC_PC] = sctx->sigc_regs.tpc;
|
||||
__collector_memcpy (&uctx->uc_mcontext.mc_gregs[3],
|
||||
sctx->sigc_regs.u_regs,
|
||||
sizeof (sctx->sigc_regs.u_regs));
|
||||
#endif /* WSIZE() */
|
||||
#else
|
||||
ucontext_t *uctx = (ucontext_t*) puc;
|
||||
#endif /* ARCH() */
|
||||
|
||||
for (int ii = 0; ii < hwcdef_cnt; ii++)
|
||||
if (lost_samples.ce_pic[ii])
|
||||
collector_record_counter (&expr_lostcounts_uc, hwcdef[ii]->timecvt,
|
||||
hwcdef[ii]->memop, lost_samples.ce_hrt,
|
||||
hwcdef[ii]->sort_order, lost_samples.ce_pic[ii]);
|
||||
for (int ii = 0; ii < hwcdef_cnt; ii++)
|
||||
if (sample.ce_pic[ii])
|
||||
collector_record_counter (uctx, hwcdef[ii]->timecvt,
|
||||
hwcdef[ii]->memop, sample.ce_hrt,
|
||||
hwcdef[ii]->sort_order, sample.ce_pic[ii]);
|
||||
}
|
||||
rc = get_hwc_driver ()->hwcdrv_sighlr_restart (NULL);
|
||||
}
|
||||
/* SIGPROF -- not installed as handler, but
|
||||
* __collector_ext_hwc_check: called by (SIGPROF) dispatcher.
|
||||
* Periodical check of integrity of HWC count/signal mechanism,
|
||||
* as required for various chip/system bugs/workarounds.
|
||||
*/
|
||||
void
|
||||
__collector_ext_hwc_check (siginfo_t *info, ucontext_t *vcontext) { }
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
collector_sigemt_sigaction (const struct sigaction *nact,
|
||||
struct sigaction *oact)
|
||||
{
|
||||
struct sigaction oact_check;
|
||||
/* Error codes and messages that refer to HWC are tricky.
|
||||
* E.g., HWC profiling might not even be on; we might
|
||||
* encounter an error here simply because the user is
|
||||
* trying to set a handler for a signal that happens to
|
||||
* be HWCFUNCS_SIGNAL, which we aren't even using.
|
||||
*/
|
||||
if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &oact_check) != 0)
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: collector_sigemt_sigaction(): request to set handler for signal %d, but check on existing handler failed\n", HWCFUNCS_SIGNAL);
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">old handler for signal %d could not be determined</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT, HWCFUNCS_SIGNAL);
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
|
||||
if (oact_check.sa_sigaction == collector_sigemt_handler)
|
||||
{
|
||||
/* dispatcher is in place, so nact/oact apply to old_sigemt_handler */
|
||||
if (oact != NULL)
|
||||
{
|
||||
oact->sa_handler = old_sigemt_handler.sa_handler;
|
||||
oact->sa_mask = old_sigemt_handler.sa_mask;
|
||||
oact->sa_flags = old_sigemt_handler.sa_flags;
|
||||
}
|
||||
if (nact != NULL)
|
||||
{
|
||||
old_sigemt_handler.sa_handler = nact->sa_handler;
|
||||
old_sigemt_handler.sa_mask = nact->sa_mask;
|
||||
old_sigemt_handler.sa_flags = nact->sa_flags;
|
||||
}
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
else /* no dispatcher in place, so just act like normal sigaction() */
|
||||
return __collector_sigaction (HWCFUNCS_SIGNAL, nact, oact);
|
||||
}
|
||||
|
||||
static void
|
||||
collector_hwc_ABORT (int errnum, const char *msg)
|
||||
{
|
||||
TprintfT (0, "hwprofile: collector_hwc_ABORT: [%d] %s\n", errnum, msg);
|
||||
if (hwc_mode == HWCMODE_ABORT) /* HWC collection already aborted! */
|
||||
return;
|
||||
set_hwc_mode (HWCMODE_ABORT); /* set global flag to disable handlers and indicate abort */
|
||||
|
||||
/* Write the error message to the experiment */
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s: errno=%d</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCFAIL, msg, errnum);
|
||||
|
||||
#ifdef REAL_DEBUG
|
||||
abort ();
|
||||
#else
|
||||
TprintfT (0, "hwprofile: Continuing without HWC collection...\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
start_data_collection (void)
|
||||
{
|
||||
hwc_mode_t old_mode = hwc_mode;
|
||||
if (!COUNTERS_ENABLED ())
|
||||
return COL_ERROR_NONE;
|
||||
TprintfT (0, "hwprofile: start_data_collection (hwc_mode=%d)\n", old_mode);
|
||||
switch (old_mode)
|
||||
{
|
||||
case HWCMODE_OFF:
|
||||
if (get_hwc_driver ()->hwcdrv_start ())
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: start_data_collection() failed in hwcdrv_start()\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s: errno=%d</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_HWCFAIL,
|
||||
"start_data_collection()", errno);
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
set_hwc_mode (HWCMODE_ACTIVE); /* start handling events on signals */
|
||||
break;
|
||||
case HWCMODE_SUSPEND:
|
||||
if (get_hwc_driver ()->hwcdrv_lwp_resume ())
|
||||
{
|
||||
TprintfT (0, "hwprofile: ERROR: start_data_collection() failed in hwcdrv_lwp_resume()\n");
|
||||
/* ignore errors from lwp_resume() */
|
||||
}
|
||||
set_hwc_mode (HWCMODE_ACTIVE); /* start handling events on signals */
|
||||
break;
|
||||
default:
|
||||
TprintfT (0, "hwprofile: ERROR: start_data_collection() invalid mode\n");
|
||||
return COL_ERROR_HWCINIT;
|
||||
}
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
stop_data_collection (void)
|
||||
{
|
||||
hwc_mode_t old_mode = hwc_mode;
|
||||
if (!COUNTERS_ENABLED ())
|
||||
return COL_ERROR_NONE;
|
||||
TprintfT (0, "hwprofile: stop_data_collection (hwc_mode=%d)\n", old_mode);
|
||||
switch (old_mode)
|
||||
{
|
||||
case HWCMODE_SUSPEND:
|
||||
return COL_ERROR_NONE;
|
||||
case HWCMODE_ACTIVE:
|
||||
set_hwc_mode (HWCMODE_SUSPEND); /* stop handling signals */
|
||||
break;
|
||||
default:
|
||||
/* Don't change the mode, but attempt to suspend anyway... */
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_hwc_driver ()->hwcdrv_lwp_suspend ())
|
||||
/* ignore errors from lwp_suspend() */
|
||||
TprintfT (0, "hwprofile: ERROR: stop_data_collection() failed in hwcdrv_lwp_suspend()\n");
|
||||
|
||||
/*
|
||||
* hwcdrv_lwp_suspend() cannot guarantee that all SIGEMTs will stop
|
||||
* but hwc_mode will prevent logging and counters will overflow once
|
||||
* then stay frozen.
|
||||
*/
|
||||
/* There may still be pending SIGEMTs so don't reset the SIG_DFL handler.
|
||||
*/
|
||||
/* see comment in dispatcher.c */
|
||||
/* ret = __collector_sigaction( SIGEMT, &old_sigemt_handler, NULL ); */
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* utilities */
|
||||
static void
|
||||
set_hwc_mode (hwc_mode_t md)
|
||||
{
|
||||
TprintfT (DBG_LT1, "hwprofile: set_hwc_mode(%d)\n", md);
|
||||
hwc_mode = md;
|
||||
}
|
||||
|
||||
int
|
||||
__collector_ext_hwc_active ()
|
||||
{
|
||||
return (hwc_mode == HWCMODE_ACTIVE);
|
||||
}
|
||||
|
||||
static void
|
||||
hwclogwrite0 ()
|
||||
{
|
||||
collector_interface->writeLog ("<profdata fname=\"%s\"/>\n",
|
||||
module_interface.description);
|
||||
/* Record Hwcntr_packet description */
|
||||
Hwcntr_packet *pp = NULL;
|
||||
collector_interface->writeLog ("<profpckt kind=\"%d\" uname=\"" STXT ("Hardware counter profiling data") "\">\n", HW_PCKT);
|
||||
collector_interface->writeLog (" <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.lwp_id, sizeof (pp->comm.lwp_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.thr_id, sizeof (pp->comm.thr_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.cpu_id, sizeof (pp->comm.cpu_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.tstamp, sizeof (pp->comm.tstamp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->comm.frinfo, sizeof (pp->comm.frinfo) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"HWCTAG\" uname=\"" STXT ("Hardware counter index") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->tag, sizeof (pp->tag) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"HWCINT\" uname=\"" STXT ("Hardware counter interval") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&pp->interval, sizeof (pp->interval) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog ("</profpckt>\n");
|
||||
if (hwcdef_has_memspace)
|
||||
{
|
||||
/* Record MHwcntr_packet description */
|
||||
MHwcntr_packet *xpp = NULL;
|
||||
collector_interface->writeLog ("<profpckt kind=\"%d\" uname=\"" STXT ("Hardware counter profiling data") "\">\n", MHWC_PCKT);
|
||||
collector_interface->writeLog (" <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->comm.lwp_id, sizeof (xpp->comm.lwp_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->comm.thr_id, sizeof (xpp->comm.thr_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->comm.cpu_id, sizeof (xpp->comm.cpu_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->comm.tstamp, sizeof (xpp->comm.tstamp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->comm.frinfo, sizeof (xpp->comm.frinfo) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"HWCTAG\" uname=\"" STXT ("Hardware counter index") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->tag, sizeof (xpp->tag) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"HWCINT\" uname=\"" STXT ("Hardware counter interval") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->interval, sizeof (xpp->interval) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"VADDR\" uname=\"" STXT ("Virtual address (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->ea_vaddr, sizeof (xpp->ea_vaddr) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" <field name=\"PADDR\" uname=\"" STXT ("Physical address (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->ea_paddr, sizeof (xpp->ea_paddr) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" <field name=\"VIRTPC\" uname=\"" STXT ("Virtual address (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->pc_vaddr, sizeof (xpp->pc_vaddr) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" <field name=\"PHYSPC\" uname=\"" STXT ("Physical address (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->pc_paddr, sizeof (xpp->pc_paddr) == 4 ? "UINT32" : "UINT64");
|
||||
collector_interface->writeLog (" <field name=\"EA_PAGESIZE\" uname=\"" STXT ("Page size (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->ea_pagesz, sizeof (xpp->ea_pagesz) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"PC_PAGESIZE\" uname=\"" STXT ("Page size (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->pc_pagesz, sizeof (xpp->pc_pagesz) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"EA_LGRP\" uname=\"" STXT ("Page locality group (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->ea_lgrp, sizeof (xpp->ea_lgrp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"PC_LGRP\" uname=\"" STXT ("Page locality group (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->pc_lgrp, sizeof (xpp->pc_lgrp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"LWP_LGRP_HOME\" uname=\"" STXT ("LWP home lgroup id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->lgrp_lwp, sizeof (xpp->lgrp_lwp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"PS_LGRP_HOME\" uname=\"" STXT ("Process home lgroup id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->lgrp_ps, sizeof (xpp->lgrp_ps) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"MEM_LAT\" uname=\"" STXT ("Memory Latency Cycles") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->latency, sizeof (xpp->latency) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"MEM_SRC\" uname=\"" STXT ("Memory Data Source") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&xpp->data_source, sizeof (xpp->data_source) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog ("</profpckt>\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwclogwrite (Hwcentry * ctr)
|
||||
{
|
||||
TprintfT (DBG_LT1, "hwprofile: writeLog(%s %u %s %d %u %d)\n",
|
||||
SP_JCMD_HW_COUNTER, cpcN_cpuver, ctr->name ? ctr->name : "NULL",
|
||||
ctr->val, ctr->sort_order, ctr->memop);
|
||||
collector_interface->writeLog ("<profile name=\"%s\"", SP_JCMD_HW_COUNTER);
|
||||
collector_interface->writeLog (" cpuver=\"%u\"", cpcN_cpuver);
|
||||
collector_interface->writeLog (" hwcname=\"%s\"", ctr->name);
|
||||
collector_interface->writeLog (" int_name=\"%s\"", ctr->int_name);
|
||||
collector_interface->writeLog (" interval=\"%d\"", ctr->val);
|
||||
collector_interface->writeLog (" tag=\"%u\"", ctr->sort_order);
|
||||
collector_interface->writeLog (" memop=\"%d\"", ctr->memop);
|
||||
collector_interface->writeLog ("/>\n");
|
||||
}
|
89
gprofng/libcollector/hwprofile.h
Normal file
89
gprofng/libcollector/hwprofile.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* Copyright (C) 2021 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 _HWPROFILE_H
|
||||
#define _HWPROFILE_H
|
||||
|
||||
#include <data_pckts.h>
|
||||
|
||||
typedef struct Hwcntr_packet
|
||||
{ /* HW counter profiling packet */
|
||||
Common_packet comm;
|
||||
uint32_t tag; /* hw counter index, register */
|
||||
uint64_t interval; /* overflow value */
|
||||
} Hwcntr_packet;
|
||||
|
||||
typedef struct MHwcntr_packet
|
||||
{ /* extended (superset) Hwcntr_packet */
|
||||
Common_packet comm;
|
||||
uint32_t tag; /* hw counter index, register */
|
||||
uint64_t interval; /* overflow value */
|
||||
Vaddr_type ea_vaddr; /* virtual addr causing HWC event */
|
||||
Vaddr_type pc_vaddr; /* candidate eventPC */
|
||||
uint64_t ea_paddr; /* physical address for ea_vaddr */
|
||||
uint64_t pc_paddr; /* physical address for pc_vaddr */
|
||||
uint64_t ea_pagesz; /* pagesz (bytes) for ea_paddr */
|
||||
uint64_t pc_pagesz; /* pagesz (bytes) for pc_paddr */
|
||||
uint32_t ea_lgrp; /* latency group of ea_paddr */
|
||||
uint32_t pc_lgrp; /* latency group of pc_paddr */
|
||||
uint32_t lgrp_lwp; /* locality group of lwp */
|
||||
uint32_t lgrp_ps; /* locality group of process */
|
||||
uint64_t latency; /* latency in cycles (sampling only) */
|
||||
uint64_t data_source; /* data source (sampling only) */
|
||||
} MHwcntr_packet;
|
||||
|
||||
#if ARCH(SPARC)
|
||||
#define CONTEXT_PC MC_PC
|
||||
#define CONTEXT_SP MC_O6
|
||||
#define CONTEXT_FP MC_O7
|
||||
#define SETFUNCTIONCONTEXT(ucp,funcp) \
|
||||
(ucp)->uc_mcontext.gregs[CONTEXT_PC] = (greg_t)(funcp); \
|
||||
(ucp)->uc_mcontext.gregs[CONTEXT_SP] = 0; \
|
||||
(ucp)->uc_mcontext.gregs[CONTEXT_FP] = 0;
|
||||
|
||||
#elif ARCH(Intel)
|
||||
#include <sys/reg.h>
|
||||
|
||||
#if WSIZE(64)
|
||||
#define CONTEXT_PC REG_RIP
|
||||
#define CONTEXT_FP REG_RBP
|
||||
#define CONTEXT_SP REG_RSP
|
||||
|
||||
#elif WSIZE(32)
|
||||
#define CONTEXT_PC REG_EIP
|
||||
#define CONTEXT_FP REG_EBP
|
||||
#define CONTEXT_SP REG_ESP
|
||||
#endif /* WSIZE() */
|
||||
#define SETFUNCTIONCONTEXT(ucp,funcp) \
|
||||
(ucp)->uc_mcontext.gregs[CONTEXT_PC] = (greg_t)(funcp); \
|
||||
(ucp)->uc_mcontext.gregs[CONTEXT_SP] = 0; \
|
||||
(ucp)->uc_mcontext.gregs[CONTEXT_FP] = 0;
|
||||
|
||||
#elif ARCH(Aarch64)
|
||||
#define CONTEXT_PC 15
|
||||
#define CONTEXT_FP 14
|
||||
#define CONTEXT_SP 13
|
||||
#define SETFUNCTIONCONTEXT(ucp,funcp) \
|
||||
(ucp)->uc_mcontext.regs[CONTEXT_PC] = (greg_t)(funcp); \
|
||||
(ucp)->uc_mcontext.regs[CONTEXT_SP] = 0; \
|
||||
(ucp)->uc_mcontext.regs[CONTEXT_FP] = 0;
|
||||
#endif /* ARCH() */
|
||||
|
||||
#endif
|
1156
gprofng/libcollector/iolib.c
Normal file
1156
gprofng/libcollector/iolib.c
Normal file
File diff suppressed because it is too large
Load diff
3728
gprofng/libcollector/iotrace.c
Normal file
3728
gprofng/libcollector/iotrace.c
Normal file
File diff suppressed because it is too large
Load diff
1315
gprofng/libcollector/jprofile.c
Normal file
1315
gprofng/libcollector/jprofile.c
Normal file
File diff suppressed because it is too large
Load diff
28
gprofng/libcollector/libcol-i386-dis.c
Normal file
28
gprofng/libcollector/libcol-i386-dis.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (C) 2022 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. */
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
#include "opcodes/i386-dis.c"
|
||||
|
||||
#undef _
|
||||
#undef M
|
||||
#include "libiberty/safe-ctype.c"
|
||||
#endif
|
||||
|
25
gprofng/libcollector/libcol_hwcdrv.c
Normal file
25
gprofng/libcollector/libcol_hwcdrv.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* Copyright (C) 2021 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 "collector.h" /* Tprintf*() */
|
||||
|
||||
#define LIBCOLLECTOR_SRC
|
||||
#include "hwcdrv.c"
|
27
gprofng/libcollector/libcol_hwcfuncs.c
Normal file
27
gprofng/libcollector/libcol_hwcfuncs.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* Copyright (C) 2021 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 "collector.h" /* Tprintf*() */
|
||||
|
||||
#define LIBCOLLECTOR_SRC
|
||||
#include "hwcfuncs.c"
|
||||
|
||||
|
1693
gprofng/libcollector/libcol_util.c
Normal file
1693
gprofng/libcollector/libcol_util.c
Normal file
File diff suppressed because it is too large
Load diff
321
gprofng/libcollector/libcol_util.h
Normal file
321
gprofng/libcollector/libcol_util.h
Normal file
|
@ -0,0 +1,321 @@
|
|||
/* Copyright (C) 2021 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 _LIBCOL_UTIL_H
|
||||
#define _LIBCOL_UTIL_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
// LIBCOLLECTOR NOT I18N
|
||||
#define NTXT(x) x
|
||||
#define STXT(x) x
|
||||
|
||||
extern int __collector_tracelevel;
|
||||
|
||||
/* Initialization function */
|
||||
extern int __collector_util_init();
|
||||
extern void __collector_libkstat_funcs_init();
|
||||
extern void __collector_libscf_funcs_init();
|
||||
|
||||
/* ------- functions from libcol_util.c ----------------- */
|
||||
extern void * __collector_memcpy (void *s1, const void *s2, size_t n);
|
||||
extern int (*__collector_sscanfp)(const char *restrict s, const char *restrict fmt, ...);
|
||||
extern char * __collector_strcat (char *s1, const char *s2);
|
||||
extern char * __collector_strchr (const char *s1, int chr);
|
||||
extern size_t __collector_strlcpy (char *dst, const char *src, size_t dstsize);
|
||||
extern char* __collector_strrchr (const char *str, int chr);
|
||||
extern size_t __collector_strlen (const char *s);
|
||||
extern size_t __collector_strlcat (char *dst, const char *src, size_t dstsize);
|
||||
extern char* __collector_strchr (const char *str, int chr);
|
||||
extern int __collector_strcmp (const char *s1, const char *s2);
|
||||
extern int __collector_strncmp (const char *s1, const char *s2, size_t n);
|
||||
extern char * __collector_strstr (const char *s1, const char *s2);
|
||||
extern size_t __collector_strncpy (char *dst, const char *src, size_t dstsize);
|
||||
extern size_t __collector_strncat (char *dst, const char *src, size_t dstsize);
|
||||
extern void * __collector_malloc (size_t size);
|
||||
extern void * __collector_calloc (size_t nelem, size_t elsize);
|
||||
extern char * __collector_strdup (const char * str);
|
||||
extern int __collector_strStartWith (const char *s1, const char *s2);
|
||||
extern int __collector_xml_snprintf (char *s, size_t n, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
extern int __collector_xml_vsnprintf (char *s, size_t n, const char *format, va_list args);
|
||||
|
||||
/* ------- collector_thread ----------------- */
|
||||
pid_t __collector_gettid ();
|
||||
extern void __collector_ext_gettid_tsd_create_key ();
|
||||
#define collector_thread_t pthread_t // not using pid_t, since tid is defined as pthread_t in package structures, and other codes assume this type
|
||||
#define statvfs_t struct statvfs
|
||||
#define __collector_lwp_self() (collector_thread_t)__collector_gettid() // not using pthread_self()
|
||||
#define __collector_thr_self() (collector_thread_t)__collector_gettid() // not using pthread_self()
|
||||
|
||||
/* ------- collector_mutex ----------------- */
|
||||
/*
|
||||
* mutex_init is defined in libthread. If we don't want to interact
|
||||
* with libthread we should use memset to initialize mutexes
|
||||
*/
|
||||
|
||||
typedef volatile int collector_mutex_t;
|
||||
#define COLLECTOR_MUTEX_INITIALIZER 0
|
||||
extern int __collector_mutex_lock (collector_mutex_t *mp);
|
||||
extern int __collector_mutex_unlock (collector_mutex_t *mp);
|
||||
extern int __collector_mutex_trylock (collector_mutex_t *mp);
|
||||
|
||||
#define __collector_mutex_init(xx) \
|
||||
do { collector_mutex_t tmp=COLLECTOR_MUTEX_INITIALIZER; *(xx)=tmp; } while(0)
|
||||
|
||||
void __collector_sample (char *name);
|
||||
void __collector_terminate_expt ();
|
||||
void __collector_pause ();
|
||||
void __collector_pause_m ();
|
||||
void __collector_resume ();
|
||||
|
||||
struct DT_lineno;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFUNC_API = 1, /* dynamic function declared with API */
|
||||
DFUNC_JAVA, /* dynamically compiled java method */
|
||||
DFUNC_KERNEL /* dynamic code mapped by the kernel (Linux) */
|
||||
} dfunc_mode_t;
|
||||
|
||||
extern void __collector_int_func_load (dfunc_mode_t mode, char *name,
|
||||
char *sourcename, void *vaddr,
|
||||
int size, int lntsize,
|
||||
struct DT_lineno *lntable);
|
||||
extern void __collector_int_func_unload (dfunc_mode_t mode, void *vaddr);
|
||||
|
||||
extern int __collector_sigaction (int sig, const struct sigaction *nact,
|
||||
struct sigaction *oact);
|
||||
extern void __collector_SIGDFL_handler (int sig);
|
||||
extern int __collector_ext_itimer_set (int period);
|
||||
|
||||
#if ARCH(Intel)
|
||||
/* Atomic functions on x86/x64 */
|
||||
|
||||
/**
|
||||
* This function enables the inrementing (by one) of the value stored in target
|
||||
* to occur in an atomic manner.
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline void
|
||||
__collector_inc_32 (uint32_t *ptr)
|
||||
{
|
||||
__asm__ __volatile__("lock; incl %0"
|
||||
: // "=m" (*ptr) // output
|
||||
: "m" (*ptr)); // input
|
||||
}
|
||||
|
||||
/**
|
||||
* This function enables the decrementing (by one) of the value stored in target
|
||||
* to occur in an atomic manner.
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline void
|
||||
__collector_dec_32 (volatile uint32_t *ptr)
|
||||
{
|
||||
__asm__ __volatile__("lock; decl %0"
|
||||
: // "=m" (*ptr) // output
|
||||
: "m" (*ptr)); // input
|
||||
}
|
||||
/**
|
||||
* This function subtrackts the value "off" of the value stored in target
|
||||
* to occur in an atomic manner, and returns new value stored in target.
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline uint32_t
|
||||
__collector_subget_32 (uint32_t *ptr, uint32_t off)
|
||||
{
|
||||
uint32_t r;
|
||||
uint32_t offset = off;
|
||||
__asm__ __volatile__("movl %2, %0; negl %0; lock; xaddl %0, %1"
|
||||
: "=r" (r), "=m" (*ptr) /* output */
|
||||
: "a" (off), "r" (*ptr) /* input */
|
||||
);
|
||||
return (r - offset);
|
||||
}
|
||||
/**
|
||||
* This function returns the value of the stack pointer register
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline void *
|
||||
__collector_getsp ()
|
||||
{
|
||||
void *r;
|
||||
#if WSIZE(64)
|
||||
__asm__ __volatile__("movq %%rsp, %0"
|
||||
#else
|
||||
__asm__ __volatile__("movl %%esp, %0"
|
||||
#endif
|
||||
: "=r" (r)); // output
|
||||
return r;
|
||||
}
|
||||
/**
|
||||
* This function returns the value of the frame pointer register
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline void *
|
||||
__collector_getfp ()
|
||||
{
|
||||
void *r;
|
||||
#if WSIZE(64)
|
||||
__asm__ __volatile__("movq %%rbp, %0"
|
||||
#else
|
||||
__asm__ __volatile__("movl %%ebp, %0"
|
||||
#endif
|
||||
: "=r" (r)); // output
|
||||
return r;
|
||||
}
|
||||
/**
|
||||
* This function returns the value of the processor counter register
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline void *
|
||||
__collector_getpc ()
|
||||
{
|
||||
void *r;
|
||||
__asm__ __volatile__(
|
||||
#if WSIZE(32)
|
||||
" call 1f \n"
|
||||
"1: popl %0 \n"
|
||||
#else
|
||||
" call 1f \n"
|
||||
"1: popq %0 \n"
|
||||
#endif
|
||||
: "=r" (r)); // output
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function enables a compare and swap operation to occur atomically.
|
||||
* The 32-bit value stored in target is compared with "old". If these values
|
||||
* are equal, the value stored in target is replaced with "new". The old
|
||||
* 32-bit value stored in target is returned by the function whether or not
|
||||
* the replacement occurred.
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline uint32_t
|
||||
__collector_cas_32 (volatile uint32_t *pdata, uint32_t old, uint32_t new)
|
||||
{
|
||||
uint32_t r;
|
||||
__asm__ __volatile__("lock; cmpxchgl %2, %1"
|
||||
: "=a" (r), "=m" (*pdata) : "r" (new),
|
||||
"a" (old), "m" (*pdata));
|
||||
return r;
|
||||
}
|
||||
/**
|
||||
* This function enables a compare and swap operation to occur atomically.
|
||||
* The 64-bit value stored in target is compared with "old". If these values
|
||||
* are equal, the value stored in target is replaced with "new". The old
|
||||
* 64-bit value stored in target is returned by the function whether or not
|
||||
* the replacement occurred.
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline uint64_t
|
||||
__collector_cas_64p (volatile uint64_t *mem, uint64_t *old, uint64_t * new)
|
||||
{
|
||||
uint64_t r;
|
||||
#if WSIZE(32)
|
||||
uint32_t old1 = (uint32_t) (*old & 0xFFFFFFFFL);
|
||||
uint32_t old2 = (uint32_t) ((*old >> 32) & 0xFFFFFFFFL);
|
||||
uint32_t new1 = (uint32_t) (*new & 0xFFFFFFFFL);
|
||||
uint32_t new2 = (uint32_t) ((*new >> 32) & 0xFFFFFFFFL);
|
||||
uint32_t res1 = 0;
|
||||
uint32_t res2 = 0;
|
||||
__asm__ __volatile__(
|
||||
"movl %3, %%esi; lock; cmpxchg8b (%%esi); movl %%edx, %2; movl %%eax, %1"
|
||||
: "=m" (r), "=m" (res1), "=m" (res2) /* output */
|
||||
: "m" (mem), "a" (old1), "d" (old2), "b" (new1), "c" (new2) /* input */
|
||||
: "memory", "cc", "esi" //, "edx", "ecx", "ebx", "eax" /* clobbered register */
|
||||
);
|
||||
r = (((uint64_t) res2) << 32) | ((uint64_t) res1);
|
||||
#else
|
||||
__asm__ __volatile__( "lock; cmpxchgq %2, %1"
|
||||
: "=a" (r), "=m" (*mem) /* output */
|
||||
: "r" (*new), "a" (*old), "m" (*mem) /* input */
|
||||
: "%rcx", "rdx" /* clobbered register */
|
||||
);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
/**
|
||||
* This function enables a compare and swap operation to occur atomically.
|
||||
* The 32-/64-bit value stored in target is compared with "cmp". If these values
|
||||
* are equal, the value stored in target is replaced with "new".
|
||||
* The old value stored in target is returned by the function whether or not
|
||||
* the replacement occurred.
|
||||
*/
|
||||
static __attribute__ ((always_inline)) inline void *
|
||||
__collector_cas_ptr (void *mem, void *cmp, void *new)
|
||||
{
|
||||
void *r;
|
||||
#if WSIZE(32)
|
||||
r = (void *) __collector_cas_32 ((volatile uint32_t *)mem, (uint32_t) cmp, (uint32_t)new);
|
||||
#else
|
||||
__asm__ __volatile__("lock; cmpxchgq %2, (%1)"
|
||||
: "=a" (r), "=b" (mem) /* output */
|
||||
: "r" (new), "a" (cmp), "b" (mem) /* input */
|
||||
);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
#elif ARCH(Aarch64)
|
||||
static __attribute__ ((always_inline)) inline uint32_t
|
||||
__collector_inc_32 (volatile uint32_t *ptr)
|
||||
{
|
||||
return __sync_add_and_fetch (ptr, 1);
|
||||
}
|
||||
|
||||
static __attribute__ ((always_inline)) inline uint32_t
|
||||
__collector_dec_32 (volatile uint32_t *ptr)
|
||||
{
|
||||
return __sync_sub_and_fetch (ptr, 1);
|
||||
}
|
||||
|
||||
static __attribute__ ((always_inline)) inline uint32_t
|
||||
__collector_subget_32 (volatile uint32_t *ptr, uint32_t off)
|
||||
{
|
||||
return __sync_sub_and_fetch (ptr, off);
|
||||
}
|
||||
|
||||
static __attribute__ ((always_inline)) inline uint32_t
|
||||
__collector_cas_32 (volatile uint32_t *ptr, uint32_t old, uint32_t new)
|
||||
{
|
||||
return __sync_val_compare_and_swap (ptr, old, new);
|
||||
}
|
||||
|
||||
static __attribute__ ((always_inline)) inline uint64_t
|
||||
__collector_cas_64p (volatile uint64_t *ptr, uint64_t *old, uint64_t * new)
|
||||
{
|
||||
return __sync_val_compare_and_swap (ptr, *old, *new);
|
||||
}
|
||||
|
||||
static __attribute__ ((always_inline)) inline void *
|
||||
__collector_cas_ptr (void *ptr, void *old, void *new)
|
||||
{
|
||||
return (void *) __sync_val_compare_and_swap ((unsigned long *) ptr, (unsigned long) old, (unsigned long) new);
|
||||
}
|
||||
|
||||
#else
|
||||
extern void __collector_flushw (); /* defined for SPARC only */
|
||||
extern void* __collector_getpc ();
|
||||
extern void* __collector_getsp ();
|
||||
extern void* __collector_getfp ();
|
||||
extern void __collector_inc_32 (volatile uint32_t *);
|
||||
extern void __collector_dec_32 (volatile uint32_t *);
|
||||
extern void* __collector_cas_ptr (volatile void *, void *, void *);
|
||||
extern uint32_t __collector_cas_32 (volatile uint32_t *, uint32_t, uint32_t);
|
||||
extern uint32_t __collector_subget_32 (volatile uint32_t *, uint32_t);
|
||||
extern uint64_t __collector_cas_64p (volatile uint64_t *, uint64_t *, uint64_t *);
|
||||
#endif /* ARCH() */
|
||||
#endif /* _LIBCOL_UTIL_H */
|
2005
gprofng/libcollector/linetrace.c
Normal file
2005
gprofng/libcollector/linetrace.c
Normal file
File diff suppressed because it is too large
Load diff
40
gprofng/libcollector/mapfile.aarch64-Linux
Normal file
40
gprofng/libcollector/mapfile.aarch64-Linux
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
GLIBC_2.17 {
|
||||
global:
|
||||
posix_spawn;
|
||||
posix_spawnp;
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_join;
|
||||
sem_wait;
|
||||
pthread_create;
|
||||
dlopen;
|
||||
popen;
|
||||
timer_create;
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
fopen;
|
||||
fclose;
|
||||
fdopen;
|
||||
fgetpos;
|
||||
fsetpos;
|
||||
};
|
79
gprofng/libcollector/mapfile.amd64-Linux
Normal file
79
gprofng/libcollector/mapfile.amd64-Linux
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
GLIBC_2.2.5 {
|
||||
global:
|
||||
posix_spawn;
|
||||
posix_spawnp;
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_join;
|
||||
sem_wait;
|
||||
pthread_create;
|
||||
dlopen;
|
||||
popen;
|
||||
timer_create;
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
fopen;
|
||||
fclose;
|
||||
fdopen;
|
||||
fgetpos;
|
||||
fsetpos;
|
||||
};
|
||||
|
||||
GLIBC_2.3.2 {
|
||||
global:
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
};
|
||||
|
||||
GLIBC_2.3.3 {
|
||||
global:
|
||||
timer_create;
|
||||
};
|
||||
|
||||
GLIBC_2.15 {
|
||||
global:
|
||||
posix_spawn;
|
||||
posix_spawnp;
|
||||
};
|
||||
|
||||
GLIBC_2.17 {
|
||||
global:
|
||||
posix_spawn;
|
||||
posix_spawnp;
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_join;
|
||||
sem_wait;
|
||||
pthread_create;
|
||||
dlopen;
|
||||
popen;
|
||||
timer_create;
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
fopen;
|
||||
fclose;
|
||||
fdopen;
|
||||
fgetpos;
|
||||
fsetpos;
|
||||
};
|
||||
|
81
gprofng/libcollector/mapfile.intel-Linux
Normal file
81
gprofng/libcollector/mapfile.intel-Linux
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
GLIBC_2.0 {
|
||||
global:
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_join;
|
||||
pthread_create;
|
||||
dlopen;
|
||||
popen;
|
||||
sem_wait;
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
fopen;
|
||||
fclose;
|
||||
fdopen;
|
||||
fgetpos;
|
||||
fsetpos;
|
||||
};
|
||||
|
||||
GLIBC_2.1 {
|
||||
global:
|
||||
sem_wait;
|
||||
pthread_create;
|
||||
dlopen;
|
||||
open64;
|
||||
pread;
|
||||
pwrite;
|
||||
pwrite64;
|
||||
popen;
|
||||
fopen;
|
||||
fclose;
|
||||
fdopen;
|
||||
fgetpos64;
|
||||
fsetpos64;
|
||||
};
|
||||
|
||||
GLIBC_2.2 {
|
||||
global:
|
||||
open64;
|
||||
posix_spawn;
|
||||
posix_spawnp;
|
||||
pread;
|
||||
pwrite;
|
||||
pwrite64;
|
||||
timer_create;
|
||||
fgetpos;
|
||||
fsetpos;
|
||||
fgetpos64;
|
||||
fsetpos64;
|
||||
};
|
||||
|
||||
GLIBC_2.3.2 {
|
||||
global:
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
};
|
||||
|
||||
GLIBC_2.15 {
|
||||
global:
|
||||
posix_spawn;
|
||||
posix_spawnp;
|
||||
};
|
40
gprofng/libcollector/mapfile.sparc-Linux
Normal file
40
gprofng/libcollector/mapfile.sparc-Linux
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
GLIBC_2.0 {
|
||||
global:
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_join;
|
||||
};
|
||||
|
||||
GLIBC_2.1 {
|
||||
global:
|
||||
sem_wait;
|
||||
pthread_create;
|
||||
dlopen;
|
||||
popen;
|
||||
};
|
||||
|
||||
GLIBC_2.3.2 {
|
||||
global:
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
};
|
58
gprofng/libcollector/mapfile.sparcv9-Linux
Normal file
58
gprofng/libcollector/mapfile.sparcv9-Linux
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
GLIBC_2.0 {
|
||||
global:
|
||||
dlopen;
|
||||
};
|
||||
|
||||
GLIBC_2.1 {
|
||||
global:
|
||||
dlopen;
|
||||
};
|
||||
|
||||
GLIBC_2.2 {
|
||||
global:
|
||||
pthread_create;
|
||||
popen;
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_join;
|
||||
sem_wait;
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
timer_create;
|
||||
fopen;
|
||||
fclose;
|
||||
fdopen;
|
||||
fgetpos;
|
||||
fsetpos;
|
||||
};
|
||||
|
||||
GLIBC_2.3.2 {
|
||||
global:
|
||||
pthread_cond_wait;
|
||||
pthread_cond_timedwait;
|
||||
};
|
||||
|
||||
GLIBC_2.3.3 {
|
||||
global:
|
||||
timer_create;
|
||||
};
|
396
gprofng/libcollector/memmgr.c
Normal file
396
gprofng/libcollector/memmgr.c
Normal file
|
@ -0,0 +1,396 @@
|
|||
/* Copyright (C) 2021 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 <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "collector.h"
|
||||
#include "libcol_util.h"
|
||||
#include "gp-experiment.h"
|
||||
#include "memmgr.h"
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
#define DBG_LT4 4
|
||||
|
||||
/*
|
||||
* Memory allocation.
|
||||
*
|
||||
* Heap:
|
||||
* chain[0] - linked list of chunks;
|
||||
* chain[1] - linked list of free 16-byte objects;
|
||||
* chain[2] - linked list of free 32-byte objects;
|
||||
* ...
|
||||
*
|
||||
* Chunk:
|
||||
*
|
||||
* base lo hi
|
||||
* V V V
|
||||
* +------------------+---------+-------------------+--+--+-----+
|
||||
* | Var size object | -> <-| Const size objects| | |Chunk|
|
||||
* +------------------+---------+-------------------+--+--+-----+
|
||||
*
|
||||
* Limitations:
|
||||
* - one var size object per chunk
|
||||
* - can't allocate const size objects larger than 2^MAXCHAIN
|
||||
*/
|
||||
|
||||
#define MAXCHAIN 32
|
||||
#define ALIGNMENT 4 /* 2^ALIGNMENT == minimal size and alignment */
|
||||
#define ALIGN(x) ((((x) - 1)/(1 << ALIGNMENT) + 1) * (1 << ALIGNMENT))
|
||||
|
||||
struct Heap
|
||||
{
|
||||
collector_mutex_t lock; /* master lock */
|
||||
void *chain[MAXCHAIN]; /* chain[0] - chunks */
|
||||
/* chain[i] - structs of size 2^i */
|
||||
};
|
||||
|
||||
typedef struct Chunk
|
||||
{
|
||||
size_t size;
|
||||
char *base;
|
||||
char *lo;
|
||||
char *hi;
|
||||
struct Chunk *next;
|
||||
} Chunk;
|
||||
|
||||
static void
|
||||
not_implemented ()
|
||||
{
|
||||
__collector_log_write ("<event kind=\"%s\" id=\"%d\">error memmgr not_implemented()</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_NOZMEM);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* void __collector_mmgr_init_mutex_locks( Heap *heap )
|
||||
* Iinitialize mmgr mutex locks.
|
||||
*/
|
||||
void
|
||||
__collector_mmgr_init_mutex_locks (Heap *heap)
|
||||
{
|
||||
if (heap == NULL)
|
||||
return;
|
||||
if (__collector_mutex_trylock (&heap->lock))
|
||||
{
|
||||
/*
|
||||
* We are in a child process immediately after the fork().
|
||||
* Parent process was in the middle of critical section when the fork() happened.
|
||||
* This is a placeholder for the cleanup.
|
||||
* See CR 6997020 for details.
|
||||
*/
|
||||
__collector_mutex_init (&heap->lock);
|
||||
}
|
||||
__collector_mutex_init (&heap->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* alloc_chunk( unsigned sz ) allocates a chunk of at least sz bytes.
|
||||
* If sz == 0, allocates a chunk of the default size.
|
||||
*/
|
||||
static Chunk *
|
||||
alloc_chunk (unsigned sz, int log)
|
||||
{
|
||||
static long pgsz = 0;
|
||||
char *ptr;
|
||||
Chunk *chnk;
|
||||
size_t chunksz;
|
||||
if (pgsz == 0)
|
||||
{
|
||||
pgsz = CALL_UTIL (sysconf)(_SC_PAGESIZE);
|
||||
Tprintf (DBG_LT2, "memmgr: pgsz = %ld (0x%lx)\n", pgsz, pgsz);
|
||||
}
|
||||
/* Allocate 2^n >= sz bytes */
|
||||
unsigned nsz = ALIGN (sizeof (Chunk)) + sz;
|
||||
for (chunksz = pgsz; chunksz < nsz; chunksz *= 2);
|
||||
if (log == 1)
|
||||
Tprintf (DBG_LT2, "alloc_chunk mapping %u, rounded up from %u\n", (unsigned int) chunksz, sz);
|
||||
/* mmap64 is only in 32-bits; this call goes to mmap in 64-bits */
|
||||
ptr = (char*) CALL_UTIL (mmap64)(0, chunksz, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, (int) -1, (off64_t) 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
Tprintf (0, "alloc_chunk mapping failed COL_ERROR_NOZMEMMAP: %s\n", CALL_UTIL (strerror)(errno));
|
||||
__collector_log_write ("<event kind=\"%s\" id=\"%d\" ec=\"%d\">%s</event>\n",
|
||||
SP_JCMD_CERROR, COL_ERROR_NOZMEMMAP, errno, "0");
|
||||
return NULL;
|
||||
}
|
||||
/* Put the chunk descriptor at the end of the chunk */
|
||||
chnk = (Chunk*) (ptr + chunksz - ALIGN (sizeof (Chunk)));
|
||||
chnk->size = chunksz;
|
||||
chnk->base = ptr;
|
||||
chnk->lo = chnk->base;
|
||||
chnk->hi = (char*) chnk;
|
||||
chnk->next = (Chunk*) NULL;
|
||||
if (log == 1)
|
||||
Tprintf (DBG_LT2, "memmgr: returning new chunk @%p, chunksx=%ld sz=%ld\n",
|
||||
ptr, (long) chunksz, (long) sz);
|
||||
return chnk;
|
||||
}
|
||||
|
||||
Heap *
|
||||
__collector_newHeap ()
|
||||
{
|
||||
Heap *heap;
|
||||
Chunk *chnk;
|
||||
Tprintf (DBG_LT2, "__collector_newHeap calling alloc_chunk(0)\n");
|
||||
chnk = alloc_chunk (0, 1);
|
||||
if (chnk == NULL)
|
||||
return NULL;
|
||||
|
||||
/* A bit of hackery: allocate heap from its own chunk */
|
||||
chnk->hi -= ALIGN (sizeof (Heap));
|
||||
heap = (Heap*) chnk->hi;
|
||||
heap->chain[0] = (void*) chnk;
|
||||
__collector_mutex_init (&heap->lock);
|
||||
return heap;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_deleteHeap (Heap *heap)
|
||||
{
|
||||
if (heap == NULL)
|
||||
return;
|
||||
/* Note: heap itself is in the last chunk */
|
||||
for (Chunk *chnk = heap->chain[0]; chnk;)
|
||||
{
|
||||
Chunk *next = chnk->next;
|
||||
CALL_UTIL (munmap)((void*) chnk->base, chnk->size);
|
||||
chnk = next;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
__collector_allocCSize (Heap *heap, unsigned sz, int log)
|
||||
{
|
||||
void *res;
|
||||
Chunk *chnk;
|
||||
if (heap == NULL)
|
||||
return NULL;
|
||||
|
||||
/* block all signals and acquire lock */
|
||||
sigset_t old_mask, new_mask;
|
||||
CALL_UTIL (sigfillset)(&new_mask);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &new_mask, &old_mask);
|
||||
__collector_mutex_lock (&heap->lock);
|
||||
|
||||
/* Allocate nsz = 2^idx >= sz bytes */
|
||||
unsigned idx = ALIGNMENT;
|
||||
unsigned nsz = 1 << idx;
|
||||
while (nsz < sz)
|
||||
nsz = 1 << ++idx;
|
||||
|
||||
/* Look in the corresponding chain first */
|
||||
if (idx < MAXCHAIN)
|
||||
{
|
||||
if (heap->chain[idx] != NULL)
|
||||
{
|
||||
res = heap->chain[idx];
|
||||
heap->chain[idx] = *(void**) res;
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
if (log == 1)
|
||||
Tprintf (DBG_LT2, "memmgr: allocCSize %p sz %d (0x%x) req = 0x%x, from chain idx = %d\n", res, nsz, nsz, sz, idx);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
not_implemented ();
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Chain is empty, allocate from chunks */
|
||||
for (chnk = (Chunk*) heap->chain[0]; chnk; chnk = chnk->next)
|
||||
if (chnk->lo + nsz < chnk->hi)
|
||||
break;
|
||||
if (chnk == NULL)
|
||||
{
|
||||
/* Get a new chunk */
|
||||
if (log == 1)
|
||||
Tprintf (DBG_LT2, "__collector_allocCSize (%u) calling alloc_chunk(%u)\n", sz, nsz);
|
||||
chnk = alloc_chunk (nsz, 1);
|
||||
if (chnk == NULL)
|
||||
{
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
return NULL;
|
||||
}
|
||||
chnk->next = (Chunk*) heap->chain[0];
|
||||
heap->chain[0] = chnk;
|
||||
}
|
||||
|
||||
/* Allocate from the chunk */
|
||||
chnk->hi -= nsz;
|
||||
res = (void*) chnk->hi;
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
if (log == 1)
|
||||
Tprintf (DBG_LT2, "memmgr: allocCSize %p sz %d (0x%x) req = 0x%x, new chunk\n", res, nsz, nsz, sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_freeCSize (Heap *heap, void *ptr, unsigned sz)
|
||||
{
|
||||
if (heap == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
/* block all signals and acquire lock */
|
||||
sigset_t old_mask, new_mask;
|
||||
CALL_UTIL (sigfillset)(&new_mask);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &new_mask, &old_mask);
|
||||
__collector_mutex_lock (&heap->lock);
|
||||
|
||||
/* Free 2^idx >= sz bytes */
|
||||
unsigned idx = ALIGNMENT;
|
||||
unsigned nsz = 1 << idx;
|
||||
while (nsz < sz)
|
||||
nsz = 1 << ++idx;
|
||||
if (idx < MAXCHAIN)
|
||||
{
|
||||
*(void**) ptr = heap->chain[idx];
|
||||
heap->chain[idx] = ptr;
|
||||
}
|
||||
else
|
||||
not_implemented ();
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
Tprintf (DBG_LT4, "memmgr: freeC %p sz %ld\n", ptr, (long) sz);
|
||||
}
|
||||
|
||||
static void *
|
||||
allocVSize_nolock (Heap *heap, unsigned sz)
|
||||
{
|
||||
void *res;
|
||||
Chunk *chnk;
|
||||
if (sz == 0)
|
||||
return NULL;
|
||||
|
||||
/* Find a good chunk */
|
||||
for (chnk = (Chunk*) heap->chain[0]; chnk; chnk = chnk->next)
|
||||
if (chnk->lo == chnk->base && chnk->lo + sz < chnk->hi)
|
||||
break;
|
||||
if (chnk == NULL)
|
||||
{
|
||||
/* Get a new chunk */
|
||||
Tprintf (DBG_LT2, "allocVsize_nolock calling alloc_chunk(%u)\n", sz);
|
||||
chnk = alloc_chunk (sz, 0);
|
||||
if (chnk == NULL)
|
||||
return NULL;
|
||||
chnk->next = (Chunk*) heap->chain[0];
|
||||
heap->chain[0] = chnk;
|
||||
}
|
||||
chnk->lo = chnk->base + sz;
|
||||
res = (void*) (chnk->base);
|
||||
Tprintf (DBG_LT4, "memmgr: allocV %p for %ld\n", res, (long) sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
__collector_allocVSize (Heap *heap, unsigned sz)
|
||||
{
|
||||
void *res;
|
||||
if (heap == NULL)
|
||||
return NULL;
|
||||
|
||||
/* block all signals and acquire lock */
|
||||
sigset_t old_mask, new_mask;
|
||||
CALL_UTIL (sigfillset)(&new_mask);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &new_mask, &old_mask);
|
||||
__collector_mutex_lock (&heap->lock);
|
||||
res = allocVSize_nolock (heap, sz);
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* reallocVSize( Heap *heap, void *ptr, unsigned newsz )
|
||||
* Changes the size of memory pointed by ptr to newsz.
|
||||
* If ptr == NULL, allocates new memory of size newsz.
|
||||
* If newsz == 0, frees ptr and returns NULL.
|
||||
*/
|
||||
void *
|
||||
__collector_reallocVSize (Heap *heap, void *ptr, unsigned newsz)
|
||||
{
|
||||
Chunk *chnk;
|
||||
void *res;
|
||||
if (heap == NULL)
|
||||
return NULL;
|
||||
if (ptr == NULL)
|
||||
return __collector_allocVSize (heap, newsz);
|
||||
|
||||
/* block all signals and acquire lock */
|
||||
sigset_t old_mask, new_mask;
|
||||
CALL_UTIL (sigfillset)(&new_mask);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &new_mask, &old_mask);
|
||||
__collector_mutex_lock (&heap->lock);
|
||||
|
||||
/* Find its chunk */
|
||||
for (chnk = (Chunk*) heap->chain[0]; chnk; chnk = chnk->next)
|
||||
if (ptr == chnk->base)
|
||||
break;
|
||||
if (chnk == NULL)
|
||||
{
|
||||
/* memory corrpution */
|
||||
not_implemented ();
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (chnk->base + newsz < chnk->hi)
|
||||
{
|
||||
/* easy case */
|
||||
chnk->lo = chnk->base + newsz;
|
||||
res = newsz ? chnk->base : NULL;
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
Tprintf (DBG_LT4, "memmgr: reallocV %p for %ld\n", ptr, (long) newsz);
|
||||
return res;
|
||||
}
|
||||
res = allocVSize_nolock (heap, newsz);
|
||||
/* Copy to new location */
|
||||
if (res)
|
||||
{
|
||||
int size = chnk->lo - chnk->base;
|
||||
if (newsz < size)
|
||||
size = newsz;
|
||||
char *s1 = (char*) res;
|
||||
char *s2 = chnk->base;
|
||||
while (size--)
|
||||
*s1++ = *s2++;
|
||||
}
|
||||
/* Free old memory*/
|
||||
chnk->lo = chnk->base;
|
||||
__collector_mutex_unlock (&heap->lock);
|
||||
CALL_UTIL (sigprocmask)(SIG_SETMASK, &old_mask, NULL);
|
||||
return res;
|
||||
}
|
59
gprofng/libcollector/memmgr.h
Normal file
59
gprofng/libcollector/memmgr.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) 2021 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 _MEMMGR_H
|
||||
#define _MEMMGR_H
|
||||
|
||||
struct Heap;
|
||||
typedef struct Heap Heap;
|
||||
|
||||
Heap *__collector_newHeap ();
|
||||
void __collector_deleteHeap (Heap *heap);
|
||||
|
||||
/*
|
||||
* Initialize memmgr mutex locks.
|
||||
*/
|
||||
void __collector_mmgr_init_mutex_locks (Heap *heap);
|
||||
|
||||
/*
|
||||
* Allocate non-resizable memory.
|
||||
*/
|
||||
void *__collector_allocCSize (Heap *heap, unsigned sz, int log);
|
||||
|
||||
/*
|
||||
* Free non-resizable memory.
|
||||
*/
|
||||
void __collector_freeCSize (Heap *heap, void *ptr, unsigned sz);
|
||||
|
||||
/*
|
||||
* Allocate resizable memory
|
||||
*/
|
||||
void *__collector_allocVSize (Heap *heap, unsigned sz);
|
||||
|
||||
/*
|
||||
* Change size of resizable memory.
|
||||
* ptr - if not NULL, it must have been previously allocated from
|
||||
* the same heap, otherwise returns allocVSize(heap, newsz);
|
||||
* newsz - new size; if 0, memory is freed and no new allocation
|
||||
* occurs;
|
||||
*/
|
||||
void *__collector_reallocVSize (Heap *heap, void *ptr, unsigned newsz);
|
||||
|
||||
#endif
|
1691
gprofng/libcollector/mmaptrace.c
Normal file
1691
gprofng/libcollector/mmaptrace.c
Normal file
File diff suppressed because it is too large
Load diff
287
gprofng/libcollector/profile.c
Normal file
287
gprofng/libcollector/profile.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* Profile handling
|
||||
*
|
||||
* Note: SIGPROF signal-handling and interval timer (once exclusive to
|
||||
* profile handling) are now common services provided by the dispatcher.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gp-defs.h"
|
||||
#include "collector_module.h"
|
||||
#include "gp-experiment.h"
|
||||
#include "data_pckts.h"
|
||||
#include "libcol_util.h"
|
||||
#include "hwprofile.h"
|
||||
#include "tsd.h"
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
|
||||
static int init_interface (CollectorInterface*);
|
||||
static int open_experiment (const char *);
|
||||
static int start_data_collection (void);
|
||||
static int stop_data_collection (void);
|
||||
static int close_experiment (void);
|
||||
static int detach_experiment (void);
|
||||
|
||||
static ModuleInterface module_interface ={
|
||||
SP_PROFILE_FILE, /* description */
|
||||
init_interface, /* initInterface */
|
||||
open_experiment, /* openExperiment */
|
||||
start_data_collection, /* startDataCollection */
|
||||
stop_data_collection, /* stopDataCollection */
|
||||
close_experiment, /* closeExperiment */
|
||||
detach_experiment /* detachExperiment (fork child) */
|
||||
};
|
||||
|
||||
static CollectorInterface *collector_interface = NULL;
|
||||
static int prof_mode = 0;
|
||||
static CollectorModule prof_hndl = COLLECTOR_MODULE_ERR;
|
||||
static unsigned prof_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
|
||||
typedef struct ClockPacket
|
||||
{ /* clock profiling packet */
|
||||
CM_Packet comm;
|
||||
pthread_t lwp_id;
|
||||
pthread_t thr_id;
|
||||
uint32_t cpu_id;
|
||||
hrtime_t tstamp __attribute__ ((packed));
|
||||
uint64_t frinfo __attribute__ ((packed));
|
||||
int mstate; /* kernel microstate */
|
||||
int nticks; /* number of ticks in that state */
|
||||
} ClockPacket;
|
||||
|
||||
/* XXX should be able to use local types */
|
||||
#define CLOCK_TYPE OPROF_PCKT
|
||||
|
||||
#define CHCK_REENTRANCE(x) ( !prof_mode || ((x) = collector_interface->getKey( prof_key )) == NULL || (*(x) != 0) )
|
||||
#define PUSH_REENTRANCE(x) ((*(x))++)
|
||||
#define POP_REENTRANCE(x) ((*(x))--)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
|
||||
#define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
|
||||
#else
|
||||
#define Tprintf(...)
|
||||
#define TprintfT(...)
|
||||
#endif
|
||||
|
||||
static void init_module () __attribute__ ((constructor));
|
||||
|
||||
static void
|
||||
init_module ()
|
||||
{
|
||||
__collector_dlsym_guard = 1;
|
||||
RegModuleFunc reg_module = (RegModuleFunc) dlsym (RTLD_DEFAULT, "__collector_register_module");
|
||||
__collector_dlsym_guard = 0;
|
||||
if (reg_module == NULL)
|
||||
{
|
||||
TprintfT (0, "clockprof: init_module FAILED -- reg_module = NULL\n");
|
||||
return;
|
||||
}
|
||||
prof_hndl = reg_module (&module_interface);
|
||||
if (prof_hndl == COLLECTOR_MODULE_ERR && collector_interface != NULL)
|
||||
{
|
||||
Tprintf (0, "clockprof: ERROR: handle not created.\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n", SP_JCMD_CERROR, COL_ERROR_PROFINIT);
|
||||
}
|
||||
TprintfT (0, "clockprof: init_module, prof_hndl = %d\n", prof_hndl);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
init_interface (CollectorInterface *_collector_interface)
|
||||
{
|
||||
collector_interface = _collector_interface;
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
open_experiment (const char *exp)
|
||||
{
|
||||
if (collector_interface == NULL)
|
||||
{
|
||||
Tprintf (0, "clockprof: ERROR: collector_interface is null.\n");
|
||||
return COL_ERROR_PROFINIT;
|
||||
}
|
||||
const char *params = collector_interface->getParams ();
|
||||
while (params)
|
||||
{
|
||||
if (__collector_strStartWith (params, "p:") == 0)
|
||||
{
|
||||
params += 2;
|
||||
break;
|
||||
}
|
||||
while (*params != 0 && *params != ';')
|
||||
params++;
|
||||
if (*params == 0)
|
||||
params = NULL;
|
||||
else
|
||||
params++;
|
||||
}
|
||||
if (params == NULL) /* Clock profiling not specified */
|
||||
return COL_ERROR_PROFINIT;
|
||||
TprintfT (0, "clockprof: open_experiment %s -- %s\n", exp, params);
|
||||
int prof_interval = CALL_UTIL (strtol)(params, NULL, 0);
|
||||
prof_key = collector_interface->createKey (sizeof ( int), NULL, NULL);
|
||||
if (prof_key == (unsigned) - 1)
|
||||
{
|
||||
Tprintf (0, "clockprof: ERROR: TSD key create failed.\n");
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n", SP_JCMD_CERROR, COL_ERROR_PROFINIT);
|
||||
return COL_ERROR_PROFINIT;
|
||||
}
|
||||
|
||||
/* set dispatcher interval timer period used for all timed activities */
|
||||
int prof_interval_actual = __collector_ext_itimer_set (prof_interval);
|
||||
TprintfT (0, "clockprof: open_experiment(): __collector_ext_itimer_set (actual period=%d, req_period=%d)\n",
|
||||
prof_interval_actual, prof_interval);
|
||||
if (prof_interval_actual <= 0)
|
||||
{
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">itimer could not be set</event>\n", SP_JCMD_CERROR, COL_ERROR_PROFINIT);
|
||||
return COL_ERROR_PROFINIT;
|
||||
}
|
||||
if ((prof_interval_actual >= (prof_interval + prof_interval / 10)) ||
|
||||
(prof_interval_actual <= (prof_interval - prof_interval / 10)))
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n", SP_JCMD_CWARN, COL_WARN_PROFRND, prof_interval, prof_interval_actual);
|
||||
else if (prof_interval_actual != prof_interval)
|
||||
collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n", SP_JCMD_COMMENT, COL_WARN_PROFRND, prof_interval, prof_interval_actual);
|
||||
prof_interval = prof_interval_actual;
|
||||
collector_interface->writeLog ("<profile name=\"%s\" ptimer=\"%d\" numstates=\"%d\">\n",
|
||||
SP_JCMD_PROFILE, prof_interval, LMS_MAGIC_ID_LINUX);
|
||||
collector_interface->writeLog (" <profdata fname=\"%s\"/>\n",
|
||||
module_interface.description);
|
||||
|
||||
/* Record Profile packet description */
|
||||
ClockPacket *cp = NULL;
|
||||
collector_interface->writeLog (" <profpckt kind=\"%d\" uname=\"" STXT ("Clock profiling data") "\">\n", CLOCK_TYPE);
|
||||
collector_interface->writeLog (" <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->lwp_id, sizeof (cp->lwp_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->thr_id, sizeof (cp->thr_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->cpu_id, sizeof (cp->cpu_id) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->tstamp, sizeof (cp->tstamp) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->frinfo, sizeof (cp->frinfo) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"MSTATE\" uname=\"" STXT ("Thread state") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->mstate, sizeof (cp->mstate) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" <field name=\"NTICK\" uname=\"" STXT ("Duration") "\" offset=\"%d\" type=\"%s\"/>\n",
|
||||
&cp->nticks, sizeof (cp->nticks) == 4 ? "INT32" : "INT64");
|
||||
collector_interface->writeLog (" </profpckt>\n");
|
||||
collector_interface->writeLog ("</profile>\n");
|
||||
return COL_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
start_data_collection (void)
|
||||
{
|
||||
TprintfT (0, "clockprof: start_data_collection\n");
|
||||
prof_mode = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
stop_data_collection (void)
|
||||
{
|
||||
prof_mode = 0;
|
||||
TprintfT (0, "clockprof: stop_data_collection\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
close_experiment (void)
|
||||
{
|
||||
prof_mode = 0;
|
||||
prof_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
TprintfT (0, "clockprof: close_experiment\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fork child. Clean up state but don't write to experiment */
|
||||
static int
|
||||
detach_experiment (void)
|
||||
{
|
||||
prof_mode = 0;
|
||||
prof_key = COLLECTOR_TSD_INVALID_KEY;
|
||||
TprintfT (0, "clockprof: detach_experiment\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* void collector_lost_profile_context
|
||||
* Placeholder/marker function used when profiling given NULL context.
|
||||
*/
|
||||
void
|
||||
__collector_lost_profile_context (void) { }
|
||||
|
||||
/*
|
||||
* void __collector_ext_profile_handler( siginfo_t *info, ucontext_t *context )
|
||||
* Handle real profile events to collect profile data.
|
||||
*/
|
||||
void
|
||||
__collector_ext_profile_handler (siginfo_t *info, ucontext_t *context)
|
||||
{
|
||||
int *guard;
|
||||
if (!prof_mode) /* sigprof timer running only because hwprofile.c needs it */
|
||||
return;
|
||||
if (CHCK_REENTRANCE (guard))
|
||||
{
|
||||
TprintfT (0, "__collector_ext_profile_handler: ERROR: prof_mode=%d guard=%d!\n",
|
||||
prof_mode, guard ? *guard : -2);
|
||||
return;
|
||||
}
|
||||
PUSH_REENTRANCE (guard);
|
||||
TprintfT (DBG_LT3, "__collector_ext_profile_handler\n");
|
||||
ucontext_t uctxmem;
|
||||
if (context == NULL)
|
||||
{
|
||||
/* assume this case is rare, and accept overhead of creating dummy_uc */
|
||||
TprintfT (0, "collector_profile_handler: ERROR: got NULL context!\n");
|
||||
context = &uctxmem;
|
||||
getcontext (context); /* initialize dummy context */
|
||||
SETFUNCTIONCONTEXT (context, &__collector_lost_profile_context);
|
||||
}
|
||||
ClockPacket pckt;
|
||||
CALL_UTIL (memset)(&pckt, 0, sizeof ( pckt));
|
||||
pckt.comm.tsize = sizeof ( pckt);
|
||||
pckt.comm.type = CLOCK_TYPE;
|
||||
pckt.lwp_id = __collector_lwp_self ();
|
||||
pckt.thr_id = __collector_thr_self ();
|
||||
pckt.cpu_id = CALL_UTIL (getcpuid)();
|
||||
pckt.tstamp = collector_interface->getHiResTime ();
|
||||
pckt.frinfo = collector_interface->getFrameInfo (COLLECTOR_MODULE_ERR, pckt.tstamp, FRINFO_FROM_UC, context);
|
||||
pckt.mstate = LMS_LINUX_CPU;
|
||||
pckt.nticks = 1;
|
||||
collector_interface->writeDataPacket (prof_hndl, (CM_Packet*) & pckt);
|
||||
POP_REENTRANCE (guard);
|
||||
}
|
1064
gprofng/libcollector/synctrace.c
Normal file
1064
gprofng/libcollector/synctrace.c
Normal file
File diff suppressed because it is too large
Load diff
149
gprofng/libcollector/tsd.c
Normal file
149
gprofng/libcollector/tsd.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/* Copyright (C) 2021 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 <pthread.h>
|
||||
|
||||
#include "collector.h"
|
||||
#include "libcol_util.h"
|
||||
#include "tsd.h"
|
||||
#include "memmgr.h"
|
||||
|
||||
/* TprintfT(<level>,...) definitions. Adjust per module as needed */
|
||||
#define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
|
||||
#define DBG_LT1 1 // for configuration details, warnings
|
||||
#define DBG_LT2 2
|
||||
#define DBG_LT3 3
|
||||
|
||||
/*
|
||||
* Build our thread-specific-data support on pthread interfaces.
|
||||
*/
|
||||
#define MAXNKEYS 64 /* hard-wired? really? well, it depends only on us and we have a sense for how many keys we will use */
|
||||
static pthread_key_t tsd_pkeys[MAXNKEYS];
|
||||
static size_t tsd_sizes[MAXNKEYS];
|
||||
static unsigned tsd_nkeys = 0;
|
||||
|
||||
int
|
||||
__collector_tsd_init ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_tsd_fini ()
|
||||
{
|
||||
Tprintf (DBG_LT1, "tsd_fini()\n");
|
||||
while (tsd_nkeys)
|
||||
{
|
||||
tsd_nkeys--;
|
||||
pthread_key_delete (tsd_pkeys[tsd_nkeys]);
|
||||
tsd_sizes[tsd_nkeys] = 0; // should be unneeded
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
__collector_tsd_allocate ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_tsd_release () { }
|
||||
|
||||
static void
|
||||
tsd_destructor (void *p)
|
||||
{
|
||||
if (p)
|
||||
__collector_freeCSize (__collector_heap, p, *((size_t *) p));
|
||||
}
|
||||
|
||||
unsigned
|
||||
__collector_tsd_create_key (size_t sz, void (*init)(void*), void (*fini)(void*))
|
||||
{
|
||||
/*
|
||||
* We no longer support init and fini arguments (and weren't using them anyhow).
|
||||
* Our hard-wired MAXNKEYS presumably is considerably higher than the number of keys we use.
|
||||
*/
|
||||
if (init || fini || (tsd_nkeys >= MAXNKEYS))
|
||||
return COLLECTOR_TSD_INVALID_KEY;
|
||||
|
||||
/*
|
||||
* A pthread key has a value that is (void *).
|
||||
* We don't know where it is stored, and can access its value only through {get|set}specific.
|
||||
* But libcollector expects a pointer to memory that it can modify.
|
||||
* So we have to allocate that memory and store the pointer.
|
||||
*
|
||||
* For now, we just have to register a destructor that will free the memory
|
||||
* when the thread finishes.
|
||||
*/
|
||||
if (pthread_key_create (&tsd_pkeys[tsd_nkeys], &tsd_destructor))
|
||||
return COLLECTOR_TSD_INVALID_KEY;
|
||||
tsd_sizes[tsd_nkeys] = sz;
|
||||
tsd_nkeys++;
|
||||
return (tsd_nkeys - 1);
|
||||
}
|
||||
|
||||
void *
|
||||
__collector_tsd_get_by_key (unsigned key_index)
|
||||
{
|
||||
if (key_index == COLLECTOR_TSD_INVALID_KEY)
|
||||
return NULL;
|
||||
if (key_index < 0 || key_index >= tsd_nkeys)
|
||||
return NULL;
|
||||
pthread_key_t key = tsd_pkeys[key_index];
|
||||
size_t sz = tsd_sizes[key_index];
|
||||
|
||||
/*
|
||||
* When we use __collector_freeCSize(), we need to know the
|
||||
* size that had been allocated. So, stick a header to the
|
||||
* front of the allocation to hold the size. The header could
|
||||
* just be sizeof(size_t), but pad it to preserve alignment for
|
||||
* the usable area.
|
||||
*/
|
||||
size_t header = 8;
|
||||
void *value = pthread_getspecific (key);
|
||||
|
||||
// check whether we have allocated the memory
|
||||
if (value == NULL)
|
||||
{
|
||||
// add room to record the size
|
||||
value = __collector_allocCSize (__collector_heap, sz + header, 0);
|
||||
if (value == NULL)
|
||||
{
|
||||
// do we need to guard against trying to alloc each time?
|
||||
return NULL;
|
||||
}
|
||||
// write the size of the allocation
|
||||
*((size_t *) value) = sz + header;
|
||||
CALL_UTIL (memset)(((char *) value) + header, 0, sz);
|
||||
|
||||
// record the allocation for future retrieval
|
||||
if (pthread_setspecific (key, value))
|
||||
return NULL;
|
||||
}
|
||||
// return the pointer, skipping the header
|
||||
return ((char *) value) +header;
|
||||
}
|
||||
|
||||
void
|
||||
__collector_tsd_fork_child_cleanup ()
|
||||
{
|
||||
__collector_tsd_fini ();
|
||||
}
|
80
gprofng/libcollector/tsd.h
Normal file
80
gprofng/libcollector/tsd.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/* Thread-specific data */
|
||||
|
||||
#ifndef _TSD_H
|
||||
#define _TSD_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
int __collector_tsd_init ();
|
||||
/* Function: Init tsd module. Call once before using other functions.
|
||||
MT-Level: Unsafe
|
||||
Return: 0 if successful
|
||||
*/
|
||||
|
||||
void __collector_tsd_fini ();
|
||||
/* Function: Shutdown tsd module.
|
||||
MT-Level: Unsafe
|
||||
Return: None
|
||||
*/
|
||||
|
||||
void __collector_tsd_fork_child_cleanup ();
|
||||
/* Function: Reset tsd module. Call immediately after fork() in child process.
|
||||
MT-Level: Unsafe
|
||||
Return: None
|
||||
*/
|
||||
|
||||
int __collector_tsd_allocate ();
|
||||
/* Function: Allocate thread info.
|
||||
Call from threads before using tsd_get_by_key().
|
||||
Call from main thread should be made before calls from other threads.
|
||||
MT-Level: First call is unsafe. Safe afterwards.
|
||||
Return: 0 if successful
|
||||
*/
|
||||
|
||||
void __collector_tsd_release ();
|
||||
/* Function: Free thread info.
|
||||
Call from threads just before thread termination.
|
||||
MT-Level: Safe
|
||||
Return: None
|
||||
*/
|
||||
|
||||
#define COLLECTOR_TSD_INVALID_KEY ((unsigned)-1)
|
||||
unsigned __collector_tsd_create_key (size_t memsize, void (*init)(void*), void (*fini)(void*));
|
||||
/* Function: Reserve TDS memory.
|
||||
MT-Level: Unsafe
|
||||
Inputs: <memsize>: number of bytes to reserve
|
||||
<init>: key memory initialization. Must be callable even if
|
||||
the associated thread has not yet been created.
|
||||
<fini>: key memory finalization. Must be callable even if
|
||||
the associated thread has been terminated.
|
||||
Return: key or COLLECTOR_TSD_INVALID_KEY if not successful.
|
||||
*/
|
||||
|
||||
void *__collector_tsd_get_by_key (unsigned key);
|
||||
/* Function: Get TSD memory.
|
||||
Call from threads after calling tsd_allocate().
|
||||
MT-Level: Safe
|
||||
Inputs: <key>: return value from tsd_create_key()
|
||||
Return: memory if successful, NULL otherwise
|
||||
*/
|
||||
#endif /* _TSD_H */
|
4630
gprofng/libcollector/unwind.c
Normal file
4630
gprofng/libcollector/unwind.c
Normal file
File diff suppressed because it is too large
Load diff
62
gprofng/src/ABS.h
Normal file
62
gprofng/src/ABS.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (C) 2021 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 _ABS_H
|
||||
#define _ABS_H
|
||||
|
||||
/*
|
||||
* Apropos Backtracking Scheme definitions.
|
||||
* Class: com_sun_forte_st_mpmt_timeline_HWCEvent
|
||||
*/
|
||||
|
||||
/* ABS failure codes */
|
||||
typedef enum
|
||||
{
|
||||
ABS_NULL = 0x00, /* undefined/disabled/inactive */
|
||||
ABS_UNSUPPORTED = 0x01, /* inappropriate HWC event type */
|
||||
ABS_BLOCKED = 0x02, /* runtime backtrack blocker reached */
|
||||
ABS_INCOMPLETE = 0x03, /* runtime backtrack limit reached */
|
||||
ABS_REG_LOSS = 0x04, /* address register contaminated */
|
||||
ABS_INVALID_EA = 0x05, /* invalid effective address value */
|
||||
ABS_NO_CTI_INFO = 0x10, /* no AnalyzerInfo for validation */
|
||||
ABS_INFO_FAILED = 0x20, /* info failed to validate backtrack */
|
||||
ABS_CTI_TARGET = 0x30, /* CTI target invalidated backtrack */
|
||||
ABS_CODE_RANGE = 0xFF /* reserved ABS code range in Vaddr */
|
||||
} ABS_code;
|
||||
|
||||
enum {
|
||||
NUM_ABS_RT_CODES = 7,
|
||||
NUM_ABS_PP_CODES = 5
|
||||
};
|
||||
|
||||
extern const char *ABS_RT_CODES[NUM_ABS_RT_CODES];
|
||||
extern char *ABS_PP_CODES[NUM_ABS_PP_CODES];
|
||||
|
||||
/* libcollector will mark HWC overflow values that appear to be invalid */
|
||||
/* dbe should check HWC values for errors */
|
||||
#define HWCVAL_ERR_FLAG (1ULL<<63)
|
||||
#define HWCVAL_SET_ERR(ctr) ((ctr) | HWCVAL_ERR_FLAG)
|
||||
#define HWCVAL_HAS_ERR(ctr) ((ctr) & HWCVAL_ERR_FLAG ? 1 : 0)
|
||||
#define HWCVAL_CLR_ERR(ctr) ((ctr) & ~HWCVAL_ERR_FLAG)
|
||||
|
||||
#define ABS_GET_RT_CODE(EA) ((EA) & 0x0FLL)
|
||||
#define ABS_GET_PP_CODE(EA) (((EA) & 0xF0LL) / 0xF)
|
||||
|
||||
#endif /* _ABS_H */
|
259
gprofng/src/Application.cc
Normal file
259
gprofng/src/Application.cc
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* Copyright (C) 2021 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 <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Settings.h"
|
||||
#include "i18n.h"
|
||||
#include "util.h"
|
||||
|
||||
Application::ProgressFunc Application::progress_func = NULL;
|
||||
Application *theApplication;
|
||||
|
||||
Application::Application (int argc, char *argv[], char *fdhome)
|
||||
{
|
||||
theApplication = this;
|
||||
cur_dir = NULL;
|
||||
prog_version = dbe_strdup (VERSION);
|
||||
set_name (strchr (argv[0], '/') ? argv[0] : NULL);
|
||||
whoami = get_basename (get_name ());
|
||||
|
||||
// set up a queue for comments
|
||||
commentq = new Emsgqueue (NTXT ("app_commentq"));
|
||||
|
||||
// Locate where the binaries are installed
|
||||
set_run_dir (fdhome);
|
||||
|
||||
// Initialize I18N
|
||||
init_locale (run_dir);
|
||||
|
||||
// Initialize licensing data
|
||||
lic_found = 0;
|
||||
lic_err = NULL;
|
||||
|
||||
// Initialize worker threads
|
||||
number_of_worker_threads = 1;
|
||||
#if DEBUG
|
||||
char *use_worker_threads = getenv (NTXT ("SP_USE_WORKER_THREADS"));
|
||||
if ((NULL != use_worker_threads) && (0 == strcasecmp (use_worker_threads, NTXT ("no"))))
|
||||
{
|
||||
number_of_worker_threads = 0;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
settings = new Settings (this);
|
||||
}
|
||||
|
||||
Application::~Application ()
|
||||
{
|
||||
delete commentq;
|
||||
delete settings;
|
||||
free (prog_version);
|
||||
free (cur_dir);
|
||||
free (prog_name);
|
||||
free (run_dir);
|
||||
}
|
||||
|
||||
// Set the name of the application (for messages)
|
||||
void
|
||||
Application::set_name (const char *_name)
|
||||
{
|
||||
prog_name = get_realpath (_name);
|
||||
}
|
||||
|
||||
char *
|
||||
Application::get_realpath (const char *_name)
|
||||
{
|
||||
if (_name == NULL)
|
||||
_name = "/proc/self/exe";
|
||||
char *exe_name = realpath (_name, NULL);
|
||||
if (exe_name)
|
||||
return exe_name;
|
||||
if (strchr (_name, '/') == NULL)
|
||||
{
|
||||
char *path = getenv ("PATH");
|
||||
if (path)
|
||||
for (char *s = path;; s++)
|
||||
if (*s == ':' || *s == 0)
|
||||
{
|
||||
if (path != s)
|
||||
{
|
||||
char *nm = dbe_sprintf (NTXT ("%.*s/%s"), (int) (path - s - 1), path, _name);
|
||||
exe_name = realpath (nm, NULL);
|
||||
free (nm);
|
||||
if (exe_name)
|
||||
return exe_name;
|
||||
}
|
||||
if (*s == 0)
|
||||
break;
|
||||
path = s + 1;
|
||||
}
|
||||
}
|
||||
return strdup (_name);
|
||||
}
|
||||
|
||||
// Set the directory where all binaries are found
|
||||
void
|
||||
Application::set_run_dir (char *fdhome)
|
||||
{
|
||||
run_dir_with_spaces = NULL;
|
||||
if (fdhome)
|
||||
{
|
||||
char *path = dbe_sprintf ("%s/bin", fdhome);
|
||||
struct stat sbuf;
|
||||
if (stat (path, &sbuf) != -1)
|
||||
run_dir = path;
|
||||
else
|
||||
{
|
||||
free (path);
|
||||
run_dir = dbe_strdup (fdhome);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
run_dir = realpath (prog_name, NULL);
|
||||
if (run_dir == NULL)
|
||||
{
|
||||
fprintf (stderr, // I18N won't work here -- not catopen yet.
|
||||
GTXT ("Can't find location of %s\n"), prog_name);
|
||||
run_dir = dbe_strdup (get_cur_dir ());
|
||||
}
|
||||
else
|
||||
{
|
||||
char *d = strrchr (run_dir, '/');
|
||||
if (d)
|
||||
*d = 0;
|
||||
// Check if the installation path contains spaces
|
||||
if (strchr (run_dir, ' ') != NULL)
|
||||
{
|
||||
// Create a symbolic link without spaces
|
||||
const char *dir = NTXT ("/tmp/.gprofngLinks");
|
||||
char *symbolic_link = dbe_create_symlink_to_path (run_dir, dir);
|
||||
if (NULL != symbolic_link)
|
||||
{
|
||||
// Save old path to avoid memory leak
|
||||
run_dir_with_spaces = run_dir;
|
||||
// Use the path through symbolic link
|
||||
run_dir = symbolic_link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
Application::get_cur_dir ()
|
||||
{
|
||||
if (cur_dir == NULL)
|
||||
{
|
||||
char cwd[MAXPATHLEN];
|
||||
if (getcwd (cwd, sizeof (cwd)) == NULL)
|
||||
{
|
||||
perror (prog_name);
|
||||
exit (1);
|
||||
}
|
||||
cur_dir = dbe_strdup (canonical_path (cwd));
|
||||
}
|
||||
return cur_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of worker threads
|
||||
* This is used to decide if it is ok to use worker threads for stat()
|
||||
* and other actions that can hang for a long time
|
||||
* @return number_of_worker_threads
|
||||
*/
|
||||
int
|
||||
Application::get_number_of_worker_threads ()
|
||||
{
|
||||
return number_of_worker_threads;
|
||||
}
|
||||
|
||||
int
|
||||
Application::check_args (int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
// Parsing the command line
|
||||
opterr = 0;
|
||||
while ((opt = getopt (argc, argv, "V")) != EOF)
|
||||
switch (opt)
|
||||
{
|
||||
case 'V':
|
||||
// Ruud
|
||||
Application::print_version_info ();
|
||||
/*
|
||||
printf (NTXT ("GNU %s version %s\n"), get_basename (prog_name), VERSION);
|
||||
*/
|
||||
exit (0);
|
||||
default:
|
||||
usage ();
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
Emsg *
|
||||
Application::fetch_comments ()
|
||||
{
|
||||
if (commentq == NULL)
|
||||
return NULL;
|
||||
return commentq->fetch ();
|
||||
}
|
||||
|
||||
void
|
||||
Application::queue_comment (Emsg *m)
|
||||
{
|
||||
commentq->append (m);
|
||||
}
|
||||
|
||||
void
|
||||
Application::delete_comments ()
|
||||
{
|
||||
if (commentq != NULL)
|
||||
{
|
||||
delete commentq;
|
||||
commentq = new Emsgqueue (NTXT ("app_commentq"));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Application::set_progress (int percentage, const char *proc_str)
|
||||
{
|
||||
if (progress_func != NULL)
|
||||
return progress_func (percentage, proc_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ruud
|
||||
void
|
||||
Application::print_version_info ()
|
||||
{
|
||||
printf ( GTXT (
|
||||
"GNU %s binutils version %s\n"
|
||||
"Copyright (C) 2021 Free Software Foundation, Inc.\n"
|
||||
"License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n"
|
||||
"This is free software: you are free to change and redistribute it.\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\n"),
|
||||
get_basename (prog_name), VERSION);
|
||||
}
|
108
gprofng/src/Application.h
Normal file
108
gprofng/src/Application.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* The Application class is the base class for all C++ executables
|
||||
* in the Performance Tools Suite
|
||||
*
|
||||
* It determines the directory from which the running binary came,
|
||||
* sets up the I18N catalog, the program name, and initializes
|
||||
* an instance of the Settings class to manage all user preferences
|
||||
* and settings. It also manages usage tracking.
|
||||
*
|
||||
* Applications which read experiments are derived from a subclass
|
||||
* named DbeApplication (q.v.)
|
||||
*/
|
||||
|
||||
#ifndef _APPLICATION_H
|
||||
#define _APPLICATION_H
|
||||
|
||||
#include "dbe_types.h"
|
||||
|
||||
class Settings;
|
||||
class Emsg;
|
||||
class Emsgqueue;
|
||||
|
||||
// Application object
|
||||
class Application
|
||||
{
|
||||
public:
|
||||
Application (int argc, char *argv[], char *_run_dir = NULL);
|
||||
virtual ~Application ();
|
||||
void set_name (const char *_name);
|
||||
char *get_cur_dir ();
|
||||
|
||||
// Control the settings of a progress bar, used for GUI applications
|
||||
// this function also detects cancel requests and returns 1
|
||||
// if yes, 0 otherwise
|
||||
static int set_progress (int percentage, const char *proc_str);
|
||||
static char *get_realpath (const char *_name);
|
||||
|
||||
// queue for messages (from reading er.rc files, ...)
|
||||
void queue_comment (Emsg *m); // queue for messages
|
||||
Emsg *fetch_comments (void); // fetch the queue of comment messages
|
||||
void delete_comments (void); // delete the queue of comment messages
|
||||
|
||||
// worker threads (currently used in dbe_stat() for stat() calls)
|
||||
int get_number_of_worker_threads ();
|
||||
|
||||
char *get_version () { return prog_version; }
|
||||
char *get_name () { return prog_name; }
|
||||
char *get_run_dir () { return run_dir; }
|
||||
Emsgqueue *get_comments_queue () { return commentq; };
|
||||
|
||||
protected: // methods
|
||||
void set_run_dir (char *fdhome = NULL);
|
||||
typedef int (*ProgressFunc)(int, const char *);
|
||||
|
||||
// Write a usage message; to be defined in derived class
|
||||
virtual void usage () = 0;
|
||||
|
||||
// Ruud
|
||||
// Write a version message; to be defined in derived class
|
||||
void print_version_info ();
|
||||
|
||||
// Can be overridden in derived class
|
||||
virtual int check_args (int argc, char *argv[]);
|
||||
|
||||
void read_rc ();
|
||||
static void set_progress_func (ProgressFunc func) { progress_func = func; }
|
||||
|
||||
protected:
|
||||
Emsgqueue *commentq;
|
||||
Settings *settings;
|
||||
char *prog_version;
|
||||
char *prog_name;
|
||||
char *whoami;
|
||||
char *run_dir;
|
||||
char *run_dir_with_spaces; // used in case there are spaces
|
||||
char *cur_dir;
|
||||
int lic_found;
|
||||
char *lic_err;
|
||||
|
||||
private:
|
||||
void set_ut_email (int argc, char *argv[]);
|
||||
int number_of_worker_threads;
|
||||
static ProgressFunc progress_func;
|
||||
};
|
||||
|
||||
extern Application *theApplication;
|
||||
|
||||
#endif /* _APPLICATION_H */
|
149
gprofng/src/ArchiveExp.cc
Normal file
149
gprofng/src/ArchiveExp.cc
Normal file
|
@ -0,0 +1,149 @@
|
|||
/* Copyright (C) 2021 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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "DbeSession.h"
|
||||
#include "LoadObject.h"
|
||||
#include "ArchiveExp.h"
|
||||
#include "DbeFile.h"
|
||||
#include "CallStack.h"
|
||||
#include "gp-archive.h"
|
||||
#include "Function.h"
|
||||
#include "Module.h"
|
||||
|
||||
ArchiveExp::ArchiveExp (char *path) : Experiment ()
|
||||
{
|
||||
force_flag = false;
|
||||
copyso_flag = false;
|
||||
use_fndr_archives = true;
|
||||
status = find_expdir (path);
|
||||
if (status == SUCCESS)
|
||||
read_log_file ();
|
||||
}
|
||||
|
||||
ArchiveExp::~ArchiveExp () { }
|
||||
|
||||
void
|
||||
ArchiveExp::read_data (int s_option)
|
||||
{
|
||||
read_archives ();
|
||||
read_map_file ();
|
||||
if (read_java_classes_file () == SUCCESS)
|
||||
{
|
||||
for (int i = 0, sz = loadObjs ? loadObjs->size () : 0; i < sz; i++)
|
||||
{
|
||||
LoadObject *lo = loadObjs->get (i);
|
||||
Dprintf (DEBUG_ARCHIVE, NTXT ("%s:%d loadObjs[%d]=%-25s %s\n"),
|
||||
get_basename (__FILE__), (int) __LINE__, i,
|
||||
STR (lo->get_name ()), STR (lo->get_pathname ()));
|
||||
if ((lo->dbeFile->filetype & DbeFile::F_JAVACLASS) == 0)
|
||||
continue;
|
||||
lo->isUsed = true;
|
||||
if ((s_option & ARCH_EXE_ONLY) != 0)
|
||||
continue;
|
||||
lo->sync_read_stabs ();
|
||||
}
|
||||
}
|
||||
if ((s_option & (ARCH_USED_EXE_ONLY | ARCH_USED_SRC_ONLY)) != 0)
|
||||
{
|
||||
read_frameinfo_file ();
|
||||
resolveFrameInfo = true;
|
||||
Vector<DataDescriptor*> *ddscr = getDataDescriptors ();
|
||||
delete ddscr; // getDataDescriptors() forces reading of experiment data
|
||||
CallStack *callStack = callTree ();
|
||||
if (callStack)
|
||||
{
|
||||
if (DEBUG_ARCHIVE)
|
||||
{
|
||||
Dprintf (DEBUG_ARCHIVE, NTXT ("stacks=%p\n"), callStack);
|
||||
callStack->print (NULL);
|
||||
}
|
||||
for (int n = 0;; n++)
|
||||
{
|
||||
CallStackNode *node = callStack->get_node (n);
|
||||
if (node == NULL)
|
||||
break;
|
||||
do
|
||||
{
|
||||
Histable *h = node->get_instr ();
|
||||
Histable::Type t = h->get_type ();
|
||||
if (t == Histable::INSTR)
|
||||
{
|
||||
DbeInstr *dbeInstr = (DbeInstr *) h;
|
||||
if (!dbeInstr->isUsed)
|
||||
{
|
||||
Function *func = (Function *) dbeInstr->convertto (Histable::FUNCTION);
|
||||
if (!func->isUsed)
|
||||
{
|
||||
func->isUsed = true;
|
||||
func->module->isUsed = true;
|
||||
func->module->loadobject->isUsed = true;
|
||||
}
|
||||
DbeLine *dbeLine = (DbeLine *) dbeInstr->convertto (Histable::LINE);
|
||||
if (dbeLine)
|
||||
dbeLine->sourceFile->isUsed = true;
|
||||
}
|
||||
}
|
||||
else if (t == Histable::LINE)
|
||||
{
|
||||
DbeLine * dbeLine = (DbeLine *) h;
|
||||
dbeLine->sourceFile->isUsed = true;
|
||||
}
|
||||
node = node->ancestor;
|
||||
}
|
||||
while (node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
ArchiveExp::createLinkToFndrArchive (LoadObject *lo, int /* hide_msg */)
|
||||
{
|
||||
// For example, archives of libc.so will be:
|
||||
// <exp>/archives/<libc.so_check_sum>
|
||||
// <exp>/M_r0.er/archives/libc.so_<hash> -> ../../archives/<libc.so_check_sum>
|
||||
if (!create_dir (get_fndr_arch_name ()))
|
||||
{
|
||||
fprintf (stderr, GTXT ("Unable to create directory `%s'\n"), get_fndr_arch_name ());
|
||||
return NULL;
|
||||
}
|
||||
uint32_t checksum = lo->get_checksum ();
|
||||
char *linkName = dbe_sprintf (NTXT ("../../%s/%u"), SP_ARCHIVES_DIR, checksum);
|
||||
char *nm = lo->get_pathname ();
|
||||
char *symLinkName = getNameInArchive (nm, false);
|
||||
if (symlink (linkName, symLinkName) != 0)
|
||||
{
|
||||
fprintf (stderr, GTXT ("Unable to create link `%s' -> `%s'\n"),
|
||||
symLinkName, linkName);
|
||||
free (linkName);
|
||||
free (symLinkName);
|
||||
return NULL;
|
||||
}
|
||||
free (linkName);
|
||||
free (symLinkName);
|
||||
|
||||
// Return a full path inside founder archive:
|
||||
return dbe_sprintf (NTXT ("%s/%u"), get_fndr_arch_name (), checksum);
|
||||
}
|
41
gprofng/src/ArchiveExp.h
Normal file
41
gprofng/src/ArchiveExp.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (C) 2021 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 _ARCHIVE_EXP_H
|
||||
#define _ARCHIVE_EXP_H
|
||||
|
||||
#include "Experiment.h"
|
||||
class LoadObject;
|
||||
|
||||
class ArchiveExp : public Experiment
|
||||
{
|
||||
public:
|
||||
ArchiveExp (char *path);
|
||||
~ArchiveExp ();
|
||||
char *createLinkToFndrArchive (LoadObject *lo, int hide_msg);
|
||||
void read_data (int s_option);
|
||||
|
||||
private:
|
||||
bool force_flag;
|
||||
bool copyso_flag;
|
||||
bool use_fndr_archives;
|
||||
};
|
||||
|
||||
#endif /* _ARCHIVE_EXP_H */
|
975
gprofng/src/BaseMetric.cc
Normal file
975
gprofng/src/BaseMetric.cc
Normal file
|
@ -0,0 +1,975 @@
|
|||
/* Copyright (C) 2021 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 <strings.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "BaseMetric.h"
|
||||
#include "DbeSession.h"
|
||||
#include "Expression.h"
|
||||
|
||||
int BaseMetric::last_id = 0;
|
||||
|
||||
void
|
||||
BaseMetric::init (Type t)
|
||||
{
|
||||
id = last_id++;
|
||||
type = t;
|
||||
aux = NULL;
|
||||
cmd = NULL;
|
||||
username = NULL;
|
||||
hw_ctr = NULL;
|
||||
cond = NULL;
|
||||
val = NULL;
|
||||
expr = NULL;
|
||||
cond_spec = NULL;
|
||||
val_spec = NULL;
|
||||
expr_spec = NULL;
|
||||
legend = NULL;
|
||||
definition = NULL;
|
||||
dependent_bm = NULL;
|
||||
zeroThreshold = 0;
|
||||
clock_unit = (Presentation_clock_unit) 0;
|
||||
for (int ii = 0; ii < NSUBTYPES; ii++)
|
||||
default_visbits[ii] = VAL_NA;
|
||||
valtype = VT_DOUBLE;
|
||||
precision = METRIC_HR_PRECISION;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = VAL_TIMEVAL | VAL_PERCENT;
|
||||
}
|
||||
|
||||
BaseMetric::BaseMetric (Type t)
|
||||
{
|
||||
init (t);
|
||||
switch (t)
|
||||
{
|
||||
case CP_LMS_USER:
|
||||
case CP_LMS_SYSTEM:
|
||||
case CP_LMS_WAIT_CPU:
|
||||
case CP_LMS_USER_LOCK:
|
||||
case CP_LMS_TFAULT:
|
||||
case CP_LMS_DFAULT:
|
||||
case OMP_MASTER_THREAD:
|
||||
case CP_TOTAL:
|
||||
case CP_TOTAL_CPU:
|
||||
case CP_LMS_TRAP:
|
||||
case CP_LMS_KFAULT:
|
||||
case CP_LMS_SLEEP:
|
||||
case CP_LMS_STOPPED:
|
||||
case OMP_NONE:
|
||||
case OMP_OVHD:
|
||||
case OMP_WORK:
|
||||
case OMP_IBAR:
|
||||
case OMP_EBAR:
|
||||
case OMP_WAIT:
|
||||
case OMP_SERL:
|
||||
case OMP_RDUC:
|
||||
case OMP_LKWT:
|
||||
case OMP_CTWT:
|
||||
case OMP_ODWT:
|
||||
case OMP_MSTR:
|
||||
case OMP_SNGL:
|
||||
case OMP_ORDD:
|
||||
case CP_KERNEL_CPU:
|
||||
// all of these are floating point, precision = clock profile tick
|
||||
valtype = VT_DOUBLE;
|
||||
precision = METRIC_SIG_PRECISION;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = VAL_TIMEVAL | VAL_PERCENT;
|
||||
break;
|
||||
case SYNC_WAIT_TIME:
|
||||
case IO_READ_TIME:
|
||||
case IO_WRITE_TIME:
|
||||
case IO_OTHER_TIME:
|
||||
case IO_ERROR_TIME:
|
||||
// all of these are floating point, precision = hrtime tick
|
||||
valtype = VT_DOUBLE;
|
||||
precision = METRIC_HR_PRECISION;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = VAL_TIMEVAL | VAL_PERCENT;
|
||||
break;
|
||||
case SYNC_WAIT_COUNT:
|
||||
case HEAP_ALLOC_CNT:
|
||||
case HEAP_LEAK_CNT:
|
||||
case IO_READ_CNT:
|
||||
case IO_WRITE_CNT:
|
||||
case IO_OTHER_CNT:
|
||||
case IO_ERROR_CNT:
|
||||
valtype = VT_LLONG;
|
||||
precision = 1;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = VAL_VALUE | VAL_PERCENT;
|
||||
break;
|
||||
case RACCESS:
|
||||
case DEADLOCKS:
|
||||
// all of these are integer
|
||||
valtype = VT_LLONG;
|
||||
precision = 1;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = VAL_VALUE | VAL_PERCENT;
|
||||
zeroThreshold = 1;
|
||||
break;
|
||||
case HEAP_ALLOC_BYTES:
|
||||
case HEAP_LEAK_BYTES:
|
||||
case IO_READ_BYTES:
|
||||
case IO_WRITE_BYTES:
|
||||
// all of these are longlong
|
||||
valtype = VT_ULLONG;
|
||||
precision = 1;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = VAL_VALUE | VAL_PERCENT;
|
||||
break;
|
||||
case SIZES:
|
||||
valtype = VT_LLONG;
|
||||
precision = 1;
|
||||
flavors = STATIC;
|
||||
value_styles = VAL_VALUE;
|
||||
break;
|
||||
case ADDRESS:
|
||||
valtype = VT_ADDRESS;
|
||||
precision = 1;
|
||||
flavors = STATIC;
|
||||
value_styles = VAL_VALUE;
|
||||
break;
|
||||
case ONAME:
|
||||
valtype = VT_LABEL;
|
||||
precision = 0;
|
||||
flavors = STATIC;
|
||||
value_styles = VAL_VALUE;
|
||||
break;
|
||||
case HWCNTR: // We should call the other constructor for hwc metric
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
specify ();
|
||||
}
|
||||
|
||||
// Constructor for linked HW counters (base counter)
|
||||
BaseMetric::BaseMetric (Hwcentry *ctr, const char* _aux, const char* _username,
|
||||
int v_styles, BaseMetric* _dependent_bm)
|
||||
{
|
||||
hwc_init (ctr, _aux, _aux, _username, v_styles);
|
||||
dependent_bm = _dependent_bm;
|
||||
}
|
||||
|
||||
// Constructor for linked HW counters (derived counter)
|
||||
|
||||
BaseMetric::BaseMetric (Hwcentry *ctr, const char *_aux, const char *_cmdname,
|
||||
const char *_username, int v_styles)
|
||||
{
|
||||
hwc_init (ctr, _aux, _cmdname, _username, v_styles);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::hwc_init (Hwcentry *ctr, const char* _aux, const char* _cmdname,
|
||||
const char* _username, int v_styles)
|
||||
{
|
||||
init (HWCNTR);
|
||||
aux = dbe_strdup (_aux); // HWC identifier
|
||||
cmd = dbe_strdup (_cmdname); // may differ from _aux for cycles->time hwcs
|
||||
username = dbe_strdup (_username);
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
value_styles = v_styles | VAL_PERCENT;
|
||||
if ((value_styles & (VAL_TIMEVAL | VAL_VALUE)) == VAL_TIMEVAL)
|
||||
valtype = VT_DOUBLE;
|
||||
else
|
||||
valtype = VT_ULLONG;
|
||||
if (ABST_MEMSPACE_ENABLED (ctr->memop))
|
||||
flavors |= DATASPACE; // only for ctrs with memop definitions
|
||||
hw_ctr = ctr;
|
||||
specify ();
|
||||
}
|
||||
|
||||
// Constructor for derived metrics
|
||||
BaseMetric::BaseMetric (const char *_cmd, const char *_username,
|
||||
Definition *def)
|
||||
{
|
||||
init (DERIVED);
|
||||
cmd = dbe_strdup (_cmd);
|
||||
username = dbe_strdup (_username);
|
||||
aux = dbe_strdup (_cmd);
|
||||
definition = def;
|
||||
flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
|
||||
clock_unit = CUNIT_NULL; // should it be CUNIT_TIME or 0 or something?
|
||||
|
||||
/* we're not going to process packets for derived metrics */
|
||||
packet_type = (ProfData_type) (-1);
|
||||
value_styles = VAL_VALUE;
|
||||
valtype = VT_DOUBLE;
|
||||
precision = 1000;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
BaseMetric::BaseMetric (const BaseMetric& m)
|
||||
{
|
||||
id = m.id;
|
||||
type = m.type;
|
||||
aux = dbe_strdup (m.aux);
|
||||
cmd = dbe_strdup (m.cmd);
|
||||
username = dbe_strdup (m.username);
|
||||
flavors = m.flavors;
|
||||
value_styles = m.value_styles;
|
||||
valtype = m.valtype;
|
||||
precision = m.precision;
|
||||
hw_ctr = m.hw_ctr;
|
||||
packet_type = m.packet_type;
|
||||
zeroThreshold = m.zeroThreshold;
|
||||
clock_unit = m.clock_unit;
|
||||
for (int ii = 0; ii < NSUBTYPES; ii++)
|
||||
default_visbits[ii] = m.default_visbits[ii];
|
||||
if (m.cond_spec)
|
||||
{
|
||||
cond_spec = strdup (m.cond_spec);
|
||||
cond = m.cond->copy ();
|
||||
}
|
||||
else
|
||||
{
|
||||
cond = NULL;
|
||||
cond_spec = NULL;
|
||||
}
|
||||
if (m.val_spec)
|
||||
{
|
||||
val_spec = strdup (m.val_spec);
|
||||
val = m.val->copy ();
|
||||
}
|
||||
else
|
||||
{
|
||||
val = NULL;
|
||||
val_spec = NULL;
|
||||
}
|
||||
if (m.expr_spec)
|
||||
{
|
||||
expr_spec = strdup (m.expr_spec);
|
||||
expr = m.expr->copy ();
|
||||
}
|
||||
else
|
||||
{
|
||||
expr = NULL;
|
||||
expr_spec = NULL;
|
||||
}
|
||||
legend = dbe_strdup (m.legend);
|
||||
definition = NULL;
|
||||
if (m.definition)
|
||||
definition = Definition::add_definition (m.definition->def);
|
||||
dependent_bm = m.dependent_bm;
|
||||
}
|
||||
|
||||
BaseMetric::~BaseMetric ()
|
||||
{
|
||||
free (aux);
|
||||
free (cmd);
|
||||
free (cond_spec);
|
||||
free (val_spec);
|
||||
free (expr_spec);
|
||||
free (legend);
|
||||
free (username);
|
||||
delete cond;
|
||||
delete val;
|
||||
delete expr;
|
||||
delete definition;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseMetric::is_internal ()
|
||||
{
|
||||
return (get_value_styles () & VAL_INTERNAL) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
BaseMetric::get_default_visbits (SubType subtype)
|
||||
{
|
||||
int rc = VAL_NA;
|
||||
switch (subtype)
|
||||
{
|
||||
case STATIC:
|
||||
case EXCLUSIVE:
|
||||
rc = default_visbits[0];
|
||||
break;
|
||||
case INCLUSIVE:
|
||||
rc = default_visbits[1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::set_default_visbits (SubType subtype, int _visbits)
|
||||
{
|
||||
switch (subtype)
|
||||
{
|
||||
case STATIC:
|
||||
case EXCLUSIVE:
|
||||
default_visbits[0] = _visbits;
|
||||
break;
|
||||
case INCLUSIVE:
|
||||
default_visbits[1] = _visbits;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::set_cond_spec (char *_cond_spec)
|
||||
{
|
||||
if (cond_spec)
|
||||
{
|
||||
free (cond_spec);
|
||||
delete cond;
|
||||
cond_spec = NULL;
|
||||
cond = NULL;
|
||||
}
|
||||
if (_cond_spec)
|
||||
{
|
||||
cond = dbeSession->ql_parse (_cond_spec);
|
||||
if (cond == NULL)
|
||||
{
|
||||
fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _cond_spec);
|
||||
abort ();
|
||||
}
|
||||
cond_spec = dbe_strdup (_cond_spec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::set_val_spec (char *_val_spec)
|
||||
{
|
||||
if (val_spec)
|
||||
{
|
||||
free (val_spec);
|
||||
delete val;
|
||||
val_spec = NULL;
|
||||
val = NULL;
|
||||
}
|
||||
if (_val_spec)
|
||||
{
|
||||
val = dbeSession->ql_parse (_val_spec);
|
||||
if (val == NULL)
|
||||
{
|
||||
fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _val_spec);
|
||||
abort ();
|
||||
}
|
||||
val_spec = dbe_strdup (_val_spec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::set_expr_spec (char *_expr_spec)
|
||||
{
|
||||
id = last_id++;
|
||||
if (expr_spec)
|
||||
{
|
||||
free (expr_spec);
|
||||
delete expr;
|
||||
expr_spec = NULL;
|
||||
expr = NULL;
|
||||
}
|
||||
if (_expr_spec)
|
||||
{
|
||||
expr = dbeSession->ql_parse (_expr_spec);
|
||||
if (expr == NULL)
|
||||
{
|
||||
fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _expr_spec);
|
||||
return;
|
||||
}
|
||||
expr_spec = dbe_strdup (_expr_spec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::specify_mstate_metric (int st)
|
||||
{
|
||||
char buf[128];
|
||||
snprintf (buf, sizeof (buf), NTXT ("MSTATE==%d"), st);
|
||||
specify_prof_metric (buf);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::specify_ompstate_metric (int st)
|
||||
{
|
||||
char buf[128];
|
||||
snprintf (buf, sizeof (buf), NTXT ("OMPSTATE==%d"), st);
|
||||
specify_prof_metric (buf);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::specify_prof_metric (char *_cond_spec)
|
||||
{
|
||||
packet_type = DATA_CLOCK;
|
||||
specify_metric (_cond_spec, NTXT ("NTICK_USEC")); // microseconds
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::specify_metric (char *_cond_spec, char *_val_spec)
|
||||
{
|
||||
set_cond_spec (_cond_spec);
|
||||
set_val_spec (_val_spec);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetric::specify ()
|
||||
{
|
||||
enum
|
||||
{
|
||||
IDLE_STATE_BITS =
|
||||
(1 << OMP_IDLE_STATE) | (1 << OMP_IBAR_STATE) | (1 << OMP_EBAR_STATE) |
|
||||
(1 << OMP_LKWT_STATE) | (1 << OMP_CTWT_STATE) | (1 << OMP_ODWT_STATE) |
|
||||
(1 << OMP_ATWT_STATE) | (1 << OMP_TSKWT_STATE),
|
||||
LMS_USER_BITS =
|
||||
(1 << OMP_NO_STATE) | (1 << OMP_WORK_STATE) | (1 << OMP_SERL_STATE) |
|
||||
(1 << OMP_RDUC_STATE)
|
||||
};
|
||||
|
||||
char buf[256];
|
||||
char buf2[256];
|
||||
packet_type = (ProfData_type) - 1; // illegal value
|
||||
clock_unit = CUNIT_TIME;
|
||||
switch (type)
|
||||
{
|
||||
case SIZES:
|
||||
username = dbe_strdup (GTXT ("Size"));
|
||||
clock_unit = CUNIT_BYTES;
|
||||
cmd = dbe_strdup (NTXT ("size"));
|
||||
break;
|
||||
case ADDRESS:
|
||||
username = dbe_strdup (GTXT ("PC Address"));
|
||||
cmd = dbe_strdup (NTXT ("address"));
|
||||
break;
|
||||
case ONAME:
|
||||
username = dbe_strdup (GTXT ("Name"));
|
||||
cmd = dbe_strdup (NTXT ("name"));
|
||||
break;
|
||||
case CP_LMS_SYSTEM:
|
||||
username = dbe_strdup (GTXT ("System CPU Time"));
|
||||
specify_mstate_metric (LMS_SYSTEM);
|
||||
cmd = dbe_strdup (NTXT ("system"));
|
||||
break;
|
||||
case CP_TOTAL_CPU:
|
||||
username = dbe_strdup (GTXT ("Total CPU Time"));
|
||||
snprintf (buf, sizeof (buf),
|
||||
"(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)",
|
||||
LMS_USER, LMS_SYSTEM, LMS_TRAP, LMS_LINUX_CPU);
|
||||
specify_prof_metric (buf);
|
||||
cmd = dbe_strdup (NTXT ("totalcpu"));
|
||||
break;
|
||||
case CP_TOTAL:
|
||||
username = dbe_strdup (GTXT ("Total Thread Time"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(MSTATE!=%d)&&(MSTATE!=%d)"),
|
||||
LMS_KERNEL_CPU, LMS_LINUX_CPU);
|
||||
specify_prof_metric (buf);
|
||||
cmd = dbe_strdup (NTXT ("total"));
|
||||
break;
|
||||
case CP_KERNEL_CPU:
|
||||
username = dbe_strdup (GTXT ("Kernel CPU Time"));
|
||||
specify_mstate_metric (LMS_KERNEL_CPU);
|
||||
cmd = dbe_strdup (NTXT ("kcpu"));
|
||||
break;
|
||||
case OMP_MASTER_THREAD:
|
||||
username = dbe_strdup (GTXT ("Master Thread Time"));
|
||||
specify_prof_metric (NTXT ("LWPID==1"));
|
||||
cmd = dbe_strdup (NTXT ("masterthread"));
|
||||
break;
|
||||
case CP_LMS_USER:
|
||||
username = dbe_strdup (GTXT ("User CPU Time"));
|
||||
specify_mstate_metric (LMS_USER);
|
||||
cmd = dbe_strdup (NTXT ("user"));
|
||||
break;
|
||||
case CP_LMS_WAIT_CPU:
|
||||
username = dbe_strdup (GTXT ("Wait CPU Time"));
|
||||
specify_mstate_metric (LMS_WAIT_CPU);
|
||||
cmd = dbe_strdup (NTXT ("wait"));
|
||||
break;
|
||||
case CP_LMS_USER_LOCK:
|
||||
username = dbe_strdup (GTXT ("User Lock Time"));
|
||||
specify_mstate_metric (LMS_USER_LOCK);
|
||||
cmd = dbe_strdup (NTXT ("lock"));
|
||||
break;
|
||||
case CP_LMS_TFAULT:
|
||||
username = dbe_strdup (GTXT ("Text Page Fault Time"));
|
||||
specify_mstate_metric (LMS_TFAULT);
|
||||
cmd = dbe_strdup (NTXT ("textpfault"));
|
||||
break;
|
||||
case CP_LMS_DFAULT:
|
||||
username = dbe_strdup (GTXT ("Data Page Fault Time"));
|
||||
specify_mstate_metric (LMS_DFAULT);
|
||||
cmd = dbe_strdup (NTXT ("datapfault"));
|
||||
break;
|
||||
case CP_LMS_TRAP:
|
||||
username = dbe_strdup (GTXT ("Trap CPU Time"));
|
||||
specify_mstate_metric (LMS_TRAP);
|
||||
cmd = dbe_strdup (NTXT ("trap"));
|
||||
break;
|
||||
case CP_LMS_KFAULT:
|
||||
username = dbe_strdup (GTXT ("Kernel Page Fault Time"));
|
||||
specify_mstate_metric (LMS_KFAULT);
|
||||
cmd = dbe_strdup (NTXT ("kernelpfault"));
|
||||
break;
|
||||
case CP_LMS_SLEEP:
|
||||
username = dbe_strdup (GTXT ("Sleep Time"));
|
||||
specify_mstate_metric (LMS_SLEEP);
|
||||
cmd = dbe_strdup (NTXT ("sleep"));
|
||||
break;
|
||||
case CP_LMS_STOPPED:
|
||||
username = dbe_strdup (GTXT ("Stopped Time"));
|
||||
specify_mstate_metric (LMS_STOPPED);
|
||||
cmd = dbe_strdup (NTXT ("stop"));
|
||||
break;
|
||||
case OMP_OVHD:
|
||||
username = dbe_strdup (GTXT ("OpenMP Overhead Time"));
|
||||
specify_ompstate_metric (OMP_OVHD_STATE);
|
||||
cmd = dbe_strdup (NTXT ("ompovhd"));
|
||||
break;
|
||||
case OMP_WORK:
|
||||
username = dbe_strdup (GTXT ("OpenMP Work Time"));
|
||||
snprintf (buf, sizeof (buf),
|
||||
NTXT ("(OMPSTATE>=0) && (MSTATE==%d) && ((1<<OMPSTATE) & %d)"),
|
||||
LMS_USER, LMS_USER_BITS);
|
||||
specify_prof_metric (buf);
|
||||
cmd = dbe_strdup (NTXT ("ompwork"));
|
||||
break;
|
||||
case OMP_WAIT:
|
||||
username = dbe_strdup (GTXT ("OpenMP Wait Time"));
|
||||
snprintf (buf, sizeof (buf),
|
||||
"OMPSTATE>=0 && ((1<<OMPSTATE) & ((MSTATE!=%d) ? %d : %d))",
|
||||
LMS_USER, (LMS_USER_BITS | IDLE_STATE_BITS), IDLE_STATE_BITS);
|
||||
specify_prof_metric (buf);
|
||||
cmd = dbe_strdup (NTXT ("ompwait"));
|
||||
break;
|
||||
case OMP_IBAR:
|
||||
username = dbe_strdup (GTXT ("OpenMP Implicit Barrier Time"));
|
||||
specify_ompstate_metric (OMP_IBAR_STATE);
|
||||
cmd = dbe_strdup (NTXT ("ompibar"));
|
||||
break;
|
||||
case OMP_EBAR:
|
||||
username = dbe_strdup (GTXT ("OpenMP Explicit Barrier Time"));
|
||||
specify_ompstate_metric (OMP_EBAR_STATE);
|
||||
cmd = dbe_strdup (NTXT ("ompebar"));
|
||||
break;
|
||||
case OMP_SERL:
|
||||
username = dbe_strdup (GTXT ("OpenMP Serial Time"));
|
||||
specify_ompstate_metric (OMP_SERL_STATE);
|
||||
cmd = dbe_strdup (NTXT ("ompserl"));
|
||||
break;
|
||||
case OMP_RDUC:
|
||||
username = dbe_strdup (GTXT ("OpenMP Reduction Time"));
|
||||
specify_ompstate_metric (OMP_RDUC_STATE);
|
||||
cmd = dbe_strdup (NTXT ("omprduc"));
|
||||
break;
|
||||
case OMP_LKWT:
|
||||
username = dbe_strdup (GTXT ("OpenMP Lock Wait Time"));
|
||||
specify_ompstate_metric (OMP_LKWT_STATE);
|
||||
cmd = dbe_strdup (NTXT ("omplkwt"));
|
||||
break;
|
||||
case OMP_CTWT:
|
||||
username = dbe_strdup (GTXT ("OpenMP Critical Section Wait Time"));
|
||||
specify_ompstate_metric (OMP_CTWT_STATE);
|
||||
cmd = dbe_strdup (NTXT ("ompctwt"));
|
||||
break;
|
||||
case OMP_ODWT:
|
||||
username = dbe_strdup (GTXT ("OpenMP Ordered Section Wait Time"));
|
||||
specify_ompstate_metric (OMP_ODWT_STATE);
|
||||
cmd = dbe_strdup (NTXT ("ompodwt"));
|
||||
break;
|
||||
case SYNC_WAIT_TIME:
|
||||
packet_type = DATA_SYNCH;
|
||||
username = dbe_strdup (GTXT ("Sync Wait Time"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(EVT_TIME)/%lld"),
|
||||
(long long) (NANOSEC / METRIC_HR_PRECISION));
|
||||
specify_metric (NULL, buf);
|
||||
cmd = dbe_strdup (NTXT ("sync"));
|
||||
break;
|
||||
case SYNC_WAIT_COUNT:
|
||||
packet_type = DATA_SYNCH;
|
||||
username = dbe_strdup (GTXT ("Sync Wait Count"));
|
||||
specify_metric (NULL, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("syncn"));
|
||||
break;
|
||||
case HEAP_ALLOC_CNT:
|
||||
packet_type = DATA_HEAP;
|
||||
username = dbe_strdup (GTXT ("Allocations"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"),
|
||||
FREE_TRACE, MUNMAP_TRACE);
|
||||
specify_metric (buf, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("heapalloccnt"));
|
||||
break;
|
||||
case HEAP_ALLOC_BYTES:
|
||||
packet_type = DATA_HEAP;
|
||||
username = dbe_strdup (GTXT ("Bytes Allocated"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"),
|
||||
FREE_TRACE, MUNMAP_TRACE);
|
||||
specify_metric (buf, NTXT ("HSIZE"));
|
||||
cmd = dbe_strdup (NTXT ("heapallocbytes"));
|
||||
break;
|
||||
case HEAP_LEAK_CNT:
|
||||
packet_type = DATA_HEAP;
|
||||
username = dbe_strdup (GTXT ("Leaks"));
|
||||
snprintf (buf, sizeof (buf), "(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR&&HLEAKED",
|
||||
FREE_TRACE, MUNMAP_TRACE);
|
||||
specify_metric (buf, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("heapleakcnt"));
|
||||
break;
|
||||
case HEAP_LEAK_BYTES:
|
||||
packet_type = DATA_HEAP;
|
||||
username = dbe_strdup (GTXT ("Bytes Leaked"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"),
|
||||
FREE_TRACE, MUNMAP_TRACE);
|
||||
specify_metric (buf, NTXT ("HLEAKED"));
|
||||
cmd = dbe_strdup (NTXT ("heapleakbytes"));
|
||||
break;
|
||||
|
||||
case IO_READ_CNT:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Read Count"));
|
||||
snprintf (buf, sizeof (buf), "(IOTYPE==%d)", READ_TRACE);
|
||||
specify_metric (buf, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("ioreadcnt"));
|
||||
break;
|
||||
case IO_WRITE_CNT:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Write Count"));
|
||||
snprintf (buf, sizeof (buf), "(IOTYPE==%d)", WRITE_TRACE);
|
||||
specify_metric (buf, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("iowritecnt"));
|
||||
break;
|
||||
case IO_OTHER_CNT:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Other I/O Count"));
|
||||
snprintf (buf, sizeof (buf), "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)",
|
||||
OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE);
|
||||
specify_metric (buf, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("ioothercnt"));
|
||||
break;
|
||||
case IO_ERROR_CNT:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("I/O Error Count"));
|
||||
snprintf (buf, sizeof (buf),
|
||||
"(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)",
|
||||
READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR,
|
||||
CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR);
|
||||
specify_metric (buf, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("ioerrorcnt"));
|
||||
break;
|
||||
case IO_READ_BYTES:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Read Bytes"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&IONBYTE"),
|
||||
READ_TRACE);
|
||||
specify_metric (buf, NTXT ("IONBYTE"));
|
||||
cmd = dbe_strdup (NTXT ("ioreadbytes"));
|
||||
break;
|
||||
case IO_WRITE_BYTES:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Write Bytes"));
|
||||
snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&IONBYTE", WRITE_TRACE);
|
||||
specify_metric (buf, NTXT ("IONBYTE"));
|
||||
cmd = dbe_strdup (NTXT ("iowritebytes"));
|
||||
break;
|
||||
case IO_READ_TIME:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Read Time"));
|
||||
snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&EVT_TIME", READ_TRACE);
|
||||
snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
|
||||
(long long) (NANOSEC / METRIC_HR_PRECISION));
|
||||
specify_metric (buf, buf2);
|
||||
cmd = dbe_strdup (NTXT ("ioreadtime"));
|
||||
break;
|
||||
case IO_WRITE_TIME:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Write Time"));
|
||||
snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&EVT_TIME"),
|
||||
WRITE_TRACE);
|
||||
snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
|
||||
(long long) (NANOSEC / METRIC_HR_PRECISION));
|
||||
specify_metric (buf, buf2);
|
||||
cmd = dbe_strdup (NTXT ("iowritetime"));
|
||||
break;
|
||||
case IO_OTHER_TIME:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("Other I/O Time"));
|
||||
snprintf (buf, sizeof (buf),
|
||||
"(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME",
|
||||
OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE);
|
||||
snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
|
||||
(long long) (NANOSEC / METRIC_HR_PRECISION));
|
||||
specify_metric (buf, buf2);
|
||||
cmd = dbe_strdup (NTXT ("ioothertime"));
|
||||
break;
|
||||
case IO_ERROR_TIME:
|
||||
packet_type = DATA_IOTRACE;
|
||||
username = dbe_strdup (GTXT ("I/O Error Time"));
|
||||
snprintf (buf, sizeof (buf),
|
||||
"(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME",
|
||||
READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR,
|
||||
CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR);
|
||||
snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
|
||||
(long long) (NANOSEC / METRIC_HR_PRECISION));
|
||||
specify_metric (buf, buf2);
|
||||
cmd = dbe_strdup (NTXT ("ioerrortime"));
|
||||
break;
|
||||
case RACCESS:
|
||||
packet_type = DATA_RACE;
|
||||
username = dbe_strdup (GTXT ("Race Accesses"));
|
||||
specify_metric (NULL, NTXT ("RCNT"));
|
||||
cmd = dbe_strdup (NTXT ("raccess"));
|
||||
break;
|
||||
case DEADLOCKS:
|
||||
packet_type = DATA_DLCK;
|
||||
username = dbe_strdup (GTXT ("Deadlocks"));
|
||||
specify_metric (NULL, NTXT ("1"));
|
||||
cmd = dbe_strdup (NTXT ("deadlocks"));
|
||||
break;
|
||||
case HWCNTR:
|
||||
packet_type = DATA_HWC;
|
||||
// username, cmd, and aux set by hwc constructor
|
||||
if (valtype == VT_DOUBLE)
|
||||
{
|
||||
if (hw_ctr->timecvt > 0) // CPU cycles
|
||||
specify_metric (NULL, NTXT ("((HWCINT*1000000)/FREQ_MHZ)"));
|
||||
else if (hw_ctr->timecvt < 0)
|
||||
{ // reference clock (frequency is -timecvt MHz)
|
||||
snprintf (buf, sizeof (buf), NTXT ("((HWCINT*1000000)/%d)"), -hw_ctr->timecvt);
|
||||
specify_metric (NULL, buf);
|
||||
}
|
||||
else // shouldn't happen
|
||||
specify_metric (NULL, NTXT ("0"));
|
||||
// resulting unit: seconds * 1e12
|
||||
precision = 1000000LL * 1000000LL; // Seconds * 1e12
|
||||
}
|
||||
else
|
||||
{
|
||||
specify_metric (NULL, NTXT ("HWCINT"));
|
||||
precision = 1;
|
||||
}
|
||||
break;
|
||||
case OMP_MSTR:
|
||||
case OMP_SNGL:
|
||||
case OMP_ORDD:
|
||||
case OMP_NONE:
|
||||
default:
|
||||
username = dbe_strdup (GTXT ("****"));
|
||||
fprintf (stderr, "BaseMetric::init Undefined basemetric %s\n",
|
||||
get_basetype_name ());
|
||||
}
|
||||
}
|
||||
|
||||
#define CASE_S(x) case x: s = (char *) #x; break
|
||||
char *
|
||||
BaseMetric::get_basetype_name ()
|
||||
{
|
||||
static char buf[128];
|
||||
char *s;
|
||||
switch (type)
|
||||
{
|
||||
CASE_S (CP_LMS_SYSTEM);
|
||||
CASE_S (CP_TOTAL_CPU);
|
||||
CASE_S (CP_TOTAL);
|
||||
CASE_S (OMP_MASTER_THREAD);
|
||||
CASE_S (CP_LMS_USER);
|
||||
CASE_S (CP_LMS_WAIT_CPU);
|
||||
CASE_S (CP_LMS_USER_LOCK);
|
||||
CASE_S (CP_LMS_TFAULT);
|
||||
CASE_S (CP_LMS_DFAULT);
|
||||
CASE_S (CP_LMS_TRAP);
|
||||
CASE_S (CP_LMS_KFAULT);
|
||||
CASE_S (CP_LMS_SLEEP);
|
||||
CASE_S (CP_LMS_STOPPED);
|
||||
CASE_S (OMP_NONE);
|
||||
CASE_S (OMP_OVHD);
|
||||
CASE_S (OMP_WORK);
|
||||
CASE_S (OMP_IBAR);
|
||||
CASE_S (OMP_EBAR);
|
||||
CASE_S (OMP_WAIT);
|
||||
CASE_S (OMP_SERL);
|
||||
CASE_S (OMP_RDUC);
|
||||
CASE_S (OMP_LKWT);
|
||||
CASE_S (OMP_CTWT);
|
||||
CASE_S (OMP_ODWT);
|
||||
CASE_S (OMP_MSTR);
|
||||
CASE_S (OMP_SNGL);
|
||||
CASE_S (OMP_ORDD);
|
||||
CASE_S (CP_KERNEL_CPU);
|
||||
CASE_S (SYNC_WAIT_TIME);
|
||||
CASE_S (IO_READ_TIME);
|
||||
CASE_S (IO_WRITE_TIME);
|
||||
CASE_S (IO_OTHER_TIME);
|
||||
CASE_S (IO_ERROR_TIME);
|
||||
CASE_S (HWCNTR);
|
||||
CASE_S (SYNC_WAIT_COUNT);
|
||||
CASE_S (HEAP_ALLOC_CNT);
|
||||
CASE_S (HEAP_LEAK_CNT);
|
||||
CASE_S (IO_READ_CNT);
|
||||
CASE_S (IO_WRITE_CNT);
|
||||
CASE_S (IO_OTHER_CNT);
|
||||
CASE_S (IO_ERROR_CNT);
|
||||
CASE_S (RACCESS);
|
||||
CASE_S (DEADLOCKS);
|
||||
CASE_S (HEAP_ALLOC_BYTES);
|
||||
CASE_S (HEAP_LEAK_BYTES);
|
||||
CASE_S (IO_READ_BYTES);
|
||||
CASE_S (IO_WRITE_BYTES);
|
||||
CASE_S (SIZES);
|
||||
CASE_S (ADDRESS);
|
||||
CASE_S (ONAME);
|
||||
CASE_S (DERIVED);
|
||||
default:
|
||||
s = NTXT ("???");
|
||||
break;
|
||||
}
|
||||
snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type);
|
||||
buf[sizeof (buf) - 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
BaseMetric::dump ()
|
||||
{
|
||||
int len = 4;
|
||||
char *msg = dbe_sprintf (NTXT ("id=%d %s aux='%s' cmd='%s' user_name='%s' expr_spec='%s'\n"
|
||||
"%*c cond_spec='%s' val_spec='%s'"),
|
||||
id, get_basetype_name (), STR (aux), STR (cmd),
|
||||
STR (username), STR (expr_spec),
|
||||
len, ' ', STR (cond_spec), STR (val_spec));
|
||||
return msg;
|
||||
}
|
||||
|
||||
Histable *
|
||||
BaseMetric::get_comparable_obj (Histable *obj)
|
||||
{
|
||||
if (obj == NULL || expr == NULL)
|
||||
return obj;
|
||||
if (strncmp (expr_spec, NTXT ("EXPGRID=="), 9) == 0)
|
||||
{
|
||||
int n = atoi (expr_spec + 9);
|
||||
Vector<Histable *> *cmpObjs = obj->get_comparable_objs ();
|
||||
if (cmpObjs && cmpObjs->size () >= n)
|
||||
return cmpObjs->get (n - 1);
|
||||
return NULL;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
Definition::Definition (opType _op)
|
||||
{
|
||||
op = _op;
|
||||
bm = NULL;
|
||||
arg1 = NULL;
|
||||
arg2 = NULL;
|
||||
def = NULL;
|
||||
dependencies = NULL;
|
||||
map = NULL;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
Definition::~Definition ()
|
||||
{
|
||||
delete arg1;
|
||||
delete arg2;
|
||||
delete dependencies;
|
||||
delete[] map;
|
||||
}
|
||||
|
||||
Vector<BaseMetric *> *
|
||||
Definition::get_dependencies ()
|
||||
{
|
||||
if (dependencies == NULL)
|
||||
{
|
||||
if (arg1 && arg1->bm && arg2 && arg2->bm)
|
||||
{
|
||||
dependencies = new Vector<BaseMetric *>(2);
|
||||
arg1->index = dependencies->size ();
|
||||
dependencies->append (arg1->bm);
|
||||
arg2->index = dependencies->size ();
|
||||
dependencies->append (arg2->bm);
|
||||
map = new long[2];
|
||||
}
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
long *
|
||||
Definition::get_map ()
|
||||
{
|
||||
get_dependencies ();
|
||||
return map;
|
||||
}
|
||||
|
||||
Definition *
|
||||
Definition::add_definition (char *_def)
|
||||
{
|
||||
// parse the definition
|
||||
char *op_ptr = strchr (_def, '/');
|
||||
if (op_ptr == NULL)
|
||||
{
|
||||
// it's a primitive metric
|
||||
BaseMetric *bm = dbeSession->find_base_reg_metric (_def);
|
||||
if (bm)
|
||||
{
|
||||
Definition *p = new Definition (opPrimitive);
|
||||
p->bm = bm;
|
||||
return p;
|
||||
}
|
||||
return NULL; // BaseMetric is not yet specified
|
||||
}
|
||||
Definition *p2 = add_definition (op_ptr + 1);
|
||||
if (p2 == NULL)
|
||||
return NULL;
|
||||
_def = dbe_strdup (_def);
|
||||
op_ptr = strchr (_def, '/');
|
||||
*op_ptr = 0;
|
||||
Definition *p1 = add_definition (_def);
|
||||
if (p1)
|
||||
{
|
||||
*op_ptr = '/';
|
||||
Definition *p = new Definition (opDivide);
|
||||
p->arg1 = p1;
|
||||
p->arg2 = p2;
|
||||
p->def = _def;
|
||||
return p;
|
||||
}
|
||||
free (_def);
|
||||
delete p1;
|
||||
delete p2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double
|
||||
Definition::eval (long *indexes, TValue *values)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case opPrimitive:
|
||||
return values[indexes[index]].to_double ();
|
||||
case opDivide:
|
||||
{
|
||||
double x2 = arg2->eval (indexes, values);
|
||||
if (x2 == 0)
|
||||
return 0.;
|
||||
double x1 = arg1->eval (indexes, values);
|
||||
return x1 / x2;
|
||||
}
|
||||
default:
|
||||
fprintf (stderr, GTXT ("unknown expression\n"));
|
||||
return 0.;
|
||||
}
|
||||
}
|
246
gprofng/src/BaseMetric.h
Normal file
246
gprofng/src/BaseMetric.h
Normal file
|
@ -0,0 +1,246 @@
|
|||
/* Copyright (C) 2021 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 _BASEMETRIC_H
|
||||
#define _BASEMETRIC_H
|
||||
|
||||
#include "dbe_structs.h"
|
||||
#include "hwcentry.h"
|
||||
#include "Table.h"
|
||||
|
||||
// METRIC_*_PRECISION determine the least threshold value
|
||||
// for time measured metrics. Any event that counts for less
|
||||
// than 1sec/METRIC_PRECISION is discarded.
|
||||
#define METRIC_SIG_PRECISION MICROSEC
|
||||
#define METRIC_HR_PRECISION MICROSEC
|
||||
|
||||
class Expression;
|
||||
class Definition;
|
||||
class Histable;
|
||||
template <class ITEM> class Vector;
|
||||
|
||||
class BaseMetric
|
||||
{
|
||||
public:
|
||||
// sync enum changes with AnMetric.java
|
||||
enum Type
|
||||
{ // Subtype==STATIC metrics:
|
||||
ONAME = 1, //ONAME must be 1
|
||||
SIZES,
|
||||
ADDRESS,
|
||||
// Clock Profiling, Derived Metrics:
|
||||
CP_TOTAL,
|
||||
CP_TOTAL_CPU,
|
||||
// Clock profiling, Solaris Microstates (LMS_* defines)
|
||||
CP_LMS_USER,
|
||||
CP_LMS_SYSTEM,
|
||||
CP_LMS_TRAP,
|
||||
CP_LMS_TFAULT,
|
||||
CP_LMS_DFAULT,
|
||||
CP_LMS_KFAULT,
|
||||
CP_LMS_USER_LOCK,
|
||||
CP_LMS_SLEEP,
|
||||
CP_LMS_WAIT_CPU,
|
||||
CP_LMS_STOPPED,
|
||||
// Kernel clock profiling
|
||||
CP_KERNEL_CPU,
|
||||
// Sync Tracing
|
||||
SYNC_WAIT_TIME,
|
||||
SYNC_WAIT_COUNT,
|
||||
// HWC
|
||||
HWCNTR,
|
||||
// Heap Tracing:
|
||||
HEAP_ALLOC_CNT,
|
||||
HEAP_ALLOC_BYTES,
|
||||
HEAP_LEAK_CNT,
|
||||
HEAP_LEAK_BYTES,
|
||||
// I/O Tracing:
|
||||
IO_READ_BYTES,
|
||||
IO_READ_CNT,
|
||||
IO_READ_TIME,
|
||||
IO_WRITE_BYTES,
|
||||
IO_WRITE_CNT,
|
||||
IO_WRITE_TIME,
|
||||
IO_OTHER_CNT,
|
||||
IO_OTHER_TIME,
|
||||
IO_ERROR_CNT,
|
||||
IO_ERROR_TIME,
|
||||
// MPI Tracing:
|
||||
MPI_TIME,
|
||||
MPI_SEND,
|
||||
MPI_BYTES_SENT,
|
||||
MPI_RCV,
|
||||
MPI_BYTES_RCVD,
|
||||
MPI_OTHER,
|
||||
// OMP states:
|
||||
OMP_NONE,
|
||||
OMP_OVHD,
|
||||
OMP_WORK,
|
||||
OMP_IBAR,
|
||||
OMP_EBAR,
|
||||
OMP_WAIT,
|
||||
OMP_SERL,
|
||||
OMP_RDUC,
|
||||
OMP_LKWT,
|
||||
OMP_CTWT,
|
||||
OMP_ODWT,
|
||||
OMP_MSTR,
|
||||
OMP_SNGL,
|
||||
OMP_ORDD,
|
||||
OMP_MASTER_THREAD,
|
||||
// MPI states:
|
||||
MPI_WORK,
|
||||
MPI_WAIT,
|
||||
// Races and Deadlocks
|
||||
RACCESS,
|
||||
DEADLOCKS,
|
||||
// Derived Metrics
|
||||
DERIVED
|
||||
};
|
||||
|
||||
// sync enum changes with AnMetric.java
|
||||
enum SubType
|
||||
{
|
||||
STATIC = 1, // Type==SIZES, ADDRESS, ONAME
|
||||
EXCLUSIVE = 2,
|
||||
INCLUSIVE = 4,
|
||||
ATTRIBUTED = 8,
|
||||
DATASPACE = 16 // Can be accessed in dataspace views
|
||||
};
|
||||
|
||||
BaseMetric (Type t);
|
||||
BaseMetric (Hwcentry *ctr, const char* _aux, const char* _cmdname,
|
||||
const char* _username, int v_styles); // depended bm
|
||||
BaseMetric (Hwcentry *ctr, const char* _aux, const char* _username,
|
||||
int v_styles, BaseMetric* _depended_bm = NULL); // master bm
|
||||
BaseMetric (const char *_cmd, const char *_username, Definition *def); // derived metrics
|
||||
BaseMetric (const BaseMetric& m);
|
||||
virtual ~BaseMetric ();
|
||||
|
||||
int get_id () { return id; }
|
||||
Type get_type () { return type; }
|
||||
Hwcentry *get_hw_ctr () { return hw_ctr; }
|
||||
char *get_aux () { return aux; }
|
||||
char *get_username () { return username; }
|
||||
char *get_cmd () { return cmd; }
|
||||
int get_flavors () { return flavors; }
|
||||
int get_clock_unit () { return clock_unit; }
|
||||
long long get_precision () { return precision; }
|
||||
ValueTag get_vtype () { return valtype; }
|
||||
int get_value_styles () { return value_styles; }
|
||||
bool is_zeroThreshold () { return zeroThreshold; }
|
||||
ProfData_type get_packet_type () { return packet_type; }
|
||||
Expression *get_cond () { return cond; }
|
||||
Expression *get_val () { return val; }
|
||||
Expression *get_expr () { return expr; }
|
||||
char *get_expr_spec () { return expr_spec; }
|
||||
Definition *get_definition () { return definition; };
|
||||
BaseMetric *get_dependent_bm () { return dependent_bm; };
|
||||
|
||||
bool
|
||||
comparable ()
|
||||
{
|
||||
return val_spec != NULL || type == DERIVED || type == SIZES || type == ADDRESS;
|
||||
}
|
||||
|
||||
// setters..
|
||||
void set_default_visbits (SubType subtype, int _visbits);
|
||||
void set_id (int _id) { id = _id; } //TBR, if possible
|
||||
// For comparison, set which packets to eval:
|
||||
void set_expr_spec (char *_expr_spec);
|
||||
void set_cond_spec (char *_cond_spec);
|
||||
int get_default_visbits (SubType subtype);
|
||||
char *dump ();
|
||||
Histable *get_comparable_obj (Histable *obj);
|
||||
bool is_internal (); // Invisible for users
|
||||
|
||||
char *legend; // for comparison: add'l column text
|
||||
|
||||
private:
|
||||
BaseMetric *dependent_bm; // for HWCs only: a link to the timecvt metric
|
||||
Expression *cond; // determines which packets to evaluate
|
||||
char *cond_spec; // used to generate "cond"
|
||||
Expression *val; // determines the numeric value for packet
|
||||
char *val_spec; // used to generate "val"
|
||||
Expression *expr; // for comparison: an additional expression to determine
|
||||
// which packets to eval. Should be NULL otherwise.
|
||||
char *expr_spec; // used to generate "expr"
|
||||
int id; // unique id (assigned to last_id @ "new")
|
||||
Type type; // e.g. HWCNTR
|
||||
char *aux; // for HWCs only: Hwcentry ctr->name
|
||||
char *cmd; // the .rc metric command, e.g. "total"
|
||||
char *username; // e.g. "GTXT("Total Wait Time")"
|
||||
int flavors; // bitmask of SubType capabilities
|
||||
int value_styles; // bitmask of ValueType capabilities
|
||||
static const int NSUBTYPES = 2; // STATIC/EXCLUSIVE, INCLUSIVE
|
||||
int default_visbits[NSUBTYPES]; // ValueType, e.g. VAL_VALUE|VAL_TIMEVAL
|
||||
ValueTag valtype; // e.g. VT_LLONG
|
||||
long long precision; // e.g. METRIC_SIG_PRECISION, 1, etc.
|
||||
Hwcentry *hw_ctr; // HWC definition
|
||||
ProfData_type packet_type; // e.g. DATA_HWC, or -1 for N/A
|
||||
bool zeroThreshold; // deadlock stuff
|
||||
Presentation_clock_unit clock_unit;
|
||||
|
||||
static int last_id; // incremented by 1 w/ every "new". Not MT-safe
|
||||
Definition *definition;
|
||||
|
||||
void hwc_init (Hwcentry *ctr, const char* _aux, const char* _cmdname, const char* _username, int v_styles);
|
||||
void init (Type t);
|
||||
char *get_basetype_name ();
|
||||
void specify ();
|
||||
void specify_metric (char *_cond_spec, char *_val_spec);
|
||||
void set_val_spec (char *_val_spec);
|
||||
void specify_mstate_metric (int st);
|
||||
void specify_ompstate_metric (int st);
|
||||
void specify_prof_metric (char *_cond_spec);
|
||||
};
|
||||
|
||||
class Definition
|
||||
{
|
||||
public:
|
||||
|
||||
enum opType
|
||||
{
|
||||
opNULL,
|
||||
opPrimitive,
|
||||
opDivide
|
||||
};
|
||||
|
||||
Definition (opType _op);
|
||||
~Definition ();
|
||||
static Definition *add_definition (char *_def);
|
||||
Vector<BaseMetric *> *get_dependencies ();
|
||||
long *get_map ();
|
||||
double eval (long *indexes, TValue *values);
|
||||
|
||||
opType op;
|
||||
Definition *arg1;
|
||||
Definition *arg2;
|
||||
char *def;
|
||||
|
||||
private:
|
||||
BaseMetric *bm;
|
||||
long *map;
|
||||
Vector<BaseMetric *> *dependencies;
|
||||
long index;
|
||||
};
|
||||
|
||||
#endif /* _BASEMETRIC_H */
|
||||
|
329
gprofng/src/BaseMetricTreeNode.cc
Normal file
329
gprofng/src/BaseMetricTreeNode.cc
Normal file
|
@ -0,0 +1,329 @@
|
|||
/* Copyright (C) 2021 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 <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "hwcentry.h"
|
||||
#include "DbeSession.h"
|
||||
#include "Experiment.h"
|
||||
#include "Expression.h"
|
||||
#include "Metric.h"
|
||||
#include "Table.h"
|
||||
#include "i18n.h"
|
||||
#include "debug.h"
|
||||
|
||||
BaseMetricTreeNode::BaseMetricTreeNode ()
|
||||
{
|
||||
init_vars ();
|
||||
build_basic_tree ();
|
||||
}
|
||||
|
||||
BaseMetricTreeNode::BaseMetricTreeNode (BaseMetric *item)
|
||||
{
|
||||
init_vars ();
|
||||
bm = item;
|
||||
name = dbe_strdup (bm->get_cmd ());
|
||||
uname = dbe_strdup (bm->get_username ());
|
||||
unit = NULL; //YXXX populate from base_metric (requires updating base_metric)
|
||||
unit_uname = NULL;
|
||||
}
|
||||
|
||||
BaseMetricTreeNode::BaseMetricTreeNode (const char *_name, const char *_uname,
|
||||
const char *_unit, const char *_unit_uname)
|
||||
{
|
||||
init_vars ();
|
||||
name = dbe_strdup (_name);
|
||||
uname = dbe_strdup (_uname);
|
||||
unit = dbe_strdup (_unit);
|
||||
unit_uname = dbe_strdup (_unit_uname);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetricTreeNode::init_vars ()
|
||||
{
|
||||
name = NULL;
|
||||
uname = NULL;
|
||||
unit = NULL;
|
||||
unit_uname = NULL;
|
||||
root = this;
|
||||
parent = NULL;
|
||||
children = new Vector<BaseMetricTreeNode*>;
|
||||
isCompositeMetric = false;
|
||||
bm = NULL;
|
||||
registered = false;
|
||||
num_registered_descendents = 0;
|
||||
}
|
||||
|
||||
BaseMetricTreeNode::~BaseMetricTreeNode ()
|
||||
{
|
||||
children->destroy ();
|
||||
delete children;
|
||||
free (name);
|
||||
free (uname);
|
||||
free (unit);
|
||||
free (unit_uname);
|
||||
}
|
||||
|
||||
BaseMetricTreeNode *
|
||||
BaseMetricTreeNode::register_metric (BaseMetric *item)
|
||||
{
|
||||
BaseMetricTreeNode *found = root->find (item->get_cmd ());
|
||||
if (!found)
|
||||
{
|
||||
switch (item->get_type ())
|
||||
{
|
||||
case BaseMetric::CP_TOTAL:
|
||||
found = root->find (L_CP_TOTAL);
|
||||
break;
|
||||
case BaseMetric::CP_TOTAL_CPU:
|
||||
found = root->find (L_CP_TOTAL_CPU);
|
||||
break;
|
||||
}
|
||||
if (found && found->bm == NULL)
|
||||
found->bm = item;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
switch (item->get_type ())
|
||||
{
|
||||
case BaseMetric::HEAP_ALLOC_BYTES:
|
||||
case BaseMetric::HEAP_ALLOC_CNT:
|
||||
case BaseMetric::HEAP_LEAK_BYTES:
|
||||
case BaseMetric::HEAP_LEAK_CNT:
|
||||
found = root->find (get_prof_data_type_name (DATA_HEAP));
|
||||
break;
|
||||
case BaseMetric::CP_KERNEL_CPU:
|
||||
case BaseMetric::CP_TOTAL:
|
||||
found = root->find (get_prof_data_type_name (DATA_CLOCK));
|
||||
break;
|
||||
case BaseMetric::CP_LMS_DFAULT:
|
||||
case BaseMetric::CP_LMS_TFAULT:
|
||||
case BaseMetric::CP_LMS_KFAULT:
|
||||
case BaseMetric::CP_LMS_STOPPED:
|
||||
case BaseMetric::CP_LMS_WAIT_CPU:
|
||||
case BaseMetric::CP_LMS_SLEEP:
|
||||
case BaseMetric::CP_LMS_USER_LOCK:
|
||||
case BaseMetric::CP_TOTAL_CPU:
|
||||
found = root->find (L_CP_TOTAL);
|
||||
break;
|
||||
case BaseMetric::CP_LMS_USER:
|
||||
case BaseMetric::CP_LMS_SYSTEM:
|
||||
case BaseMetric::CP_LMS_TRAP:
|
||||
found = root->find (L_CP_TOTAL_CPU);
|
||||
break;
|
||||
case BaseMetric::HWCNTR:
|
||||
found = root->find ((item->get_flavors () & BaseMetric::DATASPACE) != 0 ?
|
||||
L2_HWC_DSPACE : L2_HWC_GENERAL);
|
||||
break;
|
||||
case BaseMetric::SYNC_WAIT_TIME:
|
||||
case BaseMetric::SYNC_WAIT_COUNT:
|
||||
found = root->find (get_prof_data_type_name (DATA_SYNCH));
|
||||
break;
|
||||
case BaseMetric::OMP_WORK:
|
||||
case BaseMetric::OMP_WAIT:
|
||||
case BaseMetric::OMP_OVHD:
|
||||
found = root->find (get_prof_data_type_name (DATA_OMP));
|
||||
break;
|
||||
case BaseMetric::IO_READ_TIME:
|
||||
case BaseMetric::IO_READ_BYTES:
|
||||
case BaseMetric::IO_READ_CNT:
|
||||
case BaseMetric::IO_WRITE_TIME:
|
||||
case BaseMetric::IO_WRITE_BYTES:
|
||||
case BaseMetric::IO_WRITE_CNT:
|
||||
case BaseMetric::IO_OTHER_TIME:
|
||||
case BaseMetric::IO_OTHER_CNT:
|
||||
case BaseMetric::IO_ERROR_TIME:
|
||||
case BaseMetric::IO_ERROR_CNT:
|
||||
found = root->find (get_prof_data_type_name (DATA_IOTRACE));
|
||||
break;
|
||||
case BaseMetric::ONAME:
|
||||
case BaseMetric::SIZES:
|
||||
case BaseMetric::ADDRESS:
|
||||
found = root->find (L1_STATIC);
|
||||
break;
|
||||
default:
|
||||
found = root->find (L1_OTHER);
|
||||
break;
|
||||
}
|
||||
assert (found != NULL);
|
||||
switch (item->get_type ())
|
||||
{
|
||||
case BaseMetric::CP_TOTAL:
|
||||
case BaseMetric::CP_TOTAL_CPU:
|
||||
found->isCompositeMetric = true;
|
||||
break;
|
||||
}
|
||||
found = found->add_child (item);
|
||||
}
|
||||
register_node (found);
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetricTreeNode::register_node (BaseMetricTreeNode *node)
|
||||
{
|
||||
if (!node->registered)
|
||||
{
|
||||
node->registered = true;
|
||||
BaseMetricTreeNode *tmp = node->parent;
|
||||
while (tmp)
|
||||
{
|
||||
tmp->num_registered_descendents++;
|
||||
tmp = tmp->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseMetricTreeNode *
|
||||
BaseMetricTreeNode::find (const char *_name)
|
||||
{
|
||||
BaseMetricTreeNode *found = NULL;
|
||||
if (dbe_strcmp (get_name (), _name) == 0)
|
||||
return this;
|
||||
if (bm && dbe_strcmp (bm->get_cmd (), _name) == 0)
|
||||
return this;
|
||||
BaseMetricTreeNode *child;
|
||||
int index;
|
||||
|
||||
Vec_loop (BaseMetricTreeNode*, children, index, child)
|
||||
{
|
||||
found = child->find (_name);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
int_get_registered_descendents (BaseMetricTreeNode* curr,
|
||||
Vector<BaseMetricTreeNode*> *dest, bool nearest_only)
|
||||
{
|
||||
if (!curr)
|
||||
return;
|
||||
if (curr->is_registered ())
|
||||
{
|
||||
dest->append (curr);
|
||||
if (nearest_only)
|
||||
return; // soon as we hit a live node, stop following branch
|
||||
}
|
||||
int index;
|
||||
BaseMetricTreeNode *child;
|
||||
|
||||
Vec_loop (BaseMetricTreeNode*, curr->get_children (), index, child)
|
||||
{
|
||||
int_get_registered_descendents (child, dest, nearest_only);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetricTreeNode::get_nearest_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
|
||||
{
|
||||
if (!dest || dest->size () != 0)
|
||||
abort ();
|
||||
bool nearest_only = true;
|
||||
int_get_registered_descendents (this, dest, nearest_only);
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetricTreeNode::get_all_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
|
||||
{
|
||||
if (!dest || dest->size () != 0)
|
||||
abort ();
|
||||
bool nearest_only = false;
|
||||
int_get_registered_descendents (this, dest, nearest_only);
|
||||
}
|
||||
|
||||
char *
|
||||
BaseMetricTreeNode::get_description ()
|
||||
{
|
||||
if (bm)
|
||||
{
|
||||
Hwcentry* hw_ctr = bm->get_hw_ctr ();
|
||||
if (hw_ctr)
|
||||
return hw_ctr->short_desc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
BaseMetricTreeNode::build_basic_tree ()
|
||||
{
|
||||
#define TREE_INSERT_DATA_TYPE(t) add_child(get_prof_data_type_name (t), get_prof_data_type_uname (t))
|
||||
BaseMetricTreeNode *level1, *level2;
|
||||
// register L1_DURATION here because it has a value but is not a true metric
|
||||
register_node (add_child (L1_DURATION, L1_DURATION_UNAME, UNIT_SECONDS,
|
||||
UNIT_SECONDS_UNAME));
|
||||
register_node (add_child (L1_GCDURATION, L1_GCDURATION_UNAME, UNIT_SECONDS,
|
||||
UNIT_SECONDS_UNAME));
|
||||
TREE_INSERT_DATA_TYPE (DATA_HEAP);
|
||||
level1 = TREE_INSERT_DATA_TYPE (DATA_CLOCK);
|
||||
level1 = level1->add_child (L_CP_TOTAL, GTXT ("XXX Total Thread Time"));
|
||||
level1->isCompositeMetric = true;
|
||||
level2 = level1->add_child (L_CP_TOTAL_CPU, GTXT ("XXX Total CPU Time"));
|
||||
level2->isCompositeMetric = true;
|
||||
|
||||
add_child (L1_OTHER, L1_OTHER_UNAME);
|
||||
level1 = TREE_INSERT_DATA_TYPE (DATA_HWC);
|
||||
level1->add_child (L2_HWC_DSPACE, L2_HWC_DSPACE_UNAME);
|
||||
level1->add_child (L2_HWC_GENERAL, L2_HWC_GENERAL_UNAME);
|
||||
TREE_INSERT_DATA_TYPE (DATA_SYNCH);
|
||||
TREE_INSERT_DATA_TYPE (DATA_OMP);
|
||||
TREE_INSERT_DATA_TYPE (DATA_IOTRACE);
|
||||
add_child (L1_STATIC, L1_STATIC_UNAME);
|
||||
}
|
||||
|
||||
BaseMetricTreeNode *
|
||||
BaseMetricTreeNode::add_child (BaseMetric *item)
|
||||
{
|
||||
return add_child (new BaseMetricTreeNode (item));
|
||||
}
|
||||
|
||||
BaseMetricTreeNode *
|
||||
BaseMetricTreeNode::add_child (const char * _name, const char *_uname,
|
||||
const char * _unit, const char * _unit_uname)
|
||||
{
|
||||
return add_child (new BaseMetricTreeNode (_name, _uname, _unit, _unit_uname));
|
||||
}
|
||||
|
||||
BaseMetricTreeNode *
|
||||
BaseMetricTreeNode::add_child (BaseMetricTreeNode *new_node)
|
||||
{
|
||||
new_node->parent = this;
|
||||
new_node->root = root;
|
||||
children->append (new_node);
|
||||
return new_node;
|
||||
}
|
||||
|
||||
char *
|
||||
BaseMetricTreeNode::dump ()
|
||||
{
|
||||
int len = 4;
|
||||
char *s = bm ? bm->dump () : dbe_strdup ("<no base metric>");
|
||||
char *msg = dbe_sprintf ("%s\n%*c %*c unit='%s' unit_uname='%s' uname='%s' name='%s'\n",
|
||||
STR (s), len, ' ', len, ' ',
|
||||
STR (get_unit_uname ()), STR (get_unit ()),
|
||||
STR (get_user_name ()), STR (get_name ()));
|
||||
free (s);
|
||||
return msg;
|
||||
}
|
100
gprofng/src/BaseMetricTreeNode.h
Normal file
100
gprofng/src/BaseMetricTreeNode.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* Copyright (C) 2021 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 _BASEMETRICTREENODE_H
|
||||
#define _BASEMETRICTREENODE_H
|
||||
|
||||
#include "BaseMetric.h"
|
||||
|
||||
// Unit values
|
||||
#define UNIT_SECONDS "SECONDS"
|
||||
#define UNIT_SECONDS_UNAME GTXT("secs.")
|
||||
#define UNIT_BYTES "BYTES"
|
||||
#define UNIT_BYTES_UNAME GTXT("bytes")
|
||||
|
||||
// Name values for intermediate parent nodes that aren't defined elsewhere
|
||||
#define L1_DURATION "PROFDATA_TYPE_DURATION"
|
||||
#define L1_DURATION_UNAME GTXT("Experiment Duration")
|
||||
#define L1_GCDURATION "PROFDATA_TYPE_GCDURATION"
|
||||
#define L1_GCDURATION_UNAME GTXT("Java Garbage Collection Duration")
|
||||
#define L2_HWC_DSPACE "PROFDATA_TYPE_HWC_DSPACE"
|
||||
#define L2_HWC_DSPACE_UNAME GTXT("Memoryspace Hardware Counters")
|
||||
#define L2_HWC_GENERAL "PROFDATA_TYPE_HWC_GENERAL"
|
||||
#define L2_HWC_GENERAL_UNAME GTXT("General Hardware Counters")
|
||||
#define L1_MPI_STATES "PROFDATA_TYPE_MPI_STATES"
|
||||
#define L1_MPI_STATES_UNAME GTXT("MPI States")
|
||||
#define L1_OTHER "PROFDATA_TYPE_OTHER"
|
||||
#define L1_OTHER_UNAME GTXT("Derived and Other Metrics")
|
||||
#define L1_STATIC "PROFDATA_TYPE_STATIC"
|
||||
#define L1_STATIC_UNAME GTXT("Static")
|
||||
#define L_CP_TOTAL "L_CP_TOTAL"
|
||||
#define L_CP_TOTAL_CPU "L_CP_TOTAL_CPU"
|
||||
|
||||
class BaseMetricTreeNode
|
||||
{
|
||||
public:
|
||||
BaseMetricTreeNode (); // builds basic metric tree (not including HWCs)
|
||||
virtual ~BaseMetricTreeNode ();
|
||||
BaseMetricTreeNode *register_metric (BaseMetric *item);
|
||||
BaseMetricTreeNode *find (const char *name);
|
||||
void get_nearest_registered_descendents (Vector<BaseMetricTreeNode*> *new_vec);
|
||||
void get_all_registered_descendents (Vector<BaseMetricTreeNode*> *new_vec);
|
||||
char *get_description();
|
||||
char *dump();
|
||||
|
||||
BaseMetricTreeNode *get_root () { return root; }
|
||||
BaseMetricTreeNode *get_parent () { return parent; }
|
||||
Vector<BaseMetricTreeNode*> *get_children () { return children; }
|
||||
bool is_registered () { return registered; }
|
||||
int get_num_registered_descendents () { return num_registered_descendents; }
|
||||
bool is_composite_metric () { return isCompositeMetric; }
|
||||
BaseMetric *get_BaseMetric () { return bm; }
|
||||
char *get_name () { return name; }
|
||||
char *get_user_name () { return uname; }
|
||||
char *get_unit () { return unit; }
|
||||
char *get_unit_uname () { return unit_uname; }
|
||||
|
||||
private:
|
||||
BaseMetricTreeNode (BaseMetric *item);
|
||||
BaseMetricTreeNode (const char *name, const char *uname,
|
||||
const char *_unit, const char *_unit_uname);
|
||||
void init_vars ();
|
||||
void build_basic_tree ();
|
||||
BaseMetricTreeNode *add_child (BaseMetric *item);
|
||||
BaseMetricTreeNode *add_child (const char *name, const char *uname,
|
||||
const char *unit = NULL, const char *unit_uname = NULL);
|
||||
BaseMetricTreeNode *add_child (BaseMetricTreeNode *new_node);
|
||||
void register_node (BaseMetricTreeNode *);
|
||||
|
||||
BaseMetricTreeNode *root; // root of tree
|
||||
BaseMetricTreeNode *parent; // my parent
|
||||
bool aggregation; // value is based on children's values
|
||||
char *name; // bm->get_cmd() for metrics, unique string otherwise
|
||||
char *uname; // user-visible text
|
||||
char *unit; // see UNIT_* defines
|
||||
char *unit_uname; // see UNIT_*_UNAME defines
|
||||
Vector<BaseMetricTreeNode*> *children; // my children
|
||||
bool isCompositeMetric; // value is sum of children
|
||||
BaseMetric *bm; // metric for this node, or null
|
||||
bool registered; // metric has been officially registered
|
||||
int num_registered_descendents; // does not include self
|
||||
};
|
||||
|
||||
#endif /* _BASEMETRICTREENODE_H */
|
186
gprofng/src/CacheMap.h
Normal file
186
gprofng/src/CacheMap.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* Copyright (C) 2021 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. */
|
||||
|
||||
/*
|
||||
* Cache Map implementation.
|
||||
*
|
||||
* Cache Map makes the following assumptions:
|
||||
* - Cache Map is used for very fast but not guaranteed mapping;
|
||||
* - only REL_EQ Relation can be used;
|
||||
* - all objects used as keys or values has to be managed
|
||||
* outside CacheMap (f.e. deletion);
|
||||
* - (Key_t)0 is invalid key;
|
||||
* - (Value_t)0 is invalid value;
|
||||
* - <TBC>
|
||||
*/
|
||||
|
||||
#ifndef _DBE_CACHEMAP_H
|
||||
#define _DBE_CACHEMAP_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <vec.h>
|
||||
#include <Map.h>
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
class CacheMap : public Map<Key_t, Value_t>
|
||||
{
|
||||
public:
|
||||
|
||||
CacheMap ();
|
||||
~CacheMap ();
|
||||
void put (Key_t key, Value_t val);
|
||||
Value_t get (Key_t key);
|
||||
Value_t get (Key_t key, typename Map<Key_t, Value_t>::Relation rel);
|
||||
Value_t
|
||||
remove (Key_t key);
|
||||
|
||||
private:
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Key_t key;
|
||||
Value_t val;
|
||||
|
||||
Entry ()
|
||||
{
|
||||
key = (Key_t) 0;
|
||||
}
|
||||
};
|
||||
|
||||
static const int INIT_SIZE;
|
||||
static const int MAX_SIZE;
|
||||
|
||||
static unsigned hash (Key_t key);
|
||||
Entry *getEntry (Key_t key);
|
||||
|
||||
int cursize;
|
||||
int nputs;
|
||||
int nchunks;
|
||||
Entry **chunks;
|
||||
};
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
const int CacheMap<Key_t, Value_t>::INIT_SIZE = 1 << 14;
|
||||
template <typename Key_t, typename Value_t>
|
||||
const int CacheMap<Key_t, Value_t>::MAX_SIZE = 1 << 20;
|
||||
|
||||
template <typename Key_t, typename Value_t>CacheMap<Key_t, Value_t>
|
||||
::CacheMap ()
|
||||
{
|
||||
cursize = INIT_SIZE;
|
||||
chunks = new Entry*[32];
|
||||
nchunks = 0;
|
||||
chunks[nchunks++] = new Entry[cursize];
|
||||
nputs = 0;
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
CacheMap<Key_t, Value_t>::~CacheMap ()
|
||||
{
|
||||
for (int i = 0; i < nchunks; i++)
|
||||
delete[] chunks[i];
|
||||
delete[] chunks;
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
unsigned
|
||||
CacheMap<Key_t, Value_t>::hash (Key_t key)
|
||||
{
|
||||
unsigned h = (unsigned) key ^ (unsigned) (key >> 32);
|
||||
h ^= (h >> 20) ^ (h >> 12);
|
||||
return h ^ (h >> 7) ^ (h >> 4);
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
void
|
||||
CacheMap<Key_t, Value_t>::put (Key_t key, Value_t val)
|
||||
{
|
||||
if (nputs >= cursize && cursize < MAX_SIZE)
|
||||
{
|
||||
// Allocate new chunk for entries.
|
||||
chunks[nchunks++] = new Entry[cursize];
|
||||
cursize *= 2;
|
||||
|
||||
// Copy all old entries to the newly allocated chunk
|
||||
Entry *newchunk = chunks[nchunks - 1];
|
||||
int prevsz = 0;
|
||||
int nextsz = INIT_SIZE;
|
||||
for (int i = 0; i < nchunks - 1; i++)
|
||||
{
|
||||
Entry *oldchunk = chunks[i];
|
||||
for (int j = prevsz; j < nextsz; j++)
|
||||
newchunk[j] = oldchunk[j - prevsz];
|
||||
prevsz = nextsz;
|
||||
nextsz *= 2;
|
||||
}
|
||||
}
|
||||
Entry *entry = getEntry (key);
|
||||
entry->key = key;
|
||||
entry->val = val;
|
||||
nputs++;
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
typename CacheMap<Key_t, Value_t>::Entry *
|
||||
CacheMap<Key_t, Value_t>::getEntry (Key_t key)
|
||||
{
|
||||
unsigned idx = hash (key);
|
||||
int i = nchunks - 1;
|
||||
int j = cursize / 2;
|
||||
for (; i > 0; i -= 1, j /= 2)
|
||||
if (idx & j)
|
||||
break;
|
||||
if (i == 0)
|
||||
j *= 2;
|
||||
return &chunks[i][idx & (j - 1)];
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
Value_t
|
||||
CacheMap<Key_t, Value_t>::get (Key_t key)
|
||||
{
|
||||
Entry *entry = getEntry (key);
|
||||
return entry->key == key ? entry->val : (Value_t) 0;
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
Value_t
|
||||
CacheMap<Key_t, Value_t>::get (Key_t key, typename Map<Key_t, Value_t>::Relation rel)
|
||||
{
|
||||
if (rel != Map<Key_t, Value_t>::REL_EQ)
|
||||
return (Value_t) 0;
|
||||
return get (key);
|
||||
}
|
||||
|
||||
template <typename Key_t, typename Value_t>
|
||||
Value_t
|
||||
CacheMap<Key_t, Value_t>::remove (Key_t key)
|
||||
{
|
||||
Entry *entry = getEntry (key);
|
||||
Value_t res = (Value_t) 0;
|
||||
if (entry->key == key)
|
||||
{
|
||||
res = entry->val;
|
||||
entry->val = (Value_t) 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
1250
gprofng/src/CallStack.cc
Normal file
1250
gprofng/src/CallStack.cc
Normal file
File diff suppressed because it is too large
Load diff
114
gprofng/src/CallStack.h
Normal file
114
gprofng/src/CallStack.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/* Copyright (C) 2021 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 _CALLSTACK_H
|
||||
#define _CALLSTACK_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "dbe_structs.h"
|
||||
#include "Experiment.h"
|
||||
#include "DbeLock.h"
|
||||
|
||||
class DataDescriptor;
|
||||
class FramePacket;
|
||||
class DbeInstr;
|
||||
class Histable;
|
||||
template <class ITEM> class Vector;
|
||||
class CallStackNode;
|
||||
|
||||
class Descendants /* : public DbeLock */
|
||||
{
|
||||
public:
|
||||
Descendants ();
|
||||
~Descendants ();
|
||||
CallStackNode *find (Histable *hi, int *index);
|
||||
void append (CallStackNode *item);
|
||||
void insert (int ind, CallStackNode *item);
|
||||
int volatile count;
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
DELTA = 8
|
||||
};
|
||||
|
||||
int limit;
|
||||
CallStackNode **data;
|
||||
CallStackNode *first_data[4];
|
||||
};
|
||||
|
||||
class CallStackNode : public Descendants
|
||||
{
|
||||
public:
|
||||
CallStackNode (CallStackNode *_ancestor, Histable *_instr);
|
||||
~CallStackNode ();
|
||||
bool compare (long start, long end, Vector<Histable*> *objs, CallStackNode *mRoot);
|
||||
void dump ();
|
||||
|
||||
CallStackNode *
|
||||
get_ancestor ()
|
||||
{
|
||||
return ancestor;
|
||||
}
|
||||
|
||||
Histable *
|
||||
get_instr ()
|
||||
{
|
||||
return instr;
|
||||
}
|
||||
|
||||
CallStackNode *alt_node;
|
||||
Histable *instr;
|
||||
CallStackNode *ancestor;
|
||||
};
|
||||
|
||||
class CallStack
|
||||
{
|
||||
public:
|
||||
static CallStack *getInstance (Experiment *exp);
|
||||
virtual ~CallStack () { };
|
||||
|
||||
virtual void add_stack (DataDescriptor *dDscr, long idx, FramePacket *frp,
|
||||
cstk_ctx_chunk* cstCtxChunk) = 0;
|
||||
|
||||
// Creates a call stack representation for objs and
|
||||
// returns an opaque pointer to it
|
||||
virtual void *add_stack (Vector<Histable*> *objs) = 0;
|
||||
|
||||
// Debugging methods
|
||||
virtual void print (FILE *) = 0;
|
||||
|
||||
// Call stack inquiries
|
||||
static int stackSize (void *stack);
|
||||
static Histable *getStackPC (void *stack, int n);
|
||||
static Vector<Histable*> *getStackPCs (void *stack, bool get_hide_stack = false);
|
||||
static void setHideStack (void *stack, void *hideStack);
|
||||
static int compare (void *stack1, void *stack2);
|
||||
|
||||
virtual CallStackNode *
|
||||
get_node (int)
|
||||
{
|
||||
return NULL;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _CALLSTACK_H */
|
59
gprofng/src/CatchOutOfMemory.cc
Normal file
59
gprofng/src/CatchOutOfMemory.cc
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) 2021 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 <new> // std::bad_alloc
|
||||
#include <stdio.h> // fprintf
|
||||
#include <stdlib.h> // exit
|
||||
#include "DbeApplication.h"
|
||||
|
||||
static char *name = NULL;
|
||||
|
||||
/**
|
||||
* Out Of Memory exception handler
|
||||
*/
|
||||
void
|
||||
out_of_mem ()
|
||||
{
|
||||
fprintf (stderr, "%s: %s: %s\n", "Error", name ? name : "", "Out of memory\n");
|
||||
exit (2); // Out of memory
|
||||
// throw bad_alloc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls real_main inside try{...}catch(std::bad_alloc *)
|
||||
*/
|
||||
int
|
||||
catch_out_of_memory (int (*real_main)(int, char*[]), int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
name = argv[0];
|
||||
std::set_new_handler (out_of_mem);
|
||||
try
|
||||
{
|
||||
i = real_main (argc, argv);
|
||||
}
|
||||
catch (std::bad_alloc */*ba*/)
|
||||
{
|
||||
exit (2); // Out of memory
|
||||
}
|
||||
delete theDbeApplication;
|
||||
return i;
|
||||
}
|
1639
gprofng/src/ClassFile.cc
Normal file
1639
gprofng/src/ClassFile.cc
Normal file
File diff suppressed because it is too large
Load diff
63
gprofng/src/ClassFile.h
Normal file
63
gprofng/src/ClassFile.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* Copyright (C) 2021 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 _CLASSFILE_H
|
||||
#define _CLASSFILE_H
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
class DataInputStream;
|
||||
class BinaryConstantPool;
|
||||
class JMethod;
|
||||
class StringBuilder;
|
||||
class ByteCodeInfo;
|
||||
|
||||
class ClassFile : public Module
|
||||
{
|
||||
public:
|
||||
ClassFile ();
|
||||
virtual ~ClassFile ();
|
||||
virtual int readFile ();
|
||||
virtual char *get_disasm (uint64_t inst_address, uint64_t end_address,
|
||||
uint64_t start_address, uint64_t f_offset,
|
||||
int64_t &inst_size);
|
||||
static char *get_java_file_name (char *clname, bool classSuffix);
|
||||
|
||||
private:
|
||||
|
||||
void openFile (const char *fname);
|
||||
char *get_opc_name (int op);
|
||||
void readAttributes (int count);
|
||||
void printConstant (StringBuilder *sb, int index);
|
||||
long long printCodeSequence (StringBuilder *sb, uint64_t addr, DataInputStream *in);
|
||||
|
||||
unsigned char *cf_buf;
|
||||
int64_t cf_bufsz;
|
||||
int blanksCnt;
|
||||
DataInputStream *input;
|
||||
BinaryConstantPool *bcpool;
|
||||
JMethod *cur_jmthd;
|
||||
char *class_name;
|
||||
char *class_filename;
|
||||
char *source_name;
|
||||
Vector<ByteCodeInfo *> *byteCodeInfo;
|
||||
};
|
||||
|
||||
#endif
|
562
gprofng/src/Command.cc
Normal file
562
gprofng/src/Command.cc
Normal file
|
@ -0,0 +1,562 @@
|
|||
/* Copyright (C) 2021 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "gp-defs.h"
|
||||
#include "Command.h"
|
||||
#include "DbeSession.h"
|
||||
#include "MemorySpace.h"
|
||||
#include "i18n.h"
|
||||
#include "StringBuilder.h"
|
||||
|
||||
const char *Command::DEFAULT_CMD = "default"; // token for default
|
||||
const char *Command::ALL_CMD = "all"; // token for all
|
||||
const char *Command::ANY_CMD = "any"; // token for any
|
||||
const char *Command::NONE_CMD = "none"; // token for none
|
||||
const char *Command::HWC_CMD = "hwc"; // token for all HWC
|
||||
const char *Command::BIT_CMD = "bit"; // token for any bit-generated metric
|
||||
const char *Command::DEFAULT_METRICS = "ei.user:name"; // if no .rc files read
|
||||
const char *Command::DEFAULT_SORT = "e.user:name"; // if no .rc files read
|
||||
|
||||
static char *fhdr, *cchdr, *lahdr, *iohdr, *sdhdr, *lsthdr, *lohdr;
|
||||
static char *methdr, *othdr, *mischdr, *deflthdr;
|
||||
static char *selhdr, *filthdr, *outhdr, *exphdr, *obj_allhdr;
|
||||
static char *unsuphdr, *indxobjhdr;
|
||||
static char *helphdr, *rahdr, *ddhdr, *typehdr, *typehdr2;
|
||||
|
||||
// This is the list of commands, which governs the parser scan, as
|
||||
// well as the help command.
|
||||
// A line with the tag NO_CMD is skipped in parsing, but is used
|
||||
// to provide subheadings for the help
|
||||
// The HELP line must be the last one in the list of commands
|
||||
// to be shown by "-help"; The HHELP line must be the
|
||||
// last one to be shown by "-xhelp"
|
||||
// The LAST_CMD line must be the last one recognized by the parser
|
||||
//
|
||||
// The ordering of this list should match the ordering in the man
|
||||
// page, and the subheader lines should match the subheadings in
|
||||
// the man page.
|
||||
|
||||
static char *desc[LAST_CMD];
|
||||
|
||||
static Cmdtable cmd_lst[] = { // list of commands
|
||||
// User Commands
|
||||
{ NO_CMD, "", NULL, NULL, 0, &fhdr},
|
||||
{ FUNCS, "functions", NULL, NULL, 0, &desc[FUNCS]},
|
||||
{ METRICS, "metrics", NULL, "metric_spec", 1, &desc[METRICS]},
|
||||
{ SORT, "sort", NULL, "metric_spec", 1, &desc[SORT]},
|
||||
{ FDETAIL, "fsummary", NULL, NULL, 0, &desc[FDETAIL]},
|
||||
{ FSINGLE, "fsingle", NULL, "function_name #", 2, &desc[FSINGLE]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &cchdr},
|
||||
{ GPROF, "callers-callees", "gprof", NULL, 0, &desc[GPROF]},
|
||||
{ CSINGLE, "csingle", NULL, "function_name #", 2, &desc[CSINGLE]},
|
||||
{ CPREPEND, "cprepend", NULL, "function_name #", 2, &desc[CPREPEND]},
|
||||
{ CAPPEND, "cappend", NULL, "function_name #", 2, &desc[CAPPEND]},
|
||||
{ CRMFIRST, "crmfirst", NULL, NULL, 0, &desc[CRMFIRST]},
|
||||
{ CRMLAST, "crmlast", NULL, NULL, 0, &desc[CRMLAST]},
|
||||
{ CALLTREE, "calltree", "ctree", NULL, 0, &desc[CALLTREE]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &lahdr},
|
||||
{ LEAKS, "leaks", NULL, NULL, 0, &desc[LEAKS]},
|
||||
{ ALLOCS, "allocs", NULL, NULL, 0, &desc[ALLOCS]},
|
||||
{ HEAP, "heap", NULL, NULL, 0, &desc[HEAP]},
|
||||
{ HEAPSTAT, "heapstat", NULL, NULL, 0, &desc[HEAPSTAT]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &iohdr},
|
||||
{ IOACTIVITY, "ioactivity", NULL, NULL, 0, &desc[IOACTIVITY]},
|
||||
{ IOVFD, "iodetail", NULL, NULL, 0, &desc[IOVFD]},
|
||||
{ IOCALLSTACK, "iocallstack", NULL, NULL, 0, &desc[IOCALLSTACK]},
|
||||
{ IOSTAT, "iostat", NULL, NULL, 0, &desc[IOSTAT]},
|
||||
|
||||
// PC, line, source and dissassembly commands
|
||||
{ NO_CMD, "", NULL, NULL, 0, &sdhdr},
|
||||
{ HOTPCS, "pcs", NULL, NULL, 0, &desc[HOTPCS]},
|
||||
{ PDETAIL, "psummary", NULL, NULL, 0, &desc[PDETAIL]},
|
||||
{ HOTLINES, "lines", NULL, NULL, 0, &desc[HOTLINES]},
|
||||
{ LDETAIL, "lsummary", NULL, NULL, 0, &desc[LDETAIL]},
|
||||
{ SOURCE, "source", NULL, "func/file #", 2, &desc[SOURCE]},
|
||||
{ DISASM, "disasm", NULL, "func/file #", 2, &desc[DISASM]},
|
||||
{ SCOMPCOM, "scc", NULL, "com_spec", 1, &desc[SCOMPCOM]},
|
||||
{ STHRESH, "sthresh", NULL, "value", 1, &desc[STHRESH]},
|
||||
{ DCOMPCOM, "dcc", NULL, "com_spec", 1, &desc[DCOMPCOM]},
|
||||
{ COMPCOM, "cc", NULL, "com_spec", 1, &desc[COMPCOM]},
|
||||
{ DTHRESH, "dthresh", NULL, "value", 1, &desc[DTHRESH]},
|
||||
{ SETPATH, "setpath", NULL, "path_list", 1, &desc[SETPATH]},
|
||||
{ ADDPATH, "addpath", NULL, "path_list", 1, &desc[ADDPATH]},
|
||||
{ PATHMAP, "pathmap", NULL, "old_prefix new_prefix", 2, &desc[PATHMAP]},
|
||||
{ LIBDIRS, "preload_libdirs", NULL, NULL, 1, &desc[PATHMAP]},
|
||||
|
||||
// Index Object commands
|
||||
{ NO_CMD, "", NULL, NULL, 0, &indxobjhdr},
|
||||
{ INDXOBJ, "indxobj", NULL, "type", 1, &desc[INDXOBJ]},
|
||||
{ INDXOBJLIST, "indxobj_list", NULL, NULL, 0, &desc[INDXOBJLIST]},
|
||||
{ INDXOBJDEF, "indxobj_define", NULL, "type \"index-expr\"", 2, &desc[INDXOBJDEF]},
|
||||
|
||||
// Deadlock detection commands
|
||||
{ NO_CMD, "", NULL, NULL, 0, &ddhdr},
|
||||
{ DEADLOCK_EVNTS, "deadlocks", NULL, NULL, 0, &desc[DEADLOCK_EVNTS]},
|
||||
{ DEADLOCK_SUM, "dsummary", NULL, "{deadlock_id|all}", 1, &desc[DEADLOCK_SUM]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &lsthdr},
|
||||
{ EXP_LIST, "experiment_list", "exp_list", NULL, 0, &desc[EXP_LIST]},
|
||||
{ SAMPLE_LIST, "sample_list", NULL, NULL, 0, &desc[SAMPLE_LIST]},
|
||||
{ LWP_LIST, "lwp_list", NULL, NULL, 0, &desc[LWP_LIST]},
|
||||
{ THREAD_LIST, "thread_list", NULL, NULL, 0, &desc[THREAD_LIST]},
|
||||
{ CPU_LIST, "cpu_list", NULL, NULL, 0, &desc[CPU_LIST]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &filthdr},
|
||||
{ FILTERS, "filters", NULL, "filter-specification", 1, &desc[FILTERS]},
|
||||
{ DESCRIBE, "describe", NULL, NULL, 0, &desc[DESCRIBE]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &selhdr},
|
||||
{ SAMPLE_SELECT, "sample_select", NULL, "sample_spec", 1, &desc[SAMPLE_SELECT]},
|
||||
{ LWP_SELECT, "lwp_select", NULL, "lwp_spec", 1, &desc[LWP_SELECT]},
|
||||
{ THREAD_SELECT, "thread_select", NULL, "thread_spec", 1, &desc[THREAD_SELECT]},
|
||||
{ CPU_SELECT, "cpu_select", NULL, "cpu_spec", 1, &desc[CPU_SELECT]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &lohdr},
|
||||
{ OBJECT_LIST, "object_list", NULL, NULL, 0, &desc[OBJECT_LIST]},
|
||||
{ OBJECT_SHOW, "object_show", NULL, "obj1,...", 1, &desc[OBJECT_SHOW]},
|
||||
{ OBJECT_HIDE, "object_hide", NULL, "obj1,...", 1, &desc[OBJECT_HIDE]},
|
||||
{ OBJECT_API, "object_api", NULL, "obj1,...", 1, &desc[OBJECT_API]},
|
||||
{ DUMMY_CMD, " ", NULL, NULL, 0, &obj_allhdr},
|
||||
{ OBJECTS_DEFAULT, "objects_default", NULL, NULL, 1, &desc[OBJECTS_DEFAULT]},
|
||||
|
||||
{ OBJECT_SELECT, "object_select", NULL, "obj1,...", 1, &desc[OBJECT_SELECT]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &methdr},
|
||||
{ METRIC_LIST, "metric_list", NULL, NULL, 0, &desc[METRIC_LIST]},
|
||||
{ GMETRIC_LIST, "cmetric_list", "gmetric_list", NULL, 0, &desc[GMETRIC_LIST]},
|
||||
{ INDX_METRIC_LIST, "indx_metric_list", NULL, NULL, 1, &desc[INDX_METRIC_LIST]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &outhdr},
|
||||
{ OUTFILE, "outfile", NULL, "filename", 1, &desc[OUTFILE]},
|
||||
{ APPENDFILE, "appendfile", NULL, "filename", 1, &desc[APPENDFILE]},
|
||||
{ LIMIT, "limit", NULL, "n", 1, &desc[LIMIT]},
|
||||
{ NAMEFMT, "name", NULL, "{long|short|mangled}[:{soname|nosoname}]", 1, &desc[NAMEFMT]},
|
||||
{ VIEWMODE, "viewmode", NULL, "{user|expert|machine}", 1, &desc[VIEWMODE]},
|
||||
{ COMPARE, "compare", NULL, "{on|off|delta|ratio}", 1, &desc[COMPARE]},
|
||||
{ PRINTMODE, "printmode", NULL, "string", 1, &desc[PRINTMODE]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &othdr},
|
||||
{ HEADER, "header", NULL, "exp_id", 1, &desc[HEADER]},
|
||||
{ OBJECTS, "objects", NULL, NULL, 0, &desc[OBJECTS]},
|
||||
{ OVERVIEW_NEW, "overview", NULL, NULL, 0, &desc[OVERVIEW_NEW]},
|
||||
{ SAMPLE_DETAIL, "sample_detail", NULL, "exp_id", 1, &desc[SAMPLE_DETAIL]},
|
||||
{ STATISTICS, "statistics", NULL, "exp_id", 1, &desc[STATISTICS]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &exphdr},
|
||||
{ OPEN_EXP, "open_exp", NULL, "experiment", 1, &desc[OPEN_EXP]},
|
||||
{ ADD_EXP, "add_exp", NULL, "experiment", 1, &desc[ADD_EXP]},
|
||||
{ DROP_EXP, "drop_exp", NULL, "experiment", 1, &desc[DROP_EXP]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &deflthdr},
|
||||
{ DMETRICS, "dmetrics", NULL, "metric_spec", 1, &desc[DMETRICS]},
|
||||
{ DSORT, "dsort", NULL, "metric_spec", 1, &desc[DSORT]},
|
||||
{ EN_DESC, "en_desc", NULL, "{on|off|=<regex>}", 1, &desc[EN_DESC]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &mischdr},
|
||||
{ DUMMY_CMD, "<type>", NULL, NULL, 0, &typehdr},
|
||||
{ DUMMY_CMD, " ", NULL, NULL, 0, &typehdr2},
|
||||
|
||||
{ IFREQ, "ifreq", NULL, NULL, 0, &desc[IFREQ]},
|
||||
{ PROCSTATS, "procstats", NULL, NULL, 0, &desc[PROCSTATS]},
|
||||
{ SCRIPT, "script", NULL, "file", 1, &desc[SCRIPT]},
|
||||
{ VERSION_cmd, "version", NULL, NULL, 0, &desc[VERSION_cmd]},
|
||||
{ QUIT, "quit", "exit", NULL, 0, &desc[QUIT]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &helphdr},
|
||||
{ HELP, "help", NULL, NULL, 0, &desc[HELP]},
|
||||
|
||||
{ NO_CMD, "", NULL, NULL, 0, &unsuphdr},
|
||||
{ HELP, "-help", NULL, NULL, 0, &desc[HELP]},
|
||||
{ DUMPFUNC, "dfuncs", NULL, "string", 1, &desc[DUMPFUNC]},
|
||||
{ DUMPDOBJS, "ddobjs", NULL, "string", 1, &desc[DUMPDOBJS]},
|
||||
{ DUMPNODES, "dnodes", NULL, NULL, 0, &desc[DUMPNODES]},
|
||||
{ DUMPSTACKS, "dstacks", NULL, NULL, 0, &desc[DUMPSTACKS]},
|
||||
{ DUMPUNK, "dunkpc", NULL, NULL, 0, &desc[DUMPUNK]},
|
||||
{ DUMPMAP, "dmap", NULL, NULL, 0, &desc[DUMPMAP]},
|
||||
{ DUMPENTITIES, "dentities", NULL, NULL, 0, &desc[DUMPENTITIES]},
|
||||
{ IGNORE_NO_XHWCPROF, "ignore_no_xhwcprof", NULL, NULL, 0, &desc[IGNORE_NO_XHWCPROF]},
|
||||
{ IGNORE_FS_WARN, "ignore_fs_warn", NULL, NULL, 0, &desc[IGNORE_FS_WARN]},
|
||||
|
||||
{ DUMP_PROFILE, "dprofile", NULL, NULL, 0, &desc[DUMP_PROFILE]},
|
||||
{ DUMP_SYNC, "dsync", NULL, NULL, 0, &desc[DUMP_SYNC]},
|
||||
{ DUMP_IOTRACE, "diotrace", NULL, NULL, 0, &desc[DUMP_IOTRACE]},
|
||||
{ DUMP_HWC, "dhwc", NULL, NULL, 0, &desc[DUMP_HWC]},
|
||||
{ DUMP_HEAP, "dheap", NULL, NULL, 0, &desc[DUMP_HEAP]},
|
||||
{ RACE_ACCS, "r_accs", NULL, NULL, 0, &desc[RACE_ACCS]},
|
||||
|
||||
{ DMPI_FUNCS, "dmpi_funcs", NULL, NULL, 0, &desc[DMPI_FUNCS]},
|
||||
{ DMPI_MSGS, "dmpi_msgs", NULL, NULL, 0, &desc[DMPI_MSGS]},
|
||||
{ DMPI_EVENTS, "dmpi_events", NULL, NULL, 0, &desc[DMPI_EVENTS]},
|
||||
|
||||
{ DMEM, "dmem", NULL, NULL, 1, &desc[DMEM]},
|
||||
{ DUMP_GC, "dumpgc", NULL, NULL, 0, &desc[DUMP_GC]},
|
||||
{ DKILL, "dkill", NULL, NULL, 2, &desc[DKILL]},
|
||||
|
||||
{ QQUIT, "xquit", NULL, NULL, 0, &desc[QQUIT]},
|
||||
// use xquit for memory leak detection in dbe; it's
|
||||
// like quit, but deletes all data loaded
|
||||
|
||||
{ HHELP, "xhelp", NULL, NULL, 0, &desc[HHELP]},
|
||||
{ WHOAMI, "-whoami", NULL, NULL, 0, &desc[WHOAMI]},
|
||||
|
||||
// these are not recognized at this point
|
||||
{ LOADOBJECT, "segments", "pmap", NULL, 0, &desc[LOADOBJECT]},
|
||||
{ LOADOBJECT_LIST, "segment_list", NULL, NULL, 0, &desc[LOADOBJECT_LIST]},
|
||||
{ LOADOBJECT_SELECT, "segment_select", NULL, "seg1,...", 1, &desc[LOADOBJECT_SELECT]},
|
||||
|
||||
{ LAST_CMD, "xxxx", NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
CmdType
|
||||
Command::get_command (char *cmd, int &arg_count, int &cparam)
|
||||
{
|
||||
int i;
|
||||
int len = (int) strlen (cmd);
|
||||
bool got = false;
|
||||
CmdType token = UNKNOWN_CMD;
|
||||
arg_count = 0;
|
||||
cparam = -1;
|
||||
if (*cmd == '\0') // - command
|
||||
return STDIN;
|
||||
if (*cmd == '#') // comment
|
||||
return COMMENT;
|
||||
if (strcmp (cmd, "V") == 0 || strcmp (cmd, "-version") == 0)
|
||||
return VERSION_cmd;
|
||||
if (strcmp (cmd, "-help") == 0)
|
||||
return HELP;
|
||||
if (strncmp (cmd, NTXT ("-whoami="), 8) == 0)
|
||||
{
|
||||
cparam = 8;
|
||||
return WHOAMI;
|
||||
}
|
||||
|
||||
if (*cmd == '-')
|
||||
cmd++;
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
if (cmd_lst[i].token == LAST_CMD)
|
||||
break;
|
||||
if (!strncasecmp (cmd, cmd_lst[i].str, len) ||
|
||||
(cmd_lst[i].alt && !strncasecmp (cmd, cmd_lst[i].alt, len)))
|
||||
{
|
||||
// Is it unambiguous?
|
||||
if (!strcasecmp (cmd, cmd_lst[i].str)
|
||||
|| (cmd_lst[i].alt && !strcasecmp (cmd, cmd_lst[i].alt)))
|
||||
{
|
||||
// exact, full-length match
|
||||
token = cmd_lst[i].token;
|
||||
arg_count = cmd_lst[i].arg_count;
|
||||
return token;
|
||||
}
|
||||
if (got)
|
||||
return AMBIGUOUS_CMD;
|
||||
got = true;
|
||||
token = cmd_lst[i].token;
|
||||
arg_count = cmd_lst[i].arg_count;
|
||||
}
|
||||
}
|
||||
|
||||
// Did we find it?
|
||||
if (token != UNKNOWN_CMD)
|
||||
return token;
|
||||
|
||||
// See if it's the name of a index object
|
||||
if (dbeSession)
|
||||
{
|
||||
int indxtype = dbeSession->findIndexSpaceByName (cmd);
|
||||
if (indxtype >= 0)
|
||||
{
|
||||
// found it
|
||||
cparam = indxtype;
|
||||
return INDXOBJ;
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
const char *
|
||||
Command::get_cmd_str (CmdType type)
|
||||
{
|
||||
for (int i = 0;; i++)
|
||||
{
|
||||
if (cmd_lst[i].token == LAST_CMD)
|
||||
break;
|
||||
if (type == cmd_lst[i].token)
|
||||
return cmd_lst[i].str;
|
||||
}
|
||||
return "xxxx";
|
||||
}
|
||||
|
||||
char *
|
||||
Command::get_err_string (Cmd_status err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case CMD_OK:
|
||||
return NULL;
|
||||
case CMD_BAD:
|
||||
return GTXT ("command bad");
|
||||
case CMD_AMBIGUOUS:
|
||||
return GTXT ("command ambiguous");
|
||||
case CMD_BAD_ARG:
|
||||
return GTXT ("Invalid argument to command");
|
||||
case CMD_OUTRANGE:
|
||||
return GTXT ("argument to command is out-of-range");
|
||||
case CMD_INVALID:
|
||||
return GTXT ("invalid command");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Command::print_help (char *prog_name, bool cmd_line, bool usermode, FILE *outf)
|
||||
{
|
||||
char *fmt, *msg;
|
||||
int i;
|
||||
StringBuilder sb;
|
||||
enum CmdType nc;
|
||||
init_desc ();
|
||||
if (usermode) // show the hidden ones, too
|
||||
nc = HELP;
|
||||
else
|
||||
nc = HHELP;
|
||||
|
||||
if (cmd_line)
|
||||
fprintf (outf, GTXT ("Usage: %s [ -script script | -command | - ] exper_1 ... exper_n\n"),
|
||||
prog_name);
|
||||
fprintf (outf, GTXT ("An alternate spelling for a command is shown in [], where applicable.\n\n"
|
||||
"Those commands followed by a * may appear in .rc files.\n\n"
|
||||
"Those commands followed by a $ can only appear in .rc files.\n\n"));
|
||||
fmt = fmt_help (nc, ' ');
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
// check for end of list
|
||||
if (cmd_lst[i].token == LAST_CMD)
|
||||
break;
|
||||
if (cmd_lst[i].token == NO_CMD) // this is a header line
|
||||
fprintf (outf, NTXT (" %s\n"), *cmd_lst[i].desc);
|
||||
else
|
||||
{
|
||||
if (strlen (cmd_lst[i].str) == 0)
|
||||
continue;
|
||||
// this is a real command line
|
||||
sb.setLength (0);
|
||||
sb.append (cmd_lst[i].str);
|
||||
if (cmd_lst[i].alt)
|
||||
{
|
||||
sb.append ('[');
|
||||
sb.append (cmd_lst[i].alt);
|
||||
sb.append (']');
|
||||
}
|
||||
if (cmd_lst[i].arg)
|
||||
{
|
||||
sb.append (' ');
|
||||
sb.append (cmd_lst[i].arg);
|
||||
}
|
||||
msg = sb.toString ();
|
||||
fprintf (outf, fmt, msg, *cmd_lst[i].desc);
|
||||
free (msg);
|
||||
}
|
||||
// check for end of list
|
||||
if (cmd_lst[i].token == nc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// construct format for printing help
|
||||
char *
|
||||
Command::fmt_help (int nc, char head)
|
||||
{
|
||||
int len, max_len, i;
|
||||
static char fmt[BUFSIZ];
|
||||
|
||||
max_len = 0;
|
||||
for (i = 0; i < nc; i++)
|
||||
{
|
||||
len = (int) strlen (cmd_lst[i].str);
|
||||
if (cmd_lst[i].alt)
|
||||
len += (int) strlen (cmd_lst[i].alt) + 2;
|
||||
if (cmd_lst[i].arg)
|
||||
len += (int) strlen (cmd_lst[i].arg) + 2;
|
||||
if (max_len < len)
|
||||
max_len = len;
|
||||
}
|
||||
snprintf (fmt, sizeof (fmt), NTXT (" %c%%-%ds %%s\n"), head, max_len + 1);
|
||||
return fmt;
|
||||
}
|
||||
|
||||
void
|
||||
Command::init_desc ()
|
||||
{
|
||||
if (desc[0] != NULL)
|
||||
return;
|
||||
desc[FUNCS] = GTXT ("display functions with current metrics");
|
||||
desc[HOTPCS] = GTXT ("display hot PC's with current metrics");
|
||||
desc[HOTLINES] = GTXT ("display hot lines with current metrics");
|
||||
desc[FDETAIL] = GTXT ("display summary metrics for each function");
|
||||
desc[OBJECTS] = GTXT ("display object list with errors or warnings");
|
||||
desc[COMPARE] = GTXT ("enable comparison mode for experiments *");
|
||||
desc[PRINTMODE] = GTXT ("set the mode for printing tables *");
|
||||
desc[LDETAIL] = GTXT ("display summary metrics for each hot line");
|
||||
desc[PDETAIL] = GTXT ("display summary metrics for each hot PC");
|
||||
desc[SOURCE] = GTXT ("display annotated source for function/file");
|
||||
desc[DISASM] = GTXT ("display annotated disassembly for function/file");
|
||||
desc[SCOMPCOM] = GTXT ("set compiler commentary classes for source *");
|
||||
desc[STHRESH] = GTXT ("set highlight threshold for source *");
|
||||
desc[DCOMPCOM] = GTXT ("set compiler commentary classes for disasm *");
|
||||
desc[COMPCOM] = GTXT ("set compiler commentary classes for both source and disasm *");
|
||||
desc[DTHRESH] = GTXT ("set highlight threshold for disasm *");
|
||||
desc[METRIC_LIST] = GTXT ("display the available metrics and dmetrics keywords");
|
||||
desc[METRICS] = GTXT ("set a new list of metrics");
|
||||
desc[SORT] = GTXT ("sort tables by the specified metric");
|
||||
desc[GPROF] = GTXT ("display the callers-callees for each function");
|
||||
desc[CALLTREE] = GTXT ("display the tree of function calls");
|
||||
desc[CALLFLAME] = GTXT ("request calltree flame chart -- not a command, but used in the tabs command");
|
||||
desc[GMETRIC_LIST] = GTXT ("display the available callers-callees metrics");
|
||||
desc[FSINGLE] = GTXT ("display the summary metrics for specified function");
|
||||
desc[CSINGLE] = GTXT ("display the callers-callees for the specified function");
|
||||
desc[CPREPEND] = GTXT ("add specified function to the head of the callstack fragment");
|
||||
desc[CAPPEND] = GTXT ("add specified function to the end of the callstack fragment");
|
||||
desc[CRMFIRST] = GTXT ("remove the first function from the callstack fragment");
|
||||
desc[CRMLAST] = GTXT ("remove the last function from the callstack fragment");
|
||||
desc[LEAKS] = GTXT ("display memory leaks, aggregated by callstack");
|
||||
desc[ALLOCS] = GTXT ("display allocations, aggregated by callstack");
|
||||
desc[HEAP] = GTXT ("display memory allocations and leaks, aggregated by callstack");
|
||||
desc[HEAPSTAT] = GTXT ("display heap statistics report");
|
||||
desc[IOACTIVITY] = GTXT ("display I/O activity report, aggregated by file name");
|
||||
desc[IOVFD] = GTXT ("display I/O activity report, aggregated by file descriptor");
|
||||
desc[IOCALLSTACK] = GTXT ("display I/O activity report, aggregated by callstack");
|
||||
desc[IOSTAT] = GTXT ("display I/O statistics report");
|
||||
desc[RACE_ACCS] = GTXT ("dump race access events");
|
||||
desc[DMPI_MSGS] = GTXT ("dump mpi messages");
|
||||
desc[DMPI_FUNCS] = GTXT ("dump mpi function calls");
|
||||
desc[DMPI_EVENTS] = GTXT ("dump mpi trace events");
|
||||
desc[DMEM] = GTXT ("debug command for internal use");
|
||||
desc[DUMP_GC] = GTXT ("dump Java garbage collector events");
|
||||
desc[DKILL] = GTXT ("send process p signal s");
|
||||
desc[DEADLOCK_EVNTS] = GTXT ("display deadlock events");
|
||||
desc[DEADLOCK_SUM] = GTXT ("display summary for the deadlock event");
|
||||
desc[HEADER] = GTXT ("display information about the experiment");
|
||||
desc[OVERVIEW_NEW] = GTXT ("display the overview of all loaded experiments");
|
||||
desc[SAMPLE_DETAIL] = GTXT ("display the current sample list with data");
|
||||
desc[STATISTICS] = GTXT ("display the execution statistics data");
|
||||
desc[EXP_LIST] = GTXT ("display the existing experiments");
|
||||
desc[DESCRIBE] = GTXT ("describe recorded data and tokens available for filtering data");
|
||||
desc[OBJECT_SHOW] = GTXT ("set load objects to show all functions *");
|
||||
desc[OBJECT_HIDE] = GTXT ("set load objects to hide functions *");
|
||||
desc[OBJECT_API] = GTXT ("set load objects to show API (entry point) only *");
|
||||
desc[OBJECTS_DEFAULT] = GTXT ("reset load objects show to defaults");
|
||||
desc[OBJECT_LIST] = GTXT ("display load objects, functions-shown flag");
|
||||
desc[OBJECT_SELECT] = GTXT ("set list of load objects whose functions are shown");
|
||||
desc[SAMPLE_LIST] = GTXT ("display the list of existing samples");
|
||||
desc[SAMPLE_SELECT] = GTXT ("set a new list of samples");
|
||||
desc[THREAD_LIST] = GTXT ("display the list of existing threads");
|
||||
desc[THREAD_SELECT] = GTXT ("set a new list of threads");
|
||||
desc[LWP_LIST] = GTXT ("display the list of existing LWPs");
|
||||
desc[LWP_SELECT] = GTXT ("set a new list of LWPs");
|
||||
desc[CPU_LIST] = GTXT ("display the list of CPUs");
|
||||
desc[CPU_SELECT] = GTXT ("set a new list of CPUs");
|
||||
desc[OUTFILE] = GTXT ("open filename for subsequent output");
|
||||
desc[APPENDFILE] = GTXT ("open filename for subsequent appended output");
|
||||
desc[LIMIT] = GTXT ("limit output to the first n entries (n=0 for no limit)");
|
||||
desc[NAMEFMT] = GTXT ("set long/short/mangled names for functions *");
|
||||
desc[VIEWMODE] = GTXT ("set viewmode user|expert|machine *");
|
||||
desc[EN_DESC] = GTXT ("enable descendant processes on|off|regex matches lineage or program name $");
|
||||
desc[SETPATH] = GTXT ("set search path for annotated src/dis");
|
||||
desc[ADDPATH] = GTXT ("add search path for annotated src/dis *");
|
||||
desc[PATHMAP] = GTXT ("remap path prefix for annotated src/dis *");
|
||||
desc[LIBDIRS] = GTXT ("set path where the gprofng libraries are installed");
|
||||
desc[SCRIPT] = GTXT ("read er_print commands from script file");
|
||||
desc[PROCSTATS] = GTXT ("display processing statistics");
|
||||
desc[ADD_EXP] = GTXT ("add experiment or group");
|
||||
desc[DROP_EXP] = GTXT ("drop experiment");
|
||||
desc[OPEN_EXP] = GTXT ("open experiment or group (drops all loaded experiments first)");
|
||||
desc[VERSION_cmd] = GTXT ("display the current release version");
|
||||
desc[HELP] = GTXT ("display the list of available commands");
|
||||
desc[QUIT] = GTXT ("terminate processing and exit");
|
||||
desc[DMETRICS] = GTXT ("set default function list metrics $");
|
||||
desc[DSORT] = GTXT ("set default function list sort metric $");
|
||||
desc[TLMODE] = GTXT ("set default timeline mode, align, depth $");
|
||||
desc[TLDATA] = GTXT ("set default timeline visible data $");
|
||||
desc[TABS] = GTXT ("set default visible tabs $");
|
||||
desc[RTABS] = GTXT ("set default visible tabs for Thread Analyzer Experiment $");
|
||||
desc[INDXOBJ] = GTXT ("display index objects of a specified type with current metrics");
|
||||
desc[INDXOBJLIST] = GTXT ("display list of index objects");
|
||||
desc[INDXOBJDEF] = GTXT ("define a new index object type *");
|
||||
desc[INDX_METRIC_LIST] = GTXT ("display the available index object metrics");
|
||||
desc[IFREQ] = GTXT ("display instruction-frequency report");
|
||||
desc[TIMELINE] = GTXT ("request timeline -- not a command, but used in the tabs command");
|
||||
desc[MPI_TIMELINE] = GTXT ("request mpi-timeline -- not a command, but used in the tabs command");
|
||||
desc[MPI_CHART] = GTXT ("request mpi chart -- not a command, but used in the tabs command");
|
||||
desc[DUALSOURCE] = GTXT ("request dualsource tab -- not a command, but used in the tabs command");
|
||||
desc[SOURCEDISAM] = GTXT ("request source/disassembly tab -- not a command, but used in the tabs command");
|
||||
desc[DUMPNODES] = GTXT ("dump pathtree node table");
|
||||
desc[DUMPSTACKS] = GTXT ("dump Experiment callstack tables");
|
||||
desc[DUMPUNK] = GTXT ("dump <Unknown> PCs");
|
||||
desc[DUMPFUNC] = GTXT ("dump functions whose name matches string");
|
||||
desc[DUMPDOBJS] = GTXT ("dump dataobjects whose name matches string");
|
||||
desc[DUMPMAP] = GTXT ("dump load-object map");
|
||||
desc[DUMPENTITIES] = GTXT ("dump threads, lwps, cpus");
|
||||
desc[DUMP_PROFILE] = GTXT ("dump clock profile events");
|
||||
desc[DUMP_SYNC] = GTXT ("dump synchronization trace events");
|
||||
desc[DUMP_IOTRACE] = GTXT ("dump IO trace events");
|
||||
desc[DUMP_HWC] = GTXT ("dump HWC profile events");
|
||||
desc[DUMP_HEAP] = GTXT ("dump heap trace events");
|
||||
desc[IGNORE_NO_XHWCPROF] = GTXT ("ignore absence of -xhwcprof info in dataspace profiling $");
|
||||
desc[IGNORE_FS_WARN] = GTXT ("ignore filesystem (nfs, ...) warning $");
|
||||
desc[HHELP] = GTXT ("display help including unsupported commands");
|
||||
desc[QQUIT] = GTXT ("terminate processing and exit");
|
||||
desc[LOADOBJECT] = GTXT ("display the address map with current metrics");
|
||||
desc[LOADOBJECT_LIST] = GTXT ("display segments, indicating which are selected");
|
||||
desc[LOADOBJECT_SELECT] = GTXT ("set a new list of segments");
|
||||
desc[FILTERS] = GTXT ("define a filter");
|
||||
|
||||
fhdr = GTXT ("\nCommands controlling the function list:");
|
||||
cchdr = GTXT ("\nCommands controlling the callers-callees and calltree lists:");
|
||||
lahdr = GTXT ("\nCommands controlling the leak and allocation lists:");
|
||||
iohdr = GTXT ("\nCommand controlling the I/O activity report:");
|
||||
rahdr = GTXT ("\nCommands controlling the race events lists:");
|
||||
ddhdr = GTXT ("\nCommands controlling the deadlock events lists:");
|
||||
typehdr = GTXT ("equivalent to \"memobj type\", or \"indxobj type\"");
|
||||
typehdr2 = GTXT (" where type is a memory object or index object type");
|
||||
sdhdr = GTXT ("\nCommands controlling the source and disassembly listings:");
|
||||
lsthdr = GTXT ("\nCommands listing experiments, samples and threads:");
|
||||
lohdr = GTXT ("\nCommands controlling load object selection:");
|
||||
obj_allhdr = GTXT (" the special object name `all' refers to all load objects");
|
||||
methdr = GTXT ("\nCommands that list metrics:");
|
||||
othdr = GTXT ("\nCommands that print other displays:");
|
||||
outhdr = GTXT ("\nCommands that control output:");
|
||||
mischdr = GTXT ("\nMiscellaneous commands:");
|
||||
exphdr = GTXT ("\nCommands for experiments (scripts and interactive mode only):");
|
||||
deflthdr = GTXT ("\nDefault-setting commands:");
|
||||
selhdr = GTXT ("\nCommands controlling old-style filters/selection:");
|
||||
filthdr = GTXT ("\nCommands controlling filters:");
|
||||
indxobjhdr = GTXT ("\nCommands controlling the index objects:");
|
||||
unsuphdr = GTXT ("\nUnsupported commands:");
|
||||
helphdr = GTXT ("\nHelp command:");
|
||||
}
|
286
gprofng/src/Command.h
Normal file
286
gprofng/src/Command.h
Normal file
|
@ -0,0 +1,286 @@
|
|||
/* Copyright (C) 2021 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 _COMMAND_H
|
||||
#define _COMMAND_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Metric.h"
|
||||
#include "Hist_data.h"
|
||||
#include "dbe_types.h"
|
||||
#include "vec.h"
|
||||
#include "enums.h"
|
||||
|
||||
// This enum lists all the commands parsed by er_print
|
||||
// The ordering here is not important, but LAST_CMD must
|
||||
// be defined as the last command for which a help line will exist
|
||||
// Command.cc has a matching list, and the ordering in
|
||||
// that list determines what shows up under the help and xhelp commands.
|
||||
// In particular, the entry for HELP is the last one printed
|
||||
// for the help command, and the entry for HHELP is the last
|
||||
// one printed for xhelp.
|
||||
|
||||
enum CmdType
|
||||
{
|
||||
// Pathtree-related commands
|
||||
FUNCS = 0,
|
||||
HOTPCS,
|
||||
HOTLINES,
|
||||
FDETAIL,
|
||||
OBJECTS,
|
||||
LDETAIL,
|
||||
PDETAIL,
|
||||
SOURCE,
|
||||
DISASM,
|
||||
METRIC_LIST,
|
||||
METRICS,
|
||||
SORT,
|
||||
GPROF,
|
||||
GMETRIC_LIST,
|
||||
FSINGLE,
|
||||
CSINGLE,
|
||||
CPREPEND,
|
||||
CAPPEND,
|
||||
CRMFIRST,
|
||||
CRMLAST,
|
||||
CALLTREE,
|
||||
CALLFLAME,
|
||||
|
||||
// Source/disassembly control commands
|
||||
SCOMPCOM,
|
||||
STHRESH,
|
||||
DCOMPCOM,
|
||||
COMPCOM,
|
||||
DTHRESH,
|
||||
|
||||
// Heap trace-related commands
|
||||
LEAKS,
|
||||
ALLOCS,
|
||||
HEAP,
|
||||
HEAPSTAT,
|
||||
|
||||
// I/O trace-related commands
|
||||
IOACTIVITY,
|
||||
IOVFD,
|
||||
IOCALLSTACK,
|
||||
IOSTAT,
|
||||
|
||||
// Race detection related commands
|
||||
RACE_EVNTS,
|
||||
RACE_SUM,
|
||||
|
||||
// Deadlock detection commands
|
||||
DEADLOCK_EVNTS,
|
||||
DEADLOCK_SUM,
|
||||
|
||||
// DataSpace commands
|
||||
DOBJECTS,
|
||||
DO_SINGLE,
|
||||
DO_LAYOUT,
|
||||
DO_METRIC_LIST,
|
||||
|
||||
// MemorySpace commands
|
||||
MEMOBJ,
|
||||
MEMOBJLIST,
|
||||
MEMOBJDEF,
|
||||
MEMOBJDROP,
|
||||
MACHINEMODEL,
|
||||
|
||||
// Custom tab commands
|
||||
INDXOBJDEF,
|
||||
INDXOBJLIST,
|
||||
INDXOBJ,
|
||||
INDX_METRIC_LIST,
|
||||
|
||||
// Old-style filtering commands
|
||||
OBJECT_LIST,
|
||||
OBJECT_SELECT,
|
||||
SAMPLE_LIST,
|
||||
SAMPLE_SELECT,
|
||||
THREAD_LIST,
|
||||
THREAD_SELECT,
|
||||
LWP_LIST,
|
||||
LWP_SELECT,
|
||||
CPU_LIST,
|
||||
CPU_SELECT,
|
||||
|
||||
// Shared Object display commands
|
||||
OBJECT_SHOW,
|
||||
OBJECT_HIDE,
|
||||
OBJECT_API,
|
||||
OBJECTS_DEFAULT,
|
||||
|
||||
// the new filtering commands
|
||||
FILTERS,
|
||||
|
||||
// Miscellaneous commands
|
||||
COMPARE,
|
||||
PRINTMODE,
|
||||
HEADER,
|
||||
OVERVIEW_NEW,
|
||||
SAMPLE_DETAIL,
|
||||
STATISTICS,
|
||||
EXP_LIST,
|
||||
DESCRIBE,
|
||||
OUTFILE,
|
||||
APPENDFILE,
|
||||
LIMIT,
|
||||
NAMEFMT,
|
||||
VIEWMODE,
|
||||
EN_DESC,
|
||||
SETPATH,
|
||||
ADDPATH,
|
||||
PATHMAP,
|
||||
LIBDIRS,
|
||||
SCRIPT,
|
||||
VERSION_cmd,
|
||||
QUIT,
|
||||
PROCSTATS,
|
||||
|
||||
// Experiments handling commands
|
||||
ADD_EXP,
|
||||
DROP_EXP,
|
||||
OPEN_EXP,
|
||||
|
||||
// .rc-only Commands
|
||||
DMETRICS,
|
||||
DSORT,
|
||||
TLMODE,
|
||||
TLDATA,
|
||||
TABS,
|
||||
TIMELINE,
|
||||
MPI_TIMELINE,
|
||||
MPI_CHART,
|
||||
TIMELINE_CLASSIC_TBR,
|
||||
SOURCE_V2,
|
||||
DISASM_V2,
|
||||
RTABS,
|
||||
DUALSOURCE,
|
||||
SOURCEDISAM,
|
||||
|
||||
HELP, // this is the last of the commands listed with "help"
|
||||
IFREQ,
|
||||
DUMPNODES,
|
||||
DUMPSTACKS,
|
||||
DUMPUNK,
|
||||
DUMPFUNC,
|
||||
DUMPDOBJS,
|
||||
DUMPMAP,
|
||||
DUMPENTITIES,
|
||||
DUMP_PROFILE,
|
||||
DUMP_SYNC,
|
||||
DUMP_HWC,
|
||||
DUMP_HEAP,
|
||||
DUMP_IOTRACE,
|
||||
RACE_ACCS,
|
||||
DMPI_FUNCS,
|
||||
DMPI_MSGS,
|
||||
DMPI_EVENTS,
|
||||
DMEM,
|
||||
DUMP_GC,
|
||||
DKILL,
|
||||
IGNORE_NO_XHWCPROF,
|
||||
IGNORE_FS_WARN,
|
||||
QQUIT,
|
||||
HHELP, // this is the last command listed with "xhelp"
|
||||
NO_CMD, // Dummy command, used for headers in help
|
||||
DUMMY_CMD, // Dummy command, used for help
|
||||
|
||||
// unused commands
|
||||
LOADOBJECT,
|
||||
LOADOBJECT_LIST,
|
||||
LOADOBJECT_SELECT,
|
||||
|
||||
// Internal-only Commands
|
||||
LAST_CMD, // No more commands for which a help line is possible
|
||||
STDIN,
|
||||
COMMENT,
|
||||
WHOAMI,
|
||||
|
||||
// Error return "commands"
|
||||
AMBIGUOUS_CMD,
|
||||
UNKNOWN_CMD
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const CmdType token; // command key
|
||||
const char *str; // command string
|
||||
const char *alt; // alternate command string
|
||||
const char *arg; // argument string for help
|
||||
const int arg_count; // no. of arguments
|
||||
char **desc; // description for help
|
||||
} Cmdtable;
|
||||
|
||||
// Command class: never instantiated, completely static
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
|
||||
// look up a string in the command table, return type, set number of args
|
||||
static CmdType get_command (char *cmd, int &arg_count, int ¶m);
|
||||
static const char *get_cmd_str (CmdType type);
|
||||
static void print_help (char *prog_name, bool cmd_line, bool usermode, FILE *outf);
|
||||
static char *get_err_string (Cmd_status err);
|
||||
|
||||
static const char *DEFAULT_METRICS; // default if no .rc files read
|
||||
static const char *DEFAULT_SORT; // default if no .rc files read
|
||||
static const char *DEFAULT_CMD; // token for default
|
||||
static const char *ALL_CMD; // token for all
|
||||
static const char *ANY_CMD; // token for any
|
||||
static const char *NONE_CMD; // token for none
|
||||
static const char *HWC_CMD; // token for all HWC
|
||||
static const char *BIT_CMD; // token for any bit-derived metric
|
||||
|
||||
private:
|
||||
static const int user_no; // the last user command
|
||||
static const int hidden_no; // the last hidden command
|
||||
static const int command_no; // the last parsable command
|
||||
|
||||
static void init_desc ();
|
||||
static char *fmt_help (int nc, char head);
|
||||
};
|
||||
|
||||
// Analyzer display tabs
|
||||
struct DispTab
|
||||
{
|
||||
DispTab (int ntype, int num, bool vis, CmdType token)
|
||||
{
|
||||
type = ntype;
|
||||
order = num;
|
||||
visible = vis;
|
||||
available = true;
|
||||
cmdtoken = token;
|
||||
}
|
||||
|
||||
void setAvailability (bool val) { available = val; }
|
||||
|
||||
int type; // Display type
|
||||
int order; // Order in which tabs should appear in GUI
|
||||
bool visible; // Is Tab visible
|
||||
bool available; // Is tab available for this experiment
|
||||
CmdType cmdtoken; // command token
|
||||
int param; // command parameter (used for memory space)
|
||||
};
|
||||
|
||||
#endif /* ! _COMMAND_H */
|
313
gprofng/src/CompCom.cc
Normal file
313
gprofng/src/CompCom.cc
Normal file
|
@ -0,0 +1,313 @@
|
|||
/* Copyright (C) 2021 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "demangle.h"
|
||||
#include "gp-defs.h"
|
||||
#include "StringBuilder.h"
|
||||
#include "CompCom.h"
|
||||
#include "Elf.h"
|
||||
#include "util.h"
|
||||
#include "i18n.h"
|
||||
#include "comp_com.c"
|
||||
|
||||
CompComment::CompComment (Elf *_elf, int _compcom)
|
||||
{
|
||||
elf = _elf;
|
||||
compcom = _compcom;
|
||||
elf_cls = elf->elf_getclass ();
|
||||
}
|
||||
|
||||
CompComment::~CompComment () { }
|
||||
|
||||
int
|
||||
CompComment::get_align (int64_t offset, int align)
|
||||
{
|
||||
int val = (int) (offset % align);
|
||||
if (val)
|
||||
val = align - val;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preprocesses the header structure, builds a table of messages with the line
|
||||
* numbers, PCoffsets, original index, and compmsg pointer for each message.
|
||||
* If the show_bits field is not in the message, this routine would fill it in
|
||||
* from the mapping from COMPMSG_ID
|
||||
*/
|
||||
int
|
||||
CompComment::compcom_open (CheckSrcName check_src)
|
||||
{
|
||||
if (check_src == NULL)
|
||||
return 0;
|
||||
Elf_Data *data = elf->elf_getdata (compcom);
|
||||
uint64_t b_offset = data->d_off;
|
||||
if (get_align (b_offset, 4)) // not align 4
|
||||
return 0;
|
||||
char *CommData = (char *) data->d_buf;
|
||||
uint64_t offset = b_offset;
|
||||
for (uint64_t e_offset = b_offset + data->d_size; offset < e_offset;)
|
||||
{
|
||||
offset += get_align (offset, (int) data->d_align);
|
||||
if (offset >= e_offset)
|
||||
return 0;
|
||||
compcomhdr *hdr = (compcomhdr *) (CommData + (offset - b_offset));
|
||||
int hdr_msgcount = elf->decode (hdr->msgcount);
|
||||
int hdr_srcname = elf->decode (hdr->srcname);
|
||||
int hdr_stringlen = elf->decode (hdr->stringlen);
|
||||
int hdr_paramcount = elf->decode (hdr->paramcount);
|
||||
size_t length = sizeof (compcomhdr) + hdr_msgcount * sizeof (compmsg) +
|
||||
hdr_paramcount * sizeof (int32_t);
|
||||
if (offset + length + hdr_stringlen > e_offset || hdr_srcname < 0
|
||||
|| hdr_srcname >= hdr_stringlen)
|
||||
return 0;
|
||||
|
||||
// check source file
|
||||
char *src_name = (char *) (((char*) hdr) + length + hdr_srcname);
|
||||
if (check_src (src_name))
|
||||
{
|
||||
msgs = (compmsg *) (((char *) hdr) + sizeof (compcomhdr));
|
||||
params = (int32_t *) ((char *) msgs + hdr_msgcount * sizeof (compmsg));
|
||||
strs = (char *) ((char *) params + hdr_paramcount * sizeof (int32_t));
|
||||
|
||||
// initialize the I18N/L10N strings & set the visible table
|
||||
ccm_vis_init ();
|
||||
return hdr_msgcount;
|
||||
}
|
||||
offset += (length + hdr_stringlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
CompComment::get_demangle_name (char *fname)
|
||||
{
|
||||
if (*fname == '_')
|
||||
return cplus_demangle (fname, DMGL_PARAMS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* takes the message, and returns the I18N string for the message.
|
||||
*/
|
||||
char *
|
||||
CompComment::compcom_format (int index, compmsg *msg, int &visible)
|
||||
{
|
||||
compmsg *p = msgs + index;
|
||||
msg->instaddr = elf->decode (p->instaddr);
|
||||
msg->lineno = elf->decode (p->lineno);
|
||||
msg->msg_type = elf->decode (p->msg_type);
|
||||
msg->nparam = elf->decode (p->nparam);
|
||||
msg->param_index = elf->decode (p->param_index);
|
||||
|
||||
int vindex = ccm_vis_index (msg->msg_type);
|
||||
char *mbuf;
|
||||
Ccm_Primtype_t prim_ty;
|
||||
visible = ccm_attrs[vindex].vis;
|
||||
if (ccm_attrs[vindex].msg == NULL)
|
||||
{
|
||||
/* Print CCM_UNKNOWN message */
|
||||
int uindex = ccm_vis_index (CCM_UNKNOWN);
|
||||
visible = ccm_attrs[uindex].vis;
|
||||
return dbe_sprintf (ccm_attrs[uindex].msg, vindex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the output buffer based on the primitive types of the
|
||||
* message parameters.
|
||||
*
|
||||
* Parameter lists have to be handled carefully -- the 1 parameter
|
||||
* is built up of all the elements separated by ", ".
|
||||
*
|
||||
* Old way: Case by message format string.
|
||||
*/
|
||||
int *ind = params + msg->param_index;
|
||||
int plist_idx = ccm_paramlist_index (msg->msg_type);
|
||||
if (plist_idx <= 0)
|
||||
{
|
||||
/* No parameter list to handle; 0 parameters case is handled */
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_COMPCOM_ARGS = 13
|
||||
};
|
||||
char *parms[MAX_COMPCOM_ARGS];
|
||||
if (msg->nparam >= MAX_COMPCOM_ARGS)
|
||||
{
|
||||
fprintf (stderr,
|
||||
GTXT ("Warning: improperly formatted compiler commentary message (%d parameters >= %d);\n please report this bug against the compiler\n"),
|
||||
msg->nparam, MAX_COMPCOM_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < MAX_COMPCOM_ARGS; i++)
|
||||
parms[i] = NULL; // initialize array
|
||||
int prm_cnt = ccm_num_params (msg->msg_type);
|
||||
if (prm_cnt != msg->nparam)
|
||||
{
|
||||
fprintf (stderr,
|
||||
GTXT ("Warning, improperly formatted compiler commentary message (parameter count mismatch = %d, param# = %d, msg_type = %x, `%s');\n please report this bug against the compiler\n"),
|
||||
prm_cnt, msg->nparam, msg->msg_type, ccm_attrs[vindex].msg);
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < msg->nparam; i++)
|
||||
{
|
||||
/* Parameters in message-type numbered from '1' */
|
||||
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
||||
if (prim_ty == CCM_PRIMTYPE_INTEGER)
|
||||
{
|
||||
unsigned long v = elf->decode (ind[i]);
|
||||
parms[i] = (char*) v;
|
||||
}
|
||||
else if (prim_ty == CCM_PRIMTYPE_STRING)
|
||||
{
|
||||
char *fname = strs + elf->decode (ind[i]);
|
||||
char *demName = get_demangle_name (fname);
|
||||
parms[i] = demName ? demName : dbe_strdup (fname);
|
||||
}
|
||||
else if (prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
||||
parms[i] = dbe_sprintf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"),
|
||||
(unsigned long long) msg->instaddr);
|
||||
else
|
||||
{
|
||||
fprintf (stderr,
|
||||
GTXT ("Warning, improperly formatted compiler commentary message (unexpected primitive type %d);\n please report this bug against the compiler\n"),
|
||||
prim_ty);
|
||||
// Dummy code to avoid compiler's warning: static function ccm_param_hightype is not used
|
||||
Ccm_Hitype_t hightype = CCM_HITYPE_NONE;
|
||||
if (hightype != CCM_HITYPE_NONE)
|
||||
hightype = ccm_param_hightype (msg->msg_type, i + 1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Must make sure to pass _ALL_ params; may pass more because
|
||||
* the format won't access the 'extra' parameters if all the
|
||||
* rules for messages have been followed.
|
||||
*/
|
||||
mbuf = dbe_sprintf (ccm_attrs[vindex].msg, parms[0], parms[1], parms[2],
|
||||
parms[3], parms[4], parms[5], parms[6], parms[7],
|
||||
parms[8], parms[9], parms[10], parms[11]);
|
||||
// Cleanup allocated memory.
|
||||
for (int i = 0; i < msg->nparam; i++)
|
||||
{
|
||||
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
||||
if (prim_ty == CCM_PRIMTYPE_STRING || prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
||||
free (parms[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Parameter list messages never have 0 parameters; the
|
||||
* primitive type for the parameter list elements is always
|
||||
* the same. And as of 22-Sep-2006, it was always
|
||||
* CCM_PRIMTYPE_STRING.
|
||||
*
|
||||
* Account for different bases of parameter indices and
|
||||
* 'nparam' count (1 and 0, respectively).
|
||||
*/
|
||||
char *parms[3];
|
||||
if (plist_idx > (int) ((sizeof (parms) / sizeof (char*))))
|
||||
{
|
||||
fprintf (stderr,
|
||||
GTXT ("Warning: improperly formatted compiler commentary message (msg->nparam=%d plist_idx=%d);\n please report this bug against the compiler\n"),
|
||||
msg->nparam, plist_idx);
|
||||
return NULL;
|
||||
}
|
||||
for (size_t i = 0; i < (sizeof (parms) / sizeof (char*)); i++)
|
||||
parms[i] = NULL; // initialize array
|
||||
|
||||
StringBuilder sb;
|
||||
prim_ty = ccm_param_primtype (msg->msg_type, plist_idx);
|
||||
for (int i = plist_idx - 1; i < msg->nparam; i++)
|
||||
{
|
||||
if (i != plist_idx - 1)
|
||||
sb.append (GTXT (", "));
|
||||
if (prim_ty == CCM_PRIMTYPE_INTEGER)
|
||||
sb.append (elf->decode (ind[i]));
|
||||
else if (prim_ty == CCM_PRIMTYPE_STRING)
|
||||
{
|
||||
char *fname = strs + elf->decode (ind[i]);
|
||||
char *demName = get_demangle_name (fname);
|
||||
if (demName)
|
||||
{
|
||||
sb.append (demName);
|
||||
delete demName;
|
||||
}
|
||||
else
|
||||
sb.append (fname);
|
||||
}
|
||||
else if (prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
||||
sb.appendf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"),
|
||||
(unsigned long long) msg->instaddr);
|
||||
}
|
||||
parms[plist_idx - 1] = sb.toString ();
|
||||
|
||||
for (int i = 0; i < plist_idx - 1; i++)
|
||||
{
|
||||
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
||||
if (prim_ty == CCM_PRIMTYPE_INTEGER)
|
||||
{
|
||||
unsigned long v = elf->decode (ind[i]);
|
||||
parms[i] = (char*) v;
|
||||
}
|
||||
else if (prim_ty == CCM_PRIMTYPE_STRING)
|
||||
{
|
||||
char *fname = strs + elf->decode (ind[i]);
|
||||
char *demName = get_demangle_name (fname);
|
||||
parms[i] = demName ? demName : dbe_strdup (fname);
|
||||
}
|
||||
else if (prim_ty == CCM_PRIMTYPE_HEXSTRING)
|
||||
parms[i] = dbe_sprintf (elf_cls == ELFCLASS32 ? NTXT ("0x%08llx") : NTXT ("0x%016llx"),
|
||||
(unsigned long long) msg->instaddr);
|
||||
else
|
||||
{
|
||||
fprintf (stderr,
|
||||
GTXT ("Warning, improperly formatted compiler commentary message (unexpected primitive type %d);\n please report this bug against the compiler\n"),
|
||||
prim_ty);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have reduced the parameter list to a single string (as
|
||||
* the printf format specifier requires), so only have
|
||||
* 'plist_idx' parameters.
|
||||
*/
|
||||
mbuf = dbe_sprintf (ccm_attrs[vindex].msg, parms[0], parms[1], parms[2]);
|
||||
|
||||
// Cleanup allocated memory.
|
||||
free (parms[plist_idx - 1]);
|
||||
for (int i = 0; i < plist_idx - 1; i++)
|
||||
{
|
||||
prim_ty = ccm_param_primtype (msg->msg_type, i + 1);
|
||||
if (prim_ty == CCM_PRIMTYPE_STRING || prim_ty == CCM_PRIMTYPE_STRING)
|
||||
free (parms[i]);
|
||||
}
|
||||
}
|
||||
return mbuf;
|
||||
}
|
63
gprofng/src/CompCom.h
Normal file
63
gprofng/src/CompCom.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* Copyright (C) 2021 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 _COMPCOM_H
|
||||
#define _COMPCOM_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "comp_com.h"
|
||||
|
||||
class Elf;
|
||||
typedef int (*CheckSrcName) (char *);
|
||||
|
||||
class CompComment
|
||||
{
|
||||
public:
|
||||
CompComment (Elf *_elf, int _compcom);
|
||||
~CompComment ();
|
||||
int compcom_open (CheckSrcName check_src);
|
||||
char *compcom_format (int index, compmsg *msg, int &visible);
|
||||
|
||||
private:
|
||||
int get_align (int64_t, int align);
|
||||
char *get_demangle_name (char *fname);
|
||||
|
||||
Elf *elf;
|
||||
int compcom, elf_cls;
|
||||
compmsg *msgs; /* the array of messages */
|
||||
int32_t *params; /* the parameters used in the messages parameters are
|
||||
* either integers or string-indices */
|
||||
char *strs; /* the strings used in the messages */
|
||||
};
|
||||
|
||||
class ComC
|
||||
{
|
||||
public:
|
||||
ComC () { com_str = NULL; };
|
||||
~ComC () { free (com_str); };
|
||||
|
||||
int sec;
|
||||
int type;
|
||||
int visible;
|
||||
int line;
|
||||
char *com_str;
|
||||
};
|
||||
|
||||
#endif /* _COMPCOM_H */
|
193
gprofng/src/DataObject.cc
Normal file
193
gprofng/src/DataObject.cc
Normal file
|
@ -0,0 +1,193 @@
|
|||
/* Copyright (C) 2021 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 <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "DbeSession.h"
|
||||
#include "Application.h"
|
||||
#include "DataObject.h"
|
||||
#include "Module.h"
|
||||
#include "debug.h"
|
||||
|
||||
DataObject::DataObject ()
|
||||
{
|
||||
name = NULL;
|
||||
parent = NULL;
|
||||
master = NULL;
|
||||
_unannotated_name = NULL;
|
||||
_typename = NULL;
|
||||
_instname = NULL;
|
||||
scope = NULL;
|
||||
EAs = new Vector<DbeEA*>;
|
||||
size = 0;
|
||||
offset = (uint64_t) (-1);
|
||||
}
|
||||
|
||||
DataObject::~DataObject ()
|
||||
{
|
||||
free (_unannotated_name);
|
||||
free (_typename);
|
||||
free (_instname);
|
||||
EAs->destroy ();
|
||||
delete EAs;
|
||||
}
|
||||
|
||||
// get_addr() doesn't return an actual address for a DataObject
|
||||
// but rather synthesises an address-like identifier tuple.
|
||||
// XXXX since an aggregate and its first element have identical tuples
|
||||
// may need to arrange for special-purpose sorting "by address"
|
||||
uint64_t
|
||||
DataObject::get_addr ()
|
||||
{
|
||||
uint64_t addr;
|
||||
if (parent && parent->get_typename ())
|
||||
addr = MAKE_ADDRESS (parent->id, offset); // element
|
||||
else if (parent)
|
||||
addr = MAKE_ADDRESS (parent->id, id) | 0x8000000000000000ULL; // Scalar, Unknown
|
||||
else if (id == dbeSession->get_Scalars_DataObject ()->id)
|
||||
addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Scalar aggregate
|
||||
else if (id == dbeSession->get_Unknown_DataObject ()->id)
|
||||
addr = MAKE_ADDRESS (id, 0) | 0x8000000000000000ULL; // Unknown aggregate
|
||||
else
|
||||
addr = MAKE_ADDRESS (id, 0); // aggregate
|
||||
return addr;
|
||||
}
|
||||
|
||||
Histable *
|
||||
DataObject::convertto (Histable_type type, Histable *)
|
||||
{
|
||||
return type == DOBJECT ? this : NULL;
|
||||
}
|
||||
|
||||
char
|
||||
DataObject::get_offset_mark ()
|
||||
{
|
||||
enum
|
||||
{
|
||||
blocksize = 32
|
||||
};
|
||||
|
||||
if (size == 0 || offset == -1)
|
||||
return '?'; // undefined
|
||||
if (size > blocksize)
|
||||
return '#'; // requires multiple blocks
|
||||
if (size == blocksize && (offset % blocksize == 0))
|
||||
return '<'; // fits block entirely
|
||||
if (offset % blocksize == 0)
|
||||
return '/'; // starts block
|
||||
if ((offset + size) % blocksize == 0)
|
||||
return '\\'; // closes block
|
||||
if (offset / blocksize == ((offset + size) / blocksize))
|
||||
return '|'; // inside block
|
||||
return 'X'; // crosses blocks unnecessarily
|
||||
}
|
||||
|
||||
char *
|
||||
DataObject::get_offset_name ()
|
||||
{
|
||||
char *offset_name;
|
||||
if (parent && parent->get_typename ()) // element
|
||||
offset_name = dbe_sprintf (GTXT ("%c%+6lld .{%s %s}"),
|
||||
get_offset_mark (), (long long) offset,
|
||||
_typename ? _typename : GTXT ("NO_TYPE"),
|
||||
_instname ? _instname : GTXT ("-")); // "NO_NAME"
|
||||
else if ((offset != -1) && (offset > 0)) // filler
|
||||
offset_name = dbe_sprintf (GTXT ("%c%+6lld %s"), get_offset_mark (),
|
||||
(long long) offset, get_name ());
|
||||
else if (parent) // Scalar/Unknown element
|
||||
offset_name = dbe_sprintf (GTXT (" .%s"), get_unannotated_name ());
|
||||
else // aggregate
|
||||
offset_name = dbe_strdup (get_name ());
|
||||
return offset_name;
|
||||
}
|
||||
|
||||
void
|
||||
DataObject::set_dobjname (char *type_name, char *inst_name)
|
||||
{
|
||||
_unannotated_name = _typename = _instname = NULL;
|
||||
if (inst_name)
|
||||
_instname = dbe_strdup (inst_name);
|
||||
|
||||
char *buf;
|
||||
if (parent == dbeSession->get_Scalars_DataObject ())
|
||||
{
|
||||
if (type_name)
|
||||
_typename = dbe_strdup (type_name);
|
||||
_unannotated_name = dbe_sprintf (NTXT ("{%s %s}"), type_name,
|
||||
inst_name ? inst_name : NTXT ("-"));
|
||||
buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name);
|
||||
}
|
||||
else if (parent == dbeSession->get_Unknown_DataObject ())
|
||||
{
|
||||
_unannotated_name = dbe_strdup (type_name);
|
||||
buf = dbe_sprintf (NTXT ("%s.%s"), parent->get_name (), _unannotated_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type_name)
|
||||
_typename = dbe_strdup (type_name);
|
||||
if (parent && parent->get_typename ())
|
||||
buf = dbe_sprintf (NTXT ("%s.{%s %s}"),
|
||||
parent->get_name () ? parent->get_name () : NTXT ("ORPHAN"),
|
||||
type_name ? type_name : NTXT ("NO_TYPE"),
|
||||
inst_name ? inst_name : NTXT ("-")); // "NO_NAME"
|
||||
else
|
||||
buf = dbe_sprintf (NTXT ("{%s %s}"),
|
||||
type_name ? type_name : NTXT ("NO_TYPE"),
|
||||
inst_name ? inst_name : NTXT ("-")); // "NO_NAME"
|
||||
}
|
||||
name = buf;
|
||||
dbeSession->dobj_updateHT (this);
|
||||
}
|
||||
|
||||
void
|
||||
DataObject::set_name (char *string)
|
||||
{
|
||||
name = dbe_strdup (string);
|
||||
dbeSession->dobj_updateHT (this);
|
||||
}
|
||||
|
||||
DbeEA *
|
||||
DataObject::find_dbeEA (Vaddr EA)
|
||||
{
|
||||
DbeEA *dbeEA;
|
||||
int left = 0;
|
||||
int right = EAs->size () - 1;
|
||||
while (left <= right)
|
||||
{
|
||||
int index = (left + right) / 2;
|
||||
dbeEA = EAs->fetch (index);
|
||||
if (EA < dbeEA->eaddr)
|
||||
right = index - 1;
|
||||
else if (EA > dbeEA->eaddr)
|
||||
left = index + 1;
|
||||
else
|
||||
return dbeEA;
|
||||
}
|
||||
|
||||
// None found, create a new one
|
||||
dbeEA = new DbeEA (this, EA);
|
||||
EAs->insert (left, dbeEA);
|
||||
return dbeEA;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue