@@ 376,12 376,66 @@ CallerIs()
(gdb) source caller_is.py
(gdb) break foo if $caller_is ("bar")
\end{lstlisting}
- \end{block}
+ \end{block}
\item{Internal variables and functions on \gdb{} start with \verb|$|.}
\item{\texttt{caller\_is.py} is part of upstream \gdb{}.}
\end{itemize}
\end{frame}
+\begin{frame}[fragile]
+ \frametitle{\python{}$^5$}
+ \begin{itemize}
+ \item{Problem: \texttt{std::string s = "Hello, World";}}
+ \begin{block}{Printing ``s'' inside \gdb{}}
+ \tiny
+ \begin{lstlisting}[language=sh,showstringspaces=false]
+(gdb) print s
+$1 = {static npos = <optimized out>,
+ _M_dataplus = {<std::allocator<char>> =
+ {<__gnu_cxx::new_allocator<char>> = {<No data fields>},
+ <No data fields>}, _M_p = 0x602028 ``Hello, World''}}
+ \end{lstlisting}
+ \end{block}
+ \pause
+ \item{\gdb{} knows about \verb|_M_dataplus -> _M_p|. How to tell that this is the only field you are interested in?}
+ \pause
+ \item{Python!}
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{\python{}$^6$}
+ \begin{block}{print-std-string.py}
+ \tiny
+ \begin{lstlisting}[language=python,showstringspaces=false]
+class StdStringPrinter:
+ "Print a std::basic_string of some kind"
+
+ def __init__(self, typename, val):
+ self.val = val
+
+ def to_string(self):
+ # ... snip ...
+
+ # Calculate the length of the string so that to_string returns
+ # the string according to length, not according to first null
+ # encountered.
+ (*\textcolor{red}{ptr = self.val ['\_M\_dataplus']['\_M\_p']}*)
+ realtype = type.unqualified ().strip_typedefs ()
+ reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+ header = ptr.cast(reptype) - 1
+ len = header.dereference ()['_M_length']
+ if hasattr(ptr, "lazy_string"):
+ return ptr.lazy_string (length = len)
+ return ptr.string (length = len)
+ \end{lstlisting}
+ \end{block}
+ \begin{itemize}
+ \pause
+ \item{Present on \verb|libstdcxx| upstream}
+ \end{itemize}
+\end{frame}
+
\section{Conclusion}
\begin{frame}[fragile]
\frametitle{Conclusion}