Add first results
This commit is contained in:
parent
122c69b0ca
commit
2e656c44d9
4 changed files with 132 additions and 3 deletions
|
@ -15,6 +15,8 @@ Under supervision of Francesco Zappa-Nardelli\\
|
||||||
\usepackage{mathtools}
|
\usepackage{mathtools}
|
||||||
\usepackage{indentfirst}
|
\usepackage{indentfirst}
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{makecell}
|
||||||
|
\usepackage{booktabs}
|
||||||
%\usepackage[backend=biber,style=alphabetic]{biblatex}
|
%\usepackage[backend=biber,style=alphabetic]{biblatex}
|
||||||
\usepackage[backend=biber]{biblatex}
|
\usepackage[backend=biber]{biblatex}
|
||||||
|
|
||||||
|
@ -26,6 +28,11 @@ Under supervision of Francesco Zappa-Nardelli\\
|
||||||
|
|
||||||
\addbibresource{../shared/report.bib}
|
\addbibresource{../shared/report.bib}
|
||||||
|
|
||||||
|
\renewcommand\theadalign{c}
|
||||||
|
\renewcommand\theadfont{\bfseries}
|
||||||
|
%\renewcommand\theadgape{\Gape[4pt]}
|
||||||
|
%\renewcommand\cellgape{\Gape[4pt]}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
@ -227,7 +234,7 @@ the relevant FDE from its start, until it finds the row it was seeking.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{DWARF semantics}
|
\section{DWARF semantics}\label{sec:semantics}
|
||||||
|
|
||||||
We will now define semantics covering most of the operations used for
|
We will now define semantics covering most of the operations used for
|
||||||
CFI\footnote{To be defined elsewhere in the report} described in the DWARF
|
CFI\footnote{To be defined elsewhere in the report} described in the DWARF
|
||||||
|
@ -507,13 +514,91 @@ and $\semR{\bullet}$ is defined as
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Stack unwinding data compilation}
|
\section{Stack unwinding data compilation}
|
||||||
|
|
||||||
|
The tentative approach that was chosen to try to get better unwinding speeds at
|
||||||
|
a reasonable space loss was to compile directly the \ehframe{} into native
|
||||||
|
machine code on the x86\_64 platform.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\subsection{Compilation: \ehelfs}
|
\subsection{Compilation: \ehelfs}
|
||||||
\todo{}
|
|
||||||
|
The rough idea of the compilation is to produce, out of the \ehframe{} section
|
||||||
|
of a binary, C code that resembles the code shown in the DWARF semantics from
|
||||||
|
Section~\ref{sec:semantics} above. This C code is then compiled by GCC,
|
||||||
|
providing for free all the optimisation passes of a modern compiler. This code
|
||||||
|
is compiled as a shared library, containing a single function, taking as
|
||||||
|
argument an instruction pointer and a memory context (\ie{} the value of the
|
||||||
|
various machine registers). An optionally enabled parameter can be used to pass
|
||||||
|
a function pointer to a dereferencing function, that conceptually does what the
|
||||||
|
dereferencing \lstc{*} operator on a pointer, and is used to unwind a process
|
||||||
|
that is not the currently running process, and thus not sharing the same
|
||||||
|
address space. A call to this function returns a fresh memory context,
|
||||||
|
containing the values the registers hold after unwinding this frame.
|
||||||
|
|
||||||
|
This generated data is stored in separate shared object files, which we call
|
||||||
|
\ehelfs. It would have been possible to alter the original ELF file to embed
|
||||||
|
this data as a new section, but it getting it to be executed just as any
|
||||||
|
portion of the \lstc{.text} section would probably have been painful, and
|
||||||
|
keeping it separated during the experimental phase is quite convenient. It is
|
||||||
|
possible to have multiple versions of \ehelfs{} files in parallel, with various
|
||||||
|
options turned on or off, and it doesn't require to alter the base system by
|
||||||
|
editing \eg{} \texttt{/usr/lib/libc-*.so}. Instead, when the \ehelf{} data is
|
||||||
|
required, those files can simply be \lstc{dlopen}'d.
|
||||||
|
|
||||||
|
\todo{More details here? Is it necessary or just too technical?}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\subsection{First results}
|
\subsection{First results}
|
||||||
\todo{}
|
|
||||||
|
Without any particular care to efficiency or compactness, it is already
|
||||||
|
possible to produce a compiled version very close to the one described in
|
||||||
|
Section~\ref{sec:semantics}. Although the unwinding speed cannot yet be
|
||||||
|
actually benchmarked, it is already possible to write in a few hundreds of line
|
||||||
|
of C a simple stack walker printing the functions traversed. It already works
|
||||||
|
without any problem on the easily tested cases, since corner cases are mostly
|
||||||
|
found in standard and highly optimal libraries, and it is not that easy to get
|
||||||
|
the program to stop and print a stack trace from within a system library
|
||||||
|
without using a debugger.
|
||||||
|
|
||||||
|
The major drawback of this approach, without any particular care taken, is the
|
||||||
|
space waste.
|
||||||
|
|
||||||
|
\begin{table}[h]
|
||||||
|
\begin{tabular}{r r r r r r}
|
||||||
|
\toprule
|
||||||
|
\thead{Shared object} & \thead{Original \\ program size}
|
||||||
|
& \thead{Original \\ \lstc{.eh\_frame}}
|
||||||
|
& \thead{Generated \\ \ehelf{} \lstc{.text}}
|
||||||
|
& \thead{\% of original \\ program size}
|
||||||
|
& \thead{Growth \\ factor} \\
|
||||||
|
\midrule
|
||||||
|
libc-2.27.so & 1.4 MiB & 130.1 KiB & 914.9 KiB & 63.92 & 7.03 \\
|
||||||
|
libpthread-2.27.so & 58.1 KiB & 11.6 KiB & 70.5 KiB & 121.48 & 6.09 \\
|
||||||
|
ld-2.27.so & 129.6 KiB & 9.6 KiB & 71.7 KiB & 55.34 & 7.44 \\
|
||||||
|
hackbench & 2.9 KiB & 568.0 B & 2.1 KiB & 74.78 & 3.97 \\
|
||||||
|
Total & 1.6 MiB & 151.8 KiB & 1.0 MiB & 65.32 & 6.98 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
|
||||||
|
\caption{Basic \ehelfs{} space usage}\label{table:basic_eh_elf_space}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
The space taken by those tentative \ehelfs{} is analyzed in
|
||||||
|
Table~\ref{table:basic_eh_elf_space} for \prog{hackbench}, a small program
|
||||||
|
introduced later in Section~\qtodo{Add a reference}, and the libraries on which
|
||||||
|
it depends.
|
||||||
|
|
||||||
|
The first column only includes the sizes of the ELF sections \lstc{.text} (the
|
||||||
|
program itself) and \lstc{.rodata}, the read-only data (such as static strings,
|
||||||
|
etc.). Only the weight of the \lstc{.text} section of the generated \ehelfs{}
|
||||||
|
is considered, because it is self-consistent (few data or none is stored in
|
||||||
|
\lstc{.rodata}), and the other sections could be removed if the \ehelfs{}
|
||||||
|
\lstc{.text} was somehow embedded in the original shared object.
|
||||||
|
|
||||||
|
This first tentative version of \ehelfs{} is roughly 7 times heavier than the
|
||||||
|
original \lstc{.eh_frame}, and represents a far too significant proportion of
|
||||||
|
the original program size.
|
||||||
|
|
||||||
|
\todo{more in-depth analysis?}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\subsection{Space optimization}
|
\subsection{Space optimization}
|
||||||
|
|
8
report/tables/compare_sizes_old
Normal file
8
report/tables/compare_sizes_old
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
\begin{tabular}{r r r r r r r }
|
||||||
|
\leftcell{Shared object} & \leftcell{Orig prog size} & \leftcell{Orig eh_frame} & \leftcell{Gen eh_elf .text} & \leftcell{+ .rodata} & \leftcell{% of prog size} & \leftcell{Growth} \\
|
||||||
|
libc-2.27.so & 1.4 MiB & 130.1 KiB & 914.9 KiB & 914.9 KiB & 63.92 & 7.03 \\
|
||||||
|
libpthread-2.27.so & 58.1 KiB & 11.6 KiB & 70.5 KiB & 70.5 KiB & 121.48 & 6.09 \\
|
||||||
|
ld-2.27.so & 129.6 KiB & 9.6 KiB & 71.7 KiB & 71.7 KiB & 55.34 & 7.44 \\
|
||||||
|
hackbench & 2.9 KiB & 568.0 B & 2.1 KiB & 2.2 KiB & 74.78 & 3.97 \\
|
||||||
|
Total & 1.6 MiB & 151.8 KiB & 1.0 MiB & 1.0 MiB & 65.32 & 6.98 \\
|
||||||
|
\end{tabular}
|
6
report/tables/compare_sizes_old.cmpsz
Normal file
6
report/tables/compare_sizes_old.cmpsz
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Shared object Orig prog size Orig eh_frame Gen eh_elf .text + .rodata % of prog size Growth
|
||||||
|
libc-2.27.so 1.4 MiB 130.1 KiB 914.9 KiB 914.9 KiB 63.92 7.03
|
||||||
|
libpthread-2.27.so 58.1 KiB 11.6 KiB 70.5 KiB 70.5 KiB 121.48 6.09
|
||||||
|
ld-2.27.so 129.6 KiB 9.6 KiB 71.7 KiB 71.7 KiB 55.34 7.44
|
||||||
|
hackbench 2.9 KiB 568.0 B 2.1 KiB 2.2 KiB 74.78 3.97
|
||||||
|
Total 1.6 MiB 151.8 KiB 1.0 MiB 1.0 MiB 65.32 6.98
|
30
report/tables/to_latex.py
Normal file
30
report/tables/to_latex.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def split_line(line):
|
||||||
|
spl = line.strip().split(' ')
|
||||||
|
cleaned = map(lambda x: x.strip(), (filter(lambda x: x.strip(), spl)))
|
||||||
|
return list(cleaned)
|
||||||
|
|
||||||
|
|
||||||
|
def latexify_row(row):
|
||||||
|
return ((' & '.join(row)) + r' \\')
|
||||||
|
|
||||||
|
|
||||||
|
lines = sys.stdin.readlines()
|
||||||
|
table = list(map(split_line, lines))
|
||||||
|
|
||||||
|
cols = len(table[0])
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
|
||||||
|
print('\\begin{tabular}{' + ('r ' * cols) + '}')
|
||||||
|
|
||||||
|
## Head row
|
||||||
|
print('\t'
|
||||||
|
+ latexify_row(list(map(lambda x: r'\leftcell{' + x + r'}', table[0]))))
|
||||||
|
|
||||||
|
for row in table[1:]:
|
||||||
|
print('\t' + latexify_row(row))
|
||||||
|
|
||||||
|
print(r'\end{tabular}')
|
Loading…
Reference in a new issue