Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile.irods_runner.centos7
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ RUN \
rm -rf /var/cache/yum /tmp/*

ADD ICAT.sql /
ADD koutheir-pretty-printers.sh /
ADD keep_alive.sh /keep_alive.sh
RUN chmod +x /keep_alive.sh
ENTRYPOINT ["/keep_alive.sh"]
1 change: 1 addition & 0 deletions Dockerfile.irods_runner.ubuntu16
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ RUN \
rm -rf /var/lib/apt/lists/* /tmp/*

ADD ICAT.sql /
ADD koutheir-pretty-printers.sh /
ADD keep_alive.sh /keep_alive.sh
RUN chmod +x /keep_alive.sh
ENTRYPOINT ["/keep_alive.sh"]
1 change: 1 addition & 0 deletions Dockerfile.irods_runner.ubuntu18
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ RUN \
rm -rf /var/lib/apt/lists/* /tmp/*

ADD ICAT.sql /
ADD koutheir-pretty-printers.sh /
ADD keep_alive.sh /keep_alive.sh
RUN chmod +x /keep_alive.sh
ENTRYPOINT ["/keep_alive.sh"]
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This repository contains tools for the running and troubleshooting of a Docker-c
1. [`valgrind`](#valgrind)
1. [`scan-build`](#scan-build)
1. ( `cppcheck`, ... ?)
1. [Enabling GDB-style pretty printers](#enabling-gdb-style-pretty-printers)
---

## General Setup
Expand Down Expand Up @@ -265,3 +266,51 @@ The clang static analyzer can be used when building iRODS.
cmake -DCLANG_STATIC_ANALYZER=ON -GNinja ..
scan-build ninja
```
---

## Enabling GDB-style pretty printers

Run the provided script to enable debug libraries and pretty printing for the libcxx versions of STL containers.

```
root@399b4ef584a7:~# bash /koutheir-pretty-printers.sh
...
--> Checking out llvm and building debug libraries for cxx and cxxabi.
...
--> Writing debug shared objects.
...
--> Creating /root/.gdbinit for gdb and rr.
...
```
Then, to verify, using this file, `demo.cc`:
```
#include <map>
#include <string>
int main()
{
std::map<std::string,std::string> mymap {
{"key1","value1"}, {"key2","value2"}
};
return 0; // In rr or gdb, place breakpoint here and examine `mymap'
}
```
compile:
```
root@399b4ef584a7:/# /opt/irods-externals/clang6.0-0/bin/clang++ -Wl,-rpath -Wl,/opt/irods-externals/clang-runtime6.0-0/lib -stdlib=libc++ demo.cc -g
```
and in GDB or RR, run the program. After breaking at the `return 0;` statement, look at the **map<string,string>** variable - first using the pretty printers,
and then raw - to observe the difference.
```
root@399b4ef584a7:/# /opt/debug_tools/bin/gdb a.out
(gdb) b <line # of return statement>
(gdb) r
(gdb) p mymap
$1 = std::__1::map (count=2) = {[0] "key1" = "value1", [1] "key2" = "value

(gdb) p /r mymap
$2 = {__tree_ = {__begin_node_ = 0x608010,
__pair1_ = {<std::__1::__compressed_pair_elem<std::__1::__tree_end_node<std::__1::__tree_node_base<void*>*>, 0, false>> = {__value_ = { __left_ = 0x608010}}, <std::__1::__compressed_pair_elem<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, ...
( ... more gobbledygook ...)
<No data fields>}, <No data fields>}}}
```
Fortunately, the pretty printers support the great majority of data structures commonly used in iRODS code (that is: map, list, vector, string, etc.).
169 changes: 169 additions & 0 deletions koutheir-pretty-printers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#!/bin/bash

# ***** While CHECK_* macros are still here, we are still testing :) .

if [ -n "${CHECK_USER-1}" ] ; then # TODO - remove this if clause
[ $(id -u) = 0 ] || { echo "Please run this script as root." >&2; exit 1; }
fi

# -- Configuration Values.

CLANG_VERSION_HINT="6.*"
CMAKE_PREFIX="/opt/irods-externals/cmake"
CLANG_PREFIX="/opt/irods-externals/clang"
CLANG_RUNTIME_PREFIX="/opt/irods-externals/clang-runtime"

declare -A LLVM_TO_KOUTHEIR_VERSION_LOOKUP=(
["6.0.0"]="5ffbf2487bf8da7f08bc1c8650a4396d2ff15403"
)

# -- Process Command Line Options.

eval "set --$(/usr/bin/getopt --longoptions "clang-version-hint:" --options "c:" -- "$@")"
for option in "$@"; do
case $option in
--clang-version-hint|-c) CLANG_VERSION_HINT=$2 ; shift 2 ;;
*) shift; break;;
esac
done

#
# -- Function package_max_version
# To determine the maximum of several versions of a package in iRODS externals
#
package_max_version() ( # deliberate subshell
[ -z "$1" ] && exit
PACKAGE_PREFIX=$1
shopt -s nullglob
if [ -n "$2" ]; then
version_string_pattern="$2"
else
version_string_pattern="[0-9][-.0-9]*"
fi
max=""
paths=( ${PACKAGE_PREFIX}${version_string_pattern} )
[ ${#paths[*]} -gt 0 ] && \
for y in ${paths[*]}; do
max=$(get_max "${y#${PACKAGE_PREFIX}}" "$max")
done
echo "$max"
)

get_max() { # -- get max of two (X,Y,Z) tuples --
local z y=0 gt=""
local IFS=".-" # for splitting version numbers of the form "X[-.]Y..." into (X,Y,...)
read -a z <<<"$2"
for x in ${1}; do [ "${x:-0}" -gt "${z[$((y++))]:-0}" ] && gt=1; done
if [ "$gt" ]; then echo "$1"
else echo "$2"; fi
}

CLANG_VERSION=$(package_max_version $CLANG_PREFIX "$CLANG_VERSION_HINT")

if [ -z "$CLANG_VERSION" ] ; then
echo >&2 "ERROR - no Clang compiler found among installed irods-externals*"
exit 2
fi

LLVM_VERSION=${CLANG_VERSION//[-.]/.}

LIBCXX_PRETTY_PRINTERS_COMMIT=${LLVM_TO_KOUTHEIR_VERSION_LOOKUP[$LLVM_VERSION]}

if [ -z "$LIBCXX_PRETTY_PRINTERS_COMMIT" ]; then
echo >&2 "WARNING - no optimal version of libc++ Pretty-Printers found."
echo >&2 " Using the default branch"
fi

if [ -x /usr/bin/zypper ] ;then
pkgtool=zypper # SuSE
elif [ -x /usr/bin/yum ]; then
pkgtool=yum # CentOS, RHEL
yum install -y epel-release
else
pkgtool=apt # Debian, Ubuntu
apt update
fi

# Need:
# - python so that GDB and RR can load pretty printers
# - git to fetch LLVM source
# - make to build debug libraries

${pkgtool} install -y make git python python3

# Build debug versions of stdc++ lib shared objects.

echo >&2 -e "\n--> Checking out llvm and building debug libraries for cxx and cxxabi.\n"

CMAKE_VERSION=$(package_max_version $CMAKE_PREFIX)
CLANG_PATH=${CLANG_PREFIX}${CLANG_VERSION}
CLANG_RUNTIME_PATH=${CLANG_RUNTIME_PREFIX}${CLANG_VERSION}


if [ ! -d "$CLANG_RUNTIME_PATH" ]; then
echo >&2 "Warning - No clang runtime corresponding to clang '${CLANG_VERSION}'."
echo >&2 " Please install it before running this script."
exit 3
fi

CMAKE_VERSION=$(package_max_version $CMAKE_PREFIX)

#
# Print debug values and quit if requested by CHECK_QUIT != "" - TODO - remove this
#
if [ -n "${CHECK_QUIT}" ] ; then
echo CMAKE_VERSION "($CMAKE_VERSION)"
echo CLANG_PATH "($CLANG_PATH)"
echo CLANG_RUNTIME_PATH "($CLANG_RUNTIME_PATH)"
echo LIBCXX_PRETTY_PRINTERS_COMMIT "($LIBCXX_PRETTY_PRINTERS_COMMIT)"
exit 10
fi

if [ -n "${CMAKE_VERSION}" ]; then
cd ~ ; git clone http://github.com/llvm/llvm-project
cd llvm-project && \
git checkout "llvmorg-${LLVM_VERSION}" && \
mkdir build && \
cd build && \
"${CMAKE_PREFIX}${CMAKE_VERSION}/bin/cmake" \
-G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" ../llvm && \
make -j7 cxx cxxabi
else
echo >&2 "Error - Need at least one irods-externals-cmake* package installed"
exit 4
fi

# -- Backup existing shared objects and copy debug versions in to replace them.

echo >&2 -e "\n--> Writing debug shared objects.\n"
for SHLIB in lib/libc++*.so*; do
for DIR in /opt/irods-externals/clang{,-runtime}${CLANG_VERSION}/; do
[ -f "$DIR/$SHLIB" -o -L "$DIR/$SHLIB" ] && mv "$DIR/$SHLIB"{,.orig}
cp -rp "$SHLIB" "$DIR"/lib/.
done
done

# -- Install & configure pretty-printers

if [ -z "${LIBCXX_PRETTY_PRINTERS_COMMIT}" ]; then
GIT_PPRINTER_CHECKOUT_CMD=":"
else
GIT_PPRINTER_CHECKOUT_CMD="git checkout '${LIBCXX_PRETTY_PRINTERS_COMMIT}'"
fi

echo >&2 -e "\n--> Creating $HOME/.gdbinit for gdb and rr.\n"

cd ~ ; git clone https://github.com/koutheir/libcxx-pretty-printers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we clone this repository into the irods namespace? we do this for most everything else we use...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. Clone away, and I will change the reference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


if cd libcxx-pretty-printers
then
if ! eval "$GIT_PPRINTER_CHECKOUT_CMD" ; then
echo >&2 "Error - Could not find pretty printers repository directory."
exit 5
fi
PP_SRC_DIR=~/libcxx-pretty-printers/src
cp $PP_SRC_DIR/gdbinit ~/.gdbinit && sed -i -e "s@<path.*>@$PP_SRC_DIR@" ~/.gdbinit
else
echo >&2 "Error - Could not find pretty printers repository directory."
exit 6
fi