Draft wamr modifications + host program structure sections
This commit is contained in:
@@ -4,8 +4,6 @@
|
||||
|
||||
\begin{document}
|
||||
|
||||
\todo[inline]{Inconsistent usage of the words benchmark and experiment}
|
||||
|
||||
\chapter{Introduction}\label{ch:introduction}
|
||||
|
||||
As semiconductor node sizes shrink, transient hardware faults pose a growing risk to computing systems, especially in environments where reliability is critical.
|
||||
|
||||
@@ -6,115 +6,4 @@
|
||||
|
||||
\chapter{Methodology}\label{ch:methodology}
|
||||
|
||||
\begin{itemize}
|
||||
\item General: How do the experiments answer the research questions?
|
||||
\item Specific FARM-model variant for this research questions, fault model.
|
||||
\end{itemize}
|
||||
|
||||
\section{Experimental Design}\label{sec:experimentaldesign}
|
||||
|
||||
This thesis evaluates the effect of execution mode and software hardening on program behavior under injected faults.
|
||||
Each selected benchmark is evaluated under native execution, \Gls{aot} compiled \Gls{wasm} execution, and interpreted \Gls{wasm} execution.
|
||||
Comparisons are performed between corresponding benchmark variants using the same inputs and expected results.
|
||||
|
||||
The execution mode is the factor that influences the experiment the most.
|
||||
For benchmarks with hardened implementations, the hardening techniques are additional influences.\todo{Open if I get to that, but preferably at least CoRed}
|
||||
The experiment outcomes describe if execution completes successfully with the expected result, detects an error, or terminates for other reasons, like timeouts.
|
||||
|
||||
The experiments are designed to determine what changes when adding \Gls{wamr} to an unhardened or hardened benchmark, and specifically, what changes between \Gls{wamr}'s \Gls{aot} compiled and interpreted running modes.
|
||||
|
||||
\section{Applying the FARM-Model}\label{sec:applyingthefarmmodel}
|
||||
|
||||
With \Gls{farm}~\autocite{arlatFaultInjectionDependability1990}, Arlat et al.\ introduced a model for applications of \Gls{fi} to clearly specify the faults introduced, the conditions under which the system works, and the interpretation of the observed outcomes.
|
||||
\Gls{farm} structures its specification into four sets: faults (\(F\)) describe the disturbances introduced into the system, activations (\(A\)) specify the execution conditions of the system, readouts (\(R\)) are the outcomes collected from experiment execution, and measures (\(M\)) finally derive quantities from the observations to evaluate the system's behavior.
|
||||
|
||||
In this thesis, \Gls{farm} provides the framework to specify and compare the native, \Gls{aot}, and interpreted experiment variants and interpret the experiment results.
|
||||
|
||||
\subsection{Faults}\label{ssec:farmfaults}
|
||||
|
||||
The \Gls{fi} campaigns inject single-bit faults into the machine state exposed by the \Gls{bochs} simulator.
|
||||
Fault locations are separated into memory, register, and instruction-pointer categories that are evaluated separately.
|
||||
The injection locations and times are determined from a fault-free execution (\gls{goldenrun}) of the selected benchmark.
|
||||
The evaluated fault space is thus specific to the executed benchmark, its inputs, the execution mode and the chosen traced region.
|
||||
|
||||
\todo[inline]{Write about comparability of results, equivalence classes etc.}
|
||||
|
||||
The fault model excludes multiple simultaneous faults or multi-bit faults.
|
||||
After an injection, the program execution continues without intervention until an experiment outcome is reached.
|
||||
|
||||
\subsection{Activations}\label{ssec:farmactivations}
|
||||
|
||||
\todo[inline]{This reads more like a list of notes}
|
||||
|
||||
Each benchmark defines a traced region through explicit start and stop markers.
|
||||
The \gls{goldenrun} records a fault-free execution trajectory of that region and provides the simulator starting state for each injection.
|
||||
Additionally, the \gls{goldenrun} determines the injection locations.
|
||||
The trace boundary alone determines which program activity contributes to the experiment.
|
||||
All benchmarks use equivalent boundaries on the source-level: state initialization and \Gls{wamr} runtime initialization lie outside of this boundary.
|
||||
In contrast to natively executed benchmark variants, the \Gls{aot} or interpreted variants may call \Gls{wamr} runtime code within the boundary.
|
||||
|
||||
The effects of injected faults are later evaluated through the readouts described in \autoref{ssec:farmreadouts}.
|
||||
|
||||
\subsection{Pruning}\label{ssec:farmpruning}
|
||||
|
||||
Instead of injecting a single-bit fault at every possible location derived from the \gls{goldenrun}, the fault space is pruned before the campaign is run.
|
||||
Equivalence classes of faults leading to the same outcome are identified and represented by a single \gls{pilot} experiment, so the outcomes of all experiments that belong to an equivalence class can be determined by performing injections on only its \gls{pilot}.
|
||||
Because injections into different bits can cause different outcomes, only injections into the same bit can belong to a single equivalence class, additionally, there must not be intervening accesses into a memory location within a single equivalence class.
|
||||
|
||||
For example, if a single byte at the memory location \(m\) is written by the program under test at time \(t_{0}\) and read back (without \(m\) being accessed in between) at time \(t_{1}\) with \(t_{1} > t_{0}\), each injection into bit \(b\) of \(m\) during the time interval \([t_{0}, t_{1}]\) would cause the same outcome (multiple simultaneous faults are outside the scope of this thesis).
|
||||
Instead of performing \(t_{1} - t_{0} + 1\) individual injections into bit \(b\) of \(m\), the pruner marks \([t_{0}, t_{1}]\) as an equivalence class, represented by a single injection into bit \(b\) of \(m\) at time \(t_{1}\) (or any other \(t\in [t_{0}, t_{1}]\)).
|
||||
|
||||
This example is a case of \textquote{def/use pruning}, as introduced by Smith et al.~\autocite{smithMethodDetermineEquivalent1995} and Güthoff and Sieh~\autocite{guthoffCombiningSoftwareimplementedSimulationbased1995}.
|
||||
|
||||
\subsection{Readouts}\label{ssec:farmreadouts}
|
||||
|
||||
Outcomes are classified by using explicit markers on the source level and listening for simulator events (possible outcomes are listed in \autoref{tab:experimentoutcomes}).
|
||||
The positive and negative markers report the result of the benchmark's success condition outside the trace boundary, the detected marker records a fault that manifested to an error but was detected by the program.
|
||||
In \Gls{wamr} benchmark variants, \Gls{wamr}'s exception handler reports an explicit outcome as well.
|
||||
Traps, timeouts and invalid memory accesses are reported by the simulator without the need for source-level instrumentation.
|
||||
|
||||
\todo[inline]{Table is duplicated with background chapter on FAIL}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{\textwidth}{lX}
|
||||
Marker Type & Description \\
|
||||
\midrule
|
||||
\code{OK\_MARKER} & The experiment's success condition passed \\
|
||||
\code{FAIL\_MARKER} & The experiment's success condition did not pass \\
|
||||
\code{DETECTED\_MARKER} & The experiment signalled an error through some detection mechanism \\
|
||||
\code{TRAP} & The experiment did not complete because the CPU threw an exception \\
|
||||
\code{TIMEOUT} & The experiment did not complete in the time limit \\
|
||||
\code{ACCESS\_OUTERSPACE} & The program accessed an address outside the program's address space \\
|
||||
\code{WRITE\_TEXTSEGMENT} & The program wrote to an address located inside the program's text segment \\
|
||||
\code{GROUP1\_MARKER} & An \Gls{aot} or interpreted variant reached \Gls{wamr}'s internal exception handler \\
|
||||
\end{tabularx}
|
||||
\caption{Outcomes detected by \Gls{fail}'s experiment runner.}\label{tab:experimentoutcomes}
|
||||
\end{table}
|
||||
|
||||
\subsection{Measures}\label{ssec:farmmeasures}
|
||||
|
||||
To quantify the experiment outcomes, the evaluation must reconstruct weighted outcome totals using the \gls{pilot} outcomes with the corresponding sizes of the equivalence classes' fault spaces.
|
||||
The intuitive reason for this is, as Schirmeier et al.\ state in~\autocite{schirmeierAvoidingPitfallsFaultInjection2015}, that \textquote{the longer data lives in a memory cell, the more probable a soft error will affect it}.
|
||||
|
||||
Continuing the example from \autoref{ssec:farmpruning}, an outcome observed for an injection into a particular bit of a memory location \(m\) represents \(t_{1} - t_{0} + 1\) possible injection times within the equivalence class.
|
||||
Its contribution to the weighted total for that outcome is therefore
|
||||
\[
|
||||
w = t_{1} - t_{0} + 1.
|
||||
\]
|
||||
The weighting is applied separately to each injected bit because injections into different bits of \(m\) could produce different outcomes.
|
||||
For example, if \(m\) is one byte wide and injections into three of its eight bits produce \code{FAIL\_MARKER}, this interval contributes \(3w\) to the weighted \code{FAIL\_MARKER} total (and \(8w\) to the total weight across all outcomes).
|
||||
|
||||
Generally, if \(C\) is the set of equivalence classes for a benchmark variant and outcome, \(s_{c}\) and \(e_{c}\) are the start and end times of each class \(c\in C\), \(B_{c}\) is the set of injected bits, and \(o_{c,b}\) is the outcome corresponding to the injection into bit \(b\in B_{c}\), then the weighted total for an outcome \(o\) is
|
||||
\[
|
||||
W_o = \sum\limits_{c \in C} \sum\limits_{b \in B_c} (e_c - s_c + 1)\,\mathbf{1}\{o_{c,b} = o\},
|
||||
\]
|
||||
where \(\mathbf{1}\{o_{c,b} = o\}\) is the indicator function, which equals one if the recorded outcome matches \(o\), and zero otherwise.\footnote{%
|
||||
In terms of \Gls{fail}'s database, this corresponds to summing \code{t.time2 - t.time1 + 1} after joining the trace intervals to their \gls{pilot} results and grouping them by outcome.
|
||||
The join accounts for the individual injected bits, so no additional factor for the bit width is required in the sum.
|
||||
}
|
||||
|
||||
Weighted outcome totals are reported separately for each fault category, execution mode and injection location (memory, registers or instruction-pointer).
|
||||
Outcome shares describe the composition of each variant's fault space, while absolute totals show differences in vulnerability caused by executaion duration and memory footprint.
|
||||
|
||||
\end{document}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Experimental Design}\label{sec:experimentaldesign}
|
||||
|
||||
This thesis evaluates the effect of execution mode and software hardening on program behavior under injected faults.
|
||||
Each selected benchmark is evaluated under native execution, \Gls{aot} compiled \Gls{wasm} execution, and interpreted \Gls{wasm} execution.
|
||||
Comparisons are performed between corresponding benchmark variants using the same inputs and expected results.
|
||||
|
||||
The execution mode is the factor that influences the experiment the most.
|
||||
For benchmarks with hardened implementations, the hardening techniques are additional influences.\todo{Open if I get to that, but preferably at least CoRed}
|
||||
The experiment outcomes describe if execution completes successfully with the expected result, detects an error, or terminates for other reasons, like timeouts.
|
||||
|
||||
The experiments are designed to determine what changes when adding \Gls{wamr} to an unhardened or hardened benchmark, and specifically, what changes between \Gls{wamr}'s \Gls{aot} compiled and interpreted running modes.
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,101 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Applying the FARM-Model}\label{sec:applyingthefarmmodel}
|
||||
|
||||
With \Gls{farm}~\autocite{arlatFaultInjectionDependability1990}, Arlat et al.\ introduced a model for applications of \Gls{fi} to clearly specify the faults introduced, the conditions under which the system works, and the interpretation of the observed outcomes.
|
||||
\Gls{farm} structures its specification into four sets: faults (\(F\)) describe the disturbances introduced into the system, activations (\(A\)) specify the execution conditions of the system, readouts (\(R\)) are the outcomes collected from experiment execution, and measures (\(M\)) finally derive quantities from the observations to evaluate the system's behavior.
|
||||
|
||||
In this thesis, \Gls{farm} provides the framework to specify and compare the native, \Gls{aot}, and interpreted experiment variants and interpret the experiment results.
|
||||
|
||||
\subsection{Faults}\label{ssec:farmfaults}
|
||||
|
||||
The \Gls{fi} campaigns inject single-bit faults into the machine state exposed by the \Gls{bochs} simulator.
|
||||
Fault locations are separated into memory, register, and instruction-pointer categories that are evaluated separately.
|
||||
The injection locations and times are determined from a fault-free execution (\gls{goldenrun}) of the selected benchmark.
|
||||
The evaluated fault space is thus specific to the executed benchmark, its inputs, the execution mode and the chosen traced region.
|
||||
|
||||
\todo[inline]{Write about comparability of results, equivalence classes etc.}
|
||||
|
||||
The fault model excludes multiple simultaneous faults or multi-bit faults.
|
||||
After an injection, the program execution continues without intervention until an experiment outcome is reached.
|
||||
|
||||
\subsection{Activations}\label{ssec:farmactivations}
|
||||
|
||||
\todo[inline]{This reads more like a list of notes}
|
||||
|
||||
Each benchmark defines a traced region through explicit start and stop markers.
|
||||
The \gls{goldenrun} records a fault-free execution trajectory of that region and provides the simulator starting state for each injection.
|
||||
Additionally, the \gls{goldenrun} determines the injection locations.
|
||||
The trace boundary alone determines which program activity contributes to the experiment.
|
||||
All benchmarks use equivalent boundaries on the source-level: state initialization and \Gls{wamr} runtime initialization lie outside of this boundary.
|
||||
In contrast to natively executed benchmark variants, the \Gls{aot} or interpreted variants may call \Gls{wamr} runtime code within the boundary.
|
||||
|
||||
The effects of injected faults are later evaluated through the readouts described in \autoref{ssec:farmreadouts}.
|
||||
|
||||
\subsection{Pruning}\label{ssec:farmpruning}
|
||||
|
||||
Instead of injecting a single-bit fault at every possible location derived from the \gls{goldenrun}, the fault space is pruned before the campaign is run.
|
||||
Equivalence classes of faults leading to the same outcome are identified and represented by a single \gls{pilot} experiment, so the outcomes of all experiments that belong to an equivalence class can be determined by performing injections on only its \gls{pilot}.
|
||||
Because injections into different bits can cause different outcomes, only injections into the same bit can belong to a single equivalence class, additionally, there must not be intervening accesses into a memory location within a single equivalence class.
|
||||
|
||||
For example, if a single byte at the memory location \(m\) is written by the program under test at time \(t_{0}\) and read back (without \(m\) being accessed in between) at time \(t_{1}\) with \(t_{1} > t_{0}\), each injection into bit \(b\) of \(m\) during the time interval \([t_{0}, t_{1}]\) would cause the same outcome (multiple simultaneous faults are outside the scope of this thesis).
|
||||
Instead of performing \(t_{1} - t_{0} + 1\) individual injections into bit \(b\) of \(m\), the pruner marks \([t_{0}, t_{1}]\) as an equivalence class, represented by a single injection into bit \(b\) of \(m\) at time \(t_{1}\) (or any other \(t\in [t_{0}, t_{1}]\)).
|
||||
|
||||
This example is a case of \textquote{def/use pruning}, as introduced by Smith et al.~\autocite{smithMethodDetermineEquivalent1995} and Güthoff and Sieh~\autocite{guthoffCombiningSoftwareimplementedSimulationbased1995}.
|
||||
|
||||
\subsection{Readouts}\label{ssec:farmreadouts}
|
||||
|
||||
Outcomes are classified by using explicit markers on the source level and listening for simulator events (possible outcomes are listed in \autoref{tab:experimentoutcomes}).
|
||||
The positive and negative markers report the result of the benchmark's success condition outside the trace boundary, the detected marker records a fault that manifested to an error but was detected by the program.
|
||||
In \Gls{wamr} benchmark variants, \Gls{wamr}'s exception handler reports an explicit outcome as well.
|
||||
Traps, timeouts and invalid memory accesses are reported by the simulator without the need for source-level instrumentation.
|
||||
|
||||
\todo[inline]{Table is duplicated with background chapter on FAIL}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{\textwidth}{lX}
|
||||
Marker Type & Description \\
|
||||
\midrule
|
||||
\code{OK\_MARKER} & The experiment's success condition passed \\
|
||||
\code{FAIL\_MARKER} & The experiment's success condition did not pass \\
|
||||
\code{DETECTED\_MARKER} & The experiment signalled an error through some detection mechanism \\
|
||||
\code{TRAP} & The experiment did not complete because the CPU threw an exception \\
|
||||
\code{TIMEOUT} & The experiment did not complete in the time limit \\
|
||||
\code{ACCESS\_OUTERSPACE} & The program accessed an address outside the program's address space \\
|
||||
\code{WRITE\_TEXTSEGMENT} & The program wrote to an address located inside the program's text segment \\
|
||||
\code{GROUP1\_MARKER} & An \Gls{aot} or interpreted variant reached \Gls{wamr}'s internal exception handler \\
|
||||
\end{tabularx}
|
||||
\caption{Outcomes detected by \Gls{fail}'s experiment runner.}\label{tab:experimentoutcomes}
|
||||
\end{table}
|
||||
|
||||
\subsection{Measures}\label{ssec:farmmeasures}
|
||||
|
||||
To quantify the experiment outcomes, the evaluation must reconstruct weighted outcome totals using the \gls{pilot} outcomes with the corresponding sizes of the equivalence classes' fault spaces.
|
||||
The intuitive reason for this is, as Schirmeier et al.\ state in~\autocite{schirmeierAvoidingPitfallsFaultInjection2015}, that \textquote{the longer data lives in a memory cell, the more probable a soft error will affect it}.
|
||||
|
||||
Continuing the example from \autoref{ssec:farmpruning}, an outcome observed for an injection into a particular bit of a memory location \(m\) represents \(t_{1} - t_{0} + 1\) possible injection times within the equivalence class.
|
||||
Its contribution to the weighted total for that outcome is therefore
|
||||
\[
|
||||
w = t_{1} - t_{0} + 1.
|
||||
\]
|
||||
The weighting is applied separately to each injected bit because injections into different bits of \(m\) could produce different outcomes.
|
||||
For example, if \(m\) is one byte wide and injections into three of its eight bits produce \code{FAIL\_MARKER}, this interval contributes \(3w\) to the weighted \code{FAIL\_MARKER} total (and \(8w\) to the total weight across all outcomes).
|
||||
|
||||
Generally, if \(C\) is the set of equivalence classes for a benchmark variant and outcome, \(s_{c}\) and \(e_{c}\) are the start and end times of each class \(c\in C\), \(B_{c}\) is the set of injected bits, and \(o_{c,b}\) is the outcome corresponding to the injection into bit \(b\in B_{c}\), then the weighted total for an outcome \(o\) is
|
||||
\[
|
||||
W_o = \sum\limits_{c \in C} \sum\limits_{b \in B_c} (e_c - s_c + 1)\,\mathbf{1}\{o_{c,b} = o\},
|
||||
\]
|
||||
where \(\mathbf{1}\{o_{c,b} = o\}\) is the indicator function, which equals one if the recorded outcome matches \(o\), and zero otherwise.\footnote{%
|
||||
In terms of \Gls{fail}'s database, this corresponds to summing \code{t.time2 - t.time1 + 1} after joining the trace intervals to their \gls{pilot} results and grouping them by outcome.
|
||||
The join accounts for the individual injected bits, so no additional factor for the bit width is required in the sum.
|
||||
}
|
||||
|
||||
Weighted outcome totals are reported separately for each fault category, execution mode and injection location (memory, registers or instruction-pointer).
|
||||
Outcome shares describe the composition of each variant's fault space, while absolute totals show differences in vulnerability caused by executaion duration and memory footprint.
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,9 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Result Filtering}\label{sec:resultfiltering}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,9 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Attributing Fault Observations to Runtime Components}\label{sec:attributiontoruntimecomponents}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,14 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Reproducibility}\label{sec:reproducibility}
|
||||
|
||||
\begin{itemize}
|
||||
\item What is needed to reproduce an experiment (experiment binary, experiment runner config, fail binary for the campaign/experiment definition, filter definitions, query definitions)
|
||||
\item What of this is stored per experiment and what only once?
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
@@ -6,79 +6,4 @@
|
||||
|
||||
\chapter{Experiment Setup}\label{ch:experimentsetup}
|
||||
|
||||
\section{Execution Environment}\label{sec:executionenvironment}
|
||||
|
||||
To keep the experiment setup as simple as possible, experiments are executed in a bare-metal environment without any operating system.
|
||||
This has the advantage of avoiding some sources of possible non-determinism (caused, e.g., by scheduling or interrupts) during fault injection.
|
||||
It also prevents any operating system code from being targeted by the \Gls{fi} framework.
|
||||
While a suitable and correctly configured statically linked real-time operating system inside a controlled, emulated environment is not prone to those issues, running experiments bare-metal excludes this category of possible problems entirely.
|
||||
|
||||
Instead, experiments are cross-compiled to freestanding executables using \code{i386-elf-gcc} with Newlib\footnote{\url[2026-08-12]{https://sourceware.org/newlib/}} libc.
|
||||
To make Newlib work inside a bare-metal environment, certain system calls must be provided by the platform, although not all of them need to be functional\footnote{\url[2026-08-12]{https://sourceware.org/newlib/libgloss.html#Libraries-1}}:
|
||||
\begin{itemize}
|
||||
\item \code{sbrk()} is required for Newlib's \code{malloc()}, \code{calloc()} and \code{realloc()} memory-management functions. Although \Gls{wamr} uses its own memory allocator implementation (see \autoref{sec:wasmhostprogram}), \Gls{wasm} targets may still require a functional \code{sbrk()} if \Gls{wamr}'s \code{snprintf}/\code{vsnprintf} are used, depending on the format string.
|
||||
\item \code{read()}, \code{write()}, \code{close()}, \code{fstat()} and \code{isatty()} stubs are required for \Gls{wamr} targets. Since no filesystem or console exists in the execution environment, they do not need to be functional.
|
||||
\item \code{lseek()} is required for C and \Gls{wamr} targets. A stub suffices for the same reason as above.
|
||||
\item \code{\_exit()}, \code{kill()} and \code{getpid()} are required for \Gls{wamr} targets. Implementations can be omitted, as the execution environment does not use processes.
|
||||
\end{itemize}
|
||||
|
||||
For experiment execution, the executables are packed into Multiboot\footnote{\url[2026-07-13]{https://www.gnu.org/software/grub/manual/multiboot/multiboot.html}}-compatible disk images with GNU GRUB\footnote{\url[2026-08-12]{https://www.gnu.org/software/grub/}} embedded via \code{grub-mkrescue} and executed in \Gls{bochs} via \Gls{fail}.
|
||||
|
||||
\section{\Gls{wamr} Modifications}\label{sec:wamrmodifications}
|
||||
\begin{itemize}
|
||||
\item WAMR baremetal platform
|
||||
\item WAMR exception handler marker?
|
||||
\end{itemize}
|
||||
|
||||
\section{Wasm Host Program}\label{sec:wasmhostprogram}
|
||||
\begin{itemize}
|
||||
\item WAMR setup
|
||||
\item WAMR memory allocators
|
||||
\item Calling \code{FAIL\_MARKER}s (native functions)
|
||||
\end{itemize}
|
||||
|
||||
\section{Experiment Variants}\label{sec:experimenttypes}
|
||||
\begin{itemize}
|
||||
\item C only
|
||||
\item WAMR AOT
|
||||
\item WAMR interpreter
|
||||
\end{itemize}
|
||||
|
||||
\section{Controlling What Gets Injected/Memory Isolation}\label{sec:controllingmemoryisolation}
|
||||
\begin{itemize}
|
||||
\item How can the WAMR allocators be used to control what gets injected? They cannot. --catch-write-textsegment doesn't prevent injection, just writes of the regular program.
|
||||
\item --catch-write-textsegment (does NOT prevent injections into the textsegment!)
|
||||
\item --catch-outerspace
|
||||
\end{itemize}
|
||||
|
||||
\section{Controlling What Data Gets Extracted From The Experiments}
|
||||
\begin{itemize}
|
||||
\item What queries are run?
|
||||
\item How are the equivalence classes expanded?
|
||||
\item What/How is the data filtered (e.g., to exclude WAMR's native call chain)?
|
||||
\end{itemize}
|
||||
|
||||
\section{Missing FAIL\_MARKERs for AOT experiments}
|
||||
\begin{itemize}
|
||||
\item AOT Addressauflösung/Def-Use chain theory
|
||||
\item Somehow caught by --catch-write-textsegment or --catch-outerspace because stuff was linked to .text?
|
||||
\item Optimization theory
|
||||
\begin{itemize}
|
||||
\item Does the target program contain the expected instructions?
|
||||
\item Does FAIL* treat the variables as not live? (volatile, fail\_stop\_trace(sum))
|
||||
\item Trying more complex programs, as -O0 always writes intermediate results to memory
|
||||
\item Swap fail\_marker\_positive and fail\_marker\_negative
|
||||
\end{itemize}
|
||||
\item Does the pruner clear those injections for some reason?
|
||||
\item Does the disassembler not disassemble the .text subsections?
|
||||
\item Is the TracingPlugin broken? (GDB -> No, but FAIL* doesn't trace register accesses)
|
||||
\item Solution: Gap in the .elf symbol space (addresses that are not covered by some symbol). FAIL needs this to disassemble the Wasm AOT code to find the register accesses. FAIL also needs to find this AOT code, so it can't be relocated -> Needs --xip
|
||||
\end{itemize}
|
||||
|
||||
\section{Target Programs}
|
||||
\begin{itemize}
|
||||
\item Toy examples
|
||||
\item TacleBench~\autocite{TACLeBench,seidlerTACLeBenchWasmConverter2026}
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Execution Environment}\label{sec:executionenvironment}
|
||||
|
||||
To keep the experiment setup as simple as possible, experiments are executed in a bare-metal environment without any operating system.
|
||||
This has the advantage of avoiding some sources of possible non-determinism (caused, e.g., by scheduling or interrupts) during fault injection.
|
||||
It also prevents any operating system code from being targeted by the \Gls{fi} framework.
|
||||
While a suitable and correctly configured statically linked real-time operating system inside a controlled, emulated environment is not prone to those issues, running experiments bare-metal excludes this category of possible problems entirely.
|
||||
|
||||
Instead, experiments are cross-compiled to freestanding executables using \code{i386-elf-gcc} with Newlib\footnote{\url[2026-08-12]{https://sourceware.org/newlib/}} libc.
|
||||
To make Newlib work inside a bare-metal environment, certain system calls must be provided by the platform, although not all of them need to be functional\footnote{\url[2026-08-12]{https://sourceware.org/newlib/libgloss.html\#Libraries-1}}:
|
||||
\begin{itemize}
|
||||
\item \code{sbrk()} is required for Newlib's \code{malloc()}, \code{calloc()} and \code{realloc()} memory-management functions. Although \Gls{wamr} uses its own memory allocator implementation (see \autoref{sec:wasmhostprogram}), \Gls{wasm} targets may still require a functional \code{sbrk()} if \Gls{wamr}'s \code{snprintf}/\code{vsnprintf} are used, depending on the format string.
|
||||
\item \code{read()}, \code{write()}, \code{close()}, \code{fstat()} and \code{isatty()} stubs are required for \Gls{wamr} targets. Since no filesystem or console exists in the execution environment, they do not need to be functional.
|
||||
\item \code{lseek()} is required for C and \Gls{wamr} targets. A stub suffices for the same reason as above.
|
||||
\item \code{\_exit()}, \code{kill()} and \code{getpid()} are required for \Gls{wamr} targets. Implementations can be omitted, as the execution environment does not use processes.
|
||||
\end{itemize}
|
||||
|
||||
For experiment execution, the executables are packed into Multiboot\footnote{\url[2026-07-13]{https://www.gnu.org/software/grub/manual/multiboot/multiboot.html}}-compatible disk images with GNU GRUB\footnote{\url[2026-08-12]{https://www.gnu.org/software/grub/}} embedded via \code{grub-mkrescue} and executed in \Gls{bochs} via \Gls{fail}.
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,43 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{\Gls{wamr} Modifications}\label{sec:wamrmodifications}
|
||||
|
||||
The experiments use a slightly modified version of \Gls{wamr} based on release 2.4.4\footnote{\url[2026-09-11]{https://github.com/wasm-micro-runtime/wasm-micro-runtime/releases/tag/WAMR-2.4.4}}.
|
||||
The modifications provide a platform port for the bare-metal execution environment described in \autoref{sec:executionenvironment} and an explicit marker call during runtime exceptions.
|
||||
|
||||
\subsection{Bare-Metal Platform}\label{ssec:wamrbaremetal}
|
||||
|
||||
\Gls{wamr} implements platform-specific details separately from the runtime inside its platform abstractions.
|
||||
The added \code{baremetal} platform only provides the subset of this layer that is required by the experiments.
|
||||
It is selected through \code{WAMR\_BUILD\_PLATFORM=baremetal} and compiled for 32-bit x86 using a freestanding cross-compiler.
|
||||
The build enables the classic interpreter and \Gls{aot} execution, while disabling the fast interpreter, the \Glspl{jit}, and WASI support.
|
||||
The modifications also remove the mandatory CMake thread-library lookup and disables the compiler option \code{-mindirect-branch-register}\todo{Option was disabled because gcc 5.4 didn't support it, now I'm using a newer cross compiler}.
|
||||
|
||||
Since execution is single-threaded and no operating system is present, many platform functions are stubs.
|
||||
Platform initialization and mutex operations report success without performing any work, console output is discarded, and time queries return zero.
|
||||
The system allocation functions \code{os\_malloc} and \code{os\_realloc} return \code{NULL}.
|
||||
Instead, the host initializes \Gls{wamr} with a supplied memory pool or custom allocation callbacks, as described later in \autoref{sssec:wamrmemoryallocation}.
|
||||
|
||||
\Gls{aot} experiment variants additionally require implementations of \code{os\_mmap} and \code{os\_mremap}, to allocate memory for the loaded module text.
|
||||
The platform provides these using a static \SI{2}{\mega\byte} buffer and a simple bump allocator (allocator with monotonically increasing offset into the reserved memory region).
|
||||
Remapping allocates a new region and copies the old one, without reclaiming any memory.
|
||||
Unmapping does not reclaim memory, and \code{os\_mprotect} reports success without changing access permissions.
|
||||
Thus, these functions only supply storage for the loader without implementing any other virtual-memory or memory protection related functionalities.
|
||||
|
||||
The \code{os\_mmap} buffer can optionally be placed in the linker section \code{.text.wamr\_mmap} by defining \code{WAMR\_MMAP\_IN\_TEXT}.
|
||||
The linker script fences this region with symbols so that faults can be attributed to this address range during \Gls{fail} experiment evaluation.
|
||||
|
||||
\subsection{Runtime Exception Marker}\label{ssec:wamrexceptionmarker}
|
||||
|
||||
To differentiate errors detected by the \Gls{wamr} runtime from other fault outcomes, a \code{fail\_marker\_group1} call is added to the \code{wasm\_set\_exception\_local} handler.
|
||||
Clearing an exception by passing \code{NULL} does not invoke the marker.
|
||||
This exception handler is utilized by both interpreted execution and \Gls{aot} execution, whose \code{aot\_set\_exception} forwards to \code{wasm\_set\_exception}.
|
||||
|
||||
To enable the \code{fail\_marker\_group1} outcome, the marker function symbol has to be registered with \Gls{fail}'s experiment runner.
|
||||
\Gls{fail} then installs a breakpoint listener at this function's address and aborts the injection run if it fires.
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,95 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Workload Program Structure}\label{sec:workloadprogramstructure}
|
||||
|
||||
\subsection{Shared Traced Region}\label{ssec:sharedtracedregion}
|
||||
|
||||
All experiment variants (C, \Gls{aot} and interpreted) share the same traced region that contains the actual benchmarked workload.
|
||||
It is structured into three parts, the benchmark initialization, its execution and the success condition.
|
||||
Initialization and success condition lie outside the traced region (see \autoref{lst:workloadstructure}), so a workload under fault always starts with its intended initial state and its result is always evaluated correctly.
|
||||
|
||||
\begin{codeblock}[label=lst:workloadstructure]{Example of a shared workload.}{C++}
|
||||
\inputminted{cpp}{listings/workloadstructure.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
The \code{EXPORT("fnct")} annotation expands to \code{\_\_attribute\_\_((export\_name("fnct")))}, a directive to the LLVM-based C-to-\Gls{wasm} compiler from the WASI SDK\footnote{\url[2026-09-11]{https://github.com/WebAssembly/wasi-sdk}} that controls the name of the exported \Gls{wasm} module.
|
||||
|
||||
Such a shared workload is then called from a variant-specific host program, as seen in the next two sections.
|
||||
|
||||
\subsection{Native Host}\label{ssec:nativehost}
|
||||
|
||||
The native host for C experiment variants (see \autoref{lst:nativehostprogram}) is the simplest of the two: it just calls the \code{wasm\_module} function described in \autoref{ssec:sharedtracedregion} and does not need to consider any runtime initialization.
|
||||
|
||||
For debugging purposes, the native C variant can also be compiled for Linux instead of \Gls{fail}'s bare-metal environment.
|
||||
The \code{MAIN} and \code{RET} macros expand according to the appropriate entry function signature required by the target platform.
|
||||
|
||||
\begin{codeblock}[label=lst:nativehostprogram]{Native workload host program.}{C++}
|
||||
\inputminted{cpp}{listings/nativehost.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{\Gls{wasm} Host and \Gls{wamr} Setup}\label{ssec:wasmhostandwamrsetup}
|
||||
|
||||
The host program for \Gls{wasm} experiment variants needs to do a lot of additional work compared to the native one, mainly concerning the initialization of the \Gls{wamr} runtime\footnote{Described here: \url[2026-09-11]{https://wasmruntime.com/en/tutorials/wamr\#34-step-4-c-embedding-integration}}.
|
||||
|
||||
\subsubsection{Runtime Initialization and Memory Allocation}\label{sssec:wamrmemoryallocation}
|
||||
|
||||
\Gls{wamr} supports two different allocators for the \Gls{wasm} runtime memory: \code{Alloc\_With\_Pool} and \code{Alloc\_With\_Allocator}.
|
||||
\code{Alloc\_With\_Pool} is the simplest one, as it only requires a memory pool and no custom allocator functions.
|
||||
\code{Alloc\_With\_Allocator} is slightly more involved, as it allows complete control over memory regions and allocation behavior by utilizing custom allocator functions.
|
||||
To use this allocator, \code{malloc}, \code{realloc} and \code{free} need to be implemented.
|
||||
In this thesis, a simple bump allocator is implemented, like the one used by \Gls{wamr} itself, described in \autoref{ssec:wamrbaremetal}
|
||||
|
||||
\begin{codeblock}[label=lst:wamrinit]{\Gls{wamr} initialization.}{C++}
|
||||
\inputminted{cpp}{listings/wamrinitialization.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
The main advantage of the more complex \code{Alloc\_With\_Allocator} shows up when \Gls{wamr} is built with \code{WAMR\_BUILD\_ALLOC\_WITH\_USAGE=1}.
|
||||
This flag modifies the allocator function signatures to accept an additional \code{mem\_alloc\_usage\_t} argument, which can take the values \code{Alloc\_For\_Runtime} or \code{Alloc\_For\_LinearMemory}.
|
||||
Based on this value, memory allocations can be distributed across separate pools for \Gls{wamr} runtime memory and \Gls{wasm} linear memory, allowing a more in-depth experiment evaluation by attributing memory faults to different purposes or filtering faults originating from a specific memory pool entirely.
|
||||
|
||||
How to initialize the runtime with the desired configuration is shown in \autoref{lst:wamrinit}.
|
||||
|
||||
\subsubsection{Native Function Invocations}\label{sssec:wamrnativeinvocations}
|
||||
|
||||
\Gls{fail} markers are realized as breakpoint handlers in \Gls{fail}'s simulator backend, with the breakpoints registered to native marker function invocations.
|
||||
This presents a small problem when markers need to be called from within a workload that has been compiled to \Gls{wasm}, as those function invocations are no longer present as native instructions.
|
||||
|
||||
\begin{codeblock}[label=lst:wamrnativefunctions]{\Gls{wamr} native marker definitions.}{C++}
|
||||
\inputminted{cpp}{listings/wamrnativefunctions.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To circumvent this, \Gls{wamr}'s native function invocation mechanism can be used\footnote{Also described here: \url[2026-09-11]{https://wasmruntime.com/en/tutorials/wamr\#41-complete-example-logging-host-function}}: the breakpoint handlers are registered to native functions that are not compiled to \Gls{wasm} (see \autoref{lst:wamrnativefunctions}) but are registered to the \Gls{wamr} runtime instead (see \autoref{lst:wamrnativefunctionregistration}).
|
||||
|
||||
\begin{codeblock}[label=lst:wamrnativefunctionregistration]{\Gls{wamr} native function registration.}{C++}
|
||||
\inputminted{cpp}{listings/wamrnativefunctionregistration.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
This registration populates a lookup table that maps the native function pointers to their names, so that \Gls{aot} programs can call \Gls{wamr}'s internal \code{aot\_invoke\_native} and interpreted programs can call \code{wasm\_interp\_call\_func\_native} to invoke those functions.
|
||||
This indirection happens implicitly, on the application level no special steps need to be taken, functions can be called by their registered names.
|
||||
|
||||
To be compatible with the native function registration mechanism, functions need to accept the \Gls{wasm} execution environment as an argument (see \autoref{lst:wamrnativefunctions}).
|
||||
|
||||
\subsubsection{\Gls{wasm} Module Instantiation and Execution}\label{sssec:wamrmoduleexecution}
|
||||
|
||||
To load the workload's \Gls{wasm} module and run it, a series of steps need to be executed:
|
||||
\begin{enumerate}
|
||||
\item Load the module (\code{wasm\_runtime\_load})
|
||||
\item Instantiate the module (\code{wasm\_runtime\_instantiate})
|
||||
\item Create a \Gls{wasm} execution environment (\code{wasm\_runtime\_create\_exec\_env})
|
||||
\item Find the exported entry function (\code{wasm\_runtime\_lookup\_function})
|
||||
\item Call the exported entry function (\code{wasm\_runtime\_call\_wasm})
|
||||
\end{enumerate}
|
||||
|
||||
In this thesis, compiled \Gls{wasm} modules are converted to C-style arrays using \code{xxd} and embedded into the program's source text.
|
||||
This way, file access can be avoided and the module is loaded by simply passing a pointer to the correct function.
|
||||
A simplified module call sequence is shown in \autoref{lst:wamrmodulecall}.
|
||||
|
||||
\begin{codeblock}[label=lst:wamrmodulecall]{Calling a \Gls{wasm} module from C.}{C++}
|
||||
\inputminted{cpp}{listings/wamrmodulecall.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,15 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Experiment Variants}\label{sec:experimenttypes}
|
||||
|
||||
\begin{itemize}
|
||||
\item C only
|
||||
\item WAMR AOT
|
||||
\item WAMR interpreter
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,15 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Controlling What Gets Injected/Memory Isolation}\label{sec:controllingmemoryisolation}
|
||||
|
||||
\begin{itemize}
|
||||
\item How can the WAMR allocators be used to control what gets injected? They cannot. --catch-write-textsegment doesn't prevent injection, just writes of the regular program.
|
||||
\item --catch-write-textsegment (does NOT prevent injections into the textsegment!)
|
||||
\item --catch-outerspace
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,15 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Controlling What Data Gets Extracted From The Experiments}
|
||||
|
||||
\begin{itemize}
|
||||
\item What queries are run?
|
||||
\item How are the equivalence classes expanded?
|
||||
\item What/How is the data filtered (e.g., to exclude WAMR's native call chain)?
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,25 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Missing FAIL\_MARKERs for AOT experiments}
|
||||
|
||||
\begin{itemize}
|
||||
\item AOT Addressauflösung/Def-Use chain theory
|
||||
\item Somehow caught by --catch-write-textsegment or --catch-outerspace because stuff was linked to .text?
|
||||
\item Optimization theory
|
||||
\begin{itemize}
|
||||
\item Does the target program contain the expected instructions?
|
||||
\item Does FAIL* treat the variables as not live? (volatile, fail\_stop\_trace(sum))
|
||||
\item Trying more complex programs, as -O0 always writes intermediate results to memory
|
||||
\item Swap fail\_marker\_positive and fail\_marker\_negative
|
||||
\end{itemize}
|
||||
\item Does the pruner clear those injections for some reason?
|
||||
\item Does the disassembler not disassemble the .text subsections?
|
||||
\item Is the TracingPlugin broken? (GDB -> No, but FAIL* doesn't trace register accesses)
|
||||
\item Solution: Gap in the .elf symbol space (addresses that are not covered by some symbol). FAIL needs this to disassemble the Wasm AOT code to find the register accesses. FAIL also needs to find this AOT code, so it can't be relocated -> Needs --xip
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,14 @@
|
||||
%! TeX program = lualatex
|
||||
%! TeX root = ../../thesis.tex
|
||||
\documentclass[../../thesis.tex]{subfiles}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\section{Target Programs}
|
||||
|
||||
\begin{itemize}
|
||||
\item Toy examples
|
||||
\item TacleBench~\autocite{TACLeBench,seidlerTACLeBenchWasmConverter2026}
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Define FAIL* marker symbols
|
||||
void fail_start_trace(void) {}
|
||||
void fail_stop_trace(void) {}
|
||||
void fail_marker_positive(void) {}
|
||||
void fail_marker_negative(void) {}
|
||||
void fail_marker_detected(void) {}
|
||||
|
||||
// Forward declare workload
|
||||
int wasm_module(void);
|
||||
|
||||
// Execute
|
||||
MAIN {
|
||||
int retval = wasm_module();
|
||||
RET(retval);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
static RuntimeInitArgs init_args;
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
// If using Alloc_With_Allocator:
|
||||
init_args.mem_alloc_type = Alloc_With_Allocator;
|
||||
init_args.mem_alloc_option.allocator.malloc_func = (void *)wamr_malloc;
|
||||
init_args.mem_alloc_option.allocator.realloc_func = (void *)wamr_realloc;
|
||||
init_args.mem_alloc_option.allocator.free_func = (void *)wamr_free;
|
||||
|
||||
// If using Alloc_With_Pool instead:
|
||||
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
|
||||
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
|
||||
|
||||
init_args.max_thread_num = 1;
|
||||
if (!wasm_runtime_full_init(&init_args)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Error handling is omitted
|
||||
char error_buf[128];
|
||||
|
||||
wasm_module_t module = wasm_runtime_load(
|
||||
module_array, module_array_length, error_buf, sizeof(error_buf));
|
||||
|
||||
wasm_module_inst_t module_inst = wasm_runtime_instantiate(
|
||||
module, STACK_SIZE, HEAP_SIZE, error_buf, sizeof(error_buf));
|
||||
|
||||
wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(
|
||||
module_inst, STACK_SIZE);
|
||||
|
||||
wasm_function_inst_t func = wasm_runtime_lookup_function(
|
||||
module_inst, "wasm_module");
|
||||
|
||||
// Arguments can be supplied to the function
|
||||
// by passing a pointer to an args buffer.
|
||||
// No arguments are set here, but a single
|
||||
// slot is reserved for the return value.
|
||||
uint32_t argv[1];
|
||||
uint32_t argc = 0;
|
||||
wasm_runtime_call_wasm(exec_env, func, argc, argv);
|
||||
uint32_t retval = argv[0];
|
||||
@@ -0,0 +1,12 @@
|
||||
static NativeSymbol native_symbols[] = {
|
||||
{"fail_start_trace", (void *)host_fail_start_trace, "()", NULL},
|
||||
{"fail_stop_trace", (void *)host_fail_stop_trace, "()", NULL},
|
||||
{"fail_marker_positive", (void *)host_fail_marker_positive, "()", NULL},
|
||||
{"fail_marker_negative", (void *)host_fail_marker_negative, "()", NULL},
|
||||
{"fail_marker_detected", (void *)host_fail_marker_detected, "()", NULL},
|
||||
};
|
||||
|
||||
int count = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
if (!wasm_runtime_register_natives("env", native_symbols, count)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Define FAIL* marker symbols
|
||||
void fail_start_trace(void) {}
|
||||
void fail_stop_trace(void) {}
|
||||
void fail_marker_positive(void) {}
|
||||
void fail_marker_negative(void) {}
|
||||
void fail_marker_detected(void) {}
|
||||
|
||||
// Those functions can be called from within Wasm after registration
|
||||
void host_fail_start_trace(wasm_exec_env_t exec_env) {
|
||||
fail_start_trace();
|
||||
}
|
||||
void host_fail_stop_trace(wasm_exec_env_t exec_env) {
|
||||
fail_stop_trace();
|
||||
}
|
||||
void host_fail_marker_positive(wasm_exec_env_t exec_env) {
|
||||
fail_marker_positive();
|
||||
}
|
||||
void host_fail_marker_negative(wasm_exec_env_t exec_env) {
|
||||
fail_marker_negative();
|
||||
}
|
||||
void host_fail_marker_detected(wasm_exec_env_t exec_env) {
|
||||
fail_marker_detected();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
// Workload initialization
|
||||
int x = 0;
|
||||
|
||||
fail_start_trace();
|
||||
// Workload execution
|
||||
x = x + 1;
|
||||
fail_stop_trace();
|
||||
|
||||
// Success condition
|
||||
if (x == 1) {
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -319,7 +319,7 @@
|
||||
top=1mm,
|
||||
bottom=1mm,
|
||||
right=0mm,
|
||||
left=4.3mm,
|
||||
left=4.6mm,
|
||||
drop shadow=titlebg!50!white,
|
||||
#1 % Extra args, e.g. a label
|
||||
}
|
||||
|
||||
+17
-1
@@ -6,7 +6,10 @@
|
||||
|
||||
\begin{document}
|
||||
|
||||
% TODO: Double check the autofilled Zotero references
|
||||
\todo[inline]{Double check the autofilled Zotero references}
|
||||
\todo[inline]{Inconsistent usage of the words benchmark and experiment}
|
||||
\todo[inline]{Glossary entries are all over the place, some things don't need to be linked}
|
||||
\todo[inline]{Too many footnotes, some are unnecessary}
|
||||
|
||||
\subfile{chapters/01_introduction/01_00_introduction.tex}
|
||||
\cleardoublepage%
|
||||
@@ -22,9 +25,22 @@
|
||||
\cleardoublepage%
|
||||
|
||||
\subfile{chapters/04_methodology/04_00_methodology.tex}
|
||||
\subfile{chapters/04_methodology/04_01_experimental_design.tex}
|
||||
\subfile{chapters/04_methodology/04_02_farm_model.tex}
|
||||
\subfile{chapters/04_methodology/04_03_result_filtering.tex}
|
||||
\subfile{chapters/04_methodology/04_04_attribution.tex}
|
||||
\subfile{chapters/04_methodology/04_05_reproducibility.tex}
|
||||
\cleardoublepage%
|
||||
|
||||
\subfile{chapters/05_experiment_setup/05_00_experiment_setup.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_01_execution_environment.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_02_wamr_modifications.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_03_workload_structure.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_04_experiment_variants.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_05_controlling_injections.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_06_results_filtering.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_07_missing_fail_markers.tex}
|
||||
\subfile{chapters/05_experiment_setup/05_08_target_programs.tex}
|
||||
\cleardoublepage%
|
||||
|
||||
\subfile{chapters/06_results/06_00_results.tex}
|
||||
|
||||
Reference in New Issue
Block a user