Compare commits
229 Commits
9ca8e88ec0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
961a2f02c5
|
|||
|
e3be326c42
|
|||
|
1d1ed3581a
|
|||
|
b9ff08db16
|
|||
|
59736fb576
|
|||
|
b10233439f
|
|||
|
4ba417ebdf
|
|||
|
b344c55eee
|
|||
|
797c9512b4
|
|||
|
08c2e9c13d
|
|||
|
30daa8a00c
|
|||
|
b0cb01a7e4
|
|||
|
4b0a4b175b
|
|||
|
f999b01538
|
|||
|
7dec717e03
|
|||
|
f14d4f8d36
|
|||
|
6f3d11128c
|
|||
|
47f3132859
|
|||
|
93d911a09e
|
|||
|
170a4487c1
|
|||
|
c4bcae753b
|
|||
|
8fc755372f
|
|||
|
6042b2a145
|
|||
|
7a3a23b4d6
|
|||
|
454a85043f
|
|||
|
c5c5172f65
|
|||
|
a07cd4913c
|
|||
|
b6355a67f3
|
|||
|
7284849684
|
|||
|
bd6df6b4e9
|
|||
|
9c42618028
|
|||
|
78733403f5
|
|||
|
b1821cabd6
|
|||
|
ac6297643f
|
|||
|
c57ae5fced
|
|||
|
05a4aa18e4
|
|||
|
d7548a19ab
|
|||
|
d1c618443c
|
|||
|
25e10511e1
|
|||
|
ebaf128d92
|
|||
|
d0166f32a6
|
|||
|
a77d0782bf
|
|||
|
928719db7c
|
|||
|
dd87df37c1
|
|||
|
2c43e630f0
|
|||
|
0cb829ccf4
|
|||
|
4bd3a9d7a4
|
|||
|
ca6801edd6
|
|||
|
1e3dfa2504
|
|||
|
30f09a276f
|
|||
|
7846a2f3b6
|
|||
|
8f5e6f35b4
|
|||
|
8ac7cf8a70
|
|||
|
5c874f4cbc
|
|||
|
635a625e7c
|
|||
|
b61ee93a3e
|
|||
|
e6d2e736ff
|
|||
|
a0ac7fa7e9
|
|||
|
612aad911b
|
|||
|
ddbd6fa8d1
|
|||
|
99e8c80dc7
|
|||
|
54ec5ef63e
|
|||
|
494e06bcb1
|
|||
|
67a36aa7f8
|
|||
|
31e8f9d093
|
|||
|
156ce50116
|
|||
|
34d89b23fa
|
|||
|
eefabbd043
|
|||
|
beadbae5bf
|
|||
|
40b8ba078a
|
|||
|
e0624a10f7
|
|||
| 3ebc07bfc8 | |||
| 278eb8c980 | |||
| 0223a49099 | |||
| f4b8c16adb | |||
| a46adf528d | |||
| 38bec04ad8 | |||
| 8a97bb738b | |||
| 61c31e51bd | |||
| 2b46a7d544 | |||
| 8a6ea086d6 | |||
| e115cf05ce | |||
| 28da996299 | |||
| 2e5128db6a | |||
| d805b787ac | |||
| 32cb0460c3 | |||
| 9839d3152c | |||
| 2d20dfe665 | |||
| 59d3c7f824 | |||
| aabbd1311d | |||
| d1eee623fa | |||
| 402ba643dc | |||
| 9dd04e905c | |||
| 5487d44394 | |||
| f2f8d7f89f | |||
| 285dbc77d3 | |||
| 38183cae74 | |||
| b5d9d1ec78 | |||
| 1a4d4b64bf | |||
| b00c63ae42 | |||
| 0007193a4f | |||
| 4dcb71ff00 | |||
| fd65e8b791 | |||
| c05164bf0d | |||
| 7992744ae4 | |||
| 54574e0a88 | |||
| 171fe1703e | |||
| 1681f27afc | |||
| ca6338b351 | |||
| e444ab34df | |||
| 6b5bf117e4 | |||
| 64d6971d4d | |||
| 263bb454f1 | |||
| f4bc1b669a | |||
| 0a093c807f | |||
| 921b18cc7a | |||
| e09e3a0f9d | |||
| 63604d39c8 | |||
| 19ed8dd5a2 | |||
| 624f4fb4b3 | |||
| 19c9559cc0 | |||
| ec13adc778 | |||
| 5c826a80f2 | |||
| 3cb7349e81 | |||
| f9354690dd | |||
| 840847a7a2 | |||
| b836517168 | |||
| 8f8a3909d1 | |||
| e7d9635af7 | |||
| d4090125ef | |||
| 10b10f1e68 | |||
| e298f2edd0 | |||
| 3d1fe06f1a | |||
| 5306fdca4b | |||
| 5643b8bf84 | |||
| 950e0ea810 | |||
| 66fd5b6e8a | |||
| 5425f6e620 | |||
| ac5189d81f | |||
| c332ea6b1a | |||
| 36bda84d78 | |||
| 0bb554bb9d | |||
| fb992064ed | |||
| ed5e4fac19 | |||
| ba84d063e7 | |||
| ea3a3002be | |||
| 8cb266381d | |||
| bbc0521963 | |||
| d74222ccec | |||
| d71e0d40ce | |||
| 048b05942d | |||
| 0c19405966 | |||
| 8d1b2c459c | |||
| cece3bc3c7 | |||
| aa3c641426 | |||
| 661ea869c5 | |||
| ae9b064146 | |||
| d5648b1d85 | |||
| a3c9726540 | |||
| e29944d76c | |||
| f0b18a5285 | |||
| 8465439b24 | |||
| 6d3a482469 | |||
| 72bf924583 | |||
| 086393ef81 | |||
| 14ce025824 | |||
| 76c3e552af | |||
| ea4b431713 | |||
| 33e5a4c57c | |||
| b3fac78b8c | |||
| 42abfa0488 | |||
| cae1aead0e | |||
| 3ca6690822 | |||
| fe3adb5859 | |||
| b0ffcc1e31 | |||
| 94ce91ae0a | |||
| db54f88fd7 | |||
| c78fefbed9 | |||
| a11fab4853 | |||
| eebcb56297 | |||
| 820cc2a390 | |||
| 20e2c009fb | |||
| efc188ac10 | |||
| 266e6b51f5 | |||
| d701b88f63 | |||
| ac9ff33b24 | |||
| fbfb504123 | |||
| 258ca7ccce | |||
| 399ced2a00 | |||
| ab5ef378ab | |||
| edb903d000 | |||
| 9cc94387eb | |||
| 7e8b199fde | |||
| b9bf7dd478 | |||
| dc86ad17ec | |||
| 32e925c794 | |||
| b2f1ec44f5 | |||
| 03b2851f4d | |||
| a5cbc3e61b | |||
| 5428225d1d | |||
| 8da11311a0 | |||
| 39c7d921ab | |||
| 350dff63cd | |||
| ddde71c69a | |||
| 05bc73c711 | |||
| 4888b35c31 | |||
| a8f59a2b61 | |||
| 647c4c6406 | |||
| a04e71f183 | |||
| 38461f1708 | |||
| a37ac671ea | |||
| 10c4002bd9 | |||
| bcab6e02ae | |||
| daeb1f1211 | |||
| 4f5553737b | |||
| 7cb7ffef35 | |||
| 8fec847cca | |||
| f64d7eda8a | |||
| 9e46f14dcd | |||
| 6ff924328e | |||
| 2aea27172e | |||
| 1267f885cd | |||
| 836d2e0da1 | |||
| d7607c362d | |||
| 0b61c6f928 | |||
| 8ebb3d78df | |||
| 11cf5b1701 | |||
| 8b608a17c8 | |||
| f32f631bc3 |
7
.gitattributes
vendored
7
.gitattributes
vendored
@ -5,3 +5,10 @@ fail/bin/import-trace filter=lfs diff=lfs merge=lfs -text
|
||||
fail/bin/prune-trace filter=lfs diff=lfs merge=lfs -text
|
||||
fail/share/** filter=lfs diff=lfs merge=lfs -text
|
||||
just-bin/just filter=lfs diff=lfs merge=lfs -text
|
||||
injections/** filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
ghidra/**/*.db filter=lfs diff=lfs merge=lfs -text
|
||||
ghidra/**/*.gbf filter=lfs diff=lfs merge=lfs -text
|
||||
ghidra/**/*.prp filter=lfs diff=lfs merge=lfs -text
|
||||
ghidra/**/*.bak filter=lfs diff=lfs merge=lfs -text
|
||||
ghidra/**/*.dat filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/build-*
|
||||
/builds
|
||||
/ghidra/projects/**/*.lock*
|
||||
/mars-db.conf
|
||||
/.direnv
|
||||
/db.conf
|
||||
/fail/bin/resultbrowser/app/__pycache__
|
||||
/fail/bin/VisualFAIL/CONFIGURATION.php
|
||||
9
.gitmodules
vendored
Normal file
9
.gitmodules
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
[submodule "fail/src"]
|
||||
path = fail/src
|
||||
url = git@gitos.rrze.fau.de:wasm-hardening/fail.git
|
||||
[submodule "wamr"]
|
||||
path = wamr
|
||||
url = ssh://git@gitea.local.chriphost.de:222/christoph/wamr.git
|
||||
[submodule "tacle-converter"]
|
||||
path = tacle-converter
|
||||
url = https://gitos.rrze.fau.de/i4/openaccess/tacle-bench-wasm-converter
|
||||
72
.vscode/launch.json
vendored
Normal file
72
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "AOT Linux sum0_base",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "/home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-05-11T19:19:39_sum0_base-linux-aot/system.elf",
|
||||
"args": [],
|
||||
"cwd": "/home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-05-11T19:19:39_sum0_base-linux-aot",
|
||||
"initCommands": [
|
||||
"settings set target.x86-disassembly-flavor intel",
|
||||
"breakpoint set -b main",
|
||||
"breakpoint set -b fail_start_trace",
|
||||
"breakpoint set -b fail_stop_trace",
|
||||
"breakpoint set -b fail_marker_positive",
|
||||
"breakpoint set -b fail_marker_negative",
|
||||
"breakpoint set -b invokeNative_Void",
|
||||
],
|
||||
"sourceMap": {
|
||||
"/build/source/core": "/home/christoph/Notes/TU/MastersThesis/05 WAMR/core",
|
||||
"/home/christoph/Notes/TU/MastersThesis/FailNix/build-sum0_base": "/home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-05-11T19:19:39_sum0_base-linux-aot",
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "AOT Fail sum0_base (QEMU)",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Launch QEMU (sum0_base fail-aot)",
|
||||
"initCommands": ["settings set target.x86-disassembly-flavor intel"],
|
||||
"processCreateCommands": ["gdb-remote localhost:9000", "continue"],
|
||||
"targetCreateCommands": [
|
||||
"target create /home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-04-27T21-42-42_sum0_base-fail-aot/system.elf",
|
||||
],
|
||||
"preRunCommands": [
|
||||
"breakpoint set -b os_main",
|
||||
"breakpoint set -b fail_start_trace",
|
||||
"breakpoint set -b fail_stop_trace",
|
||||
"breakpoint set -b fail_marker_positive",
|
||||
"breakpoint set -b fail_marker_negative",
|
||||
"breakpoint set -b invokeNative_Void",
|
||||
],
|
||||
"sourceMap": {
|
||||
"/build/source/core": "/home/christoph/Notes/TU/MastersThesis/05 WAMR/core",
|
||||
"/home/christoph/Notes/TU/MastersThesis/FailNix/build-sum0_base": "/home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-04-27T21-42-42_sum0_base-fail-aot",
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "fail-x86-tracing-dbg",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "/nix/store/z3cyzvdz8pbxccp9jyxgp57ccjjppi1j-fail-1.0.0/bin/fail-x86-tracing",
|
||||
"args": [
|
||||
"-q", "-f", "./bochs.rc",
|
||||
"-Wf,--start-symbol=fail_start_trace",
|
||||
"-Wf,--save-symbol=fail_start_trace",
|
||||
"-Wf,--end-symbol=fail_stop_trace",
|
||||
"-Wf,--state-file=./state",
|
||||
"-Wf,--trace-file=./trace.pb",
|
||||
"-Wf,--elf-file=./system.elf",
|
||||
],
|
||||
"cwd": "/home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-05-17T23-00-56_sum0_base-fail-aot",
|
||||
"initCommands": [
|
||||
"settings set target.x86-disassembly-flavor intel",
|
||||
"breakpoint set -n GenericTracing::run()",
|
||||
],
|
||||
"sourceMap": {
|
||||
"/home/fail/work": "/home/christoph/Notes/TU/MastersThesis/FailNix/fail/src",
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
25
.vscode/tasks.json
vendored
Normal file
25
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Launch QEMU (sum0_base fail-aot)",
|
||||
"type": "shell",
|
||||
"command": "qemu-system-i386 -drive file=system.iso,media=cdrom -boot d -m 32 -S -gdb tcp::9000",
|
||||
"options": {
|
||||
"cwd": "/home/christoph/Notes/TU/MastersThesis/FailNix/injections/2026-04-27T21-42-42_sum0_base-fail-aot",
|
||||
},
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"pattern": {
|
||||
"regexp": "^(.*)$",
|
||||
"message": 1,
|
||||
},
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": ".",
|
||||
"endsPattern": "^NEVER_MATCH$",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
BIN
fail-db.png
(Stored with Git LFS)
Normal file
BIN
fail-db.png
(Stored with Git LFS)
Normal file
Binary file not shown.
10
fail/bin/VisualFAIL/CONFIGURATION.php.dist
Normal file
10
fail/bin/VisualFAIL/CONFIGURATION.php.dist
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
// database credentials
|
||||
$host = "localhost";
|
||||
$username = "";
|
||||
$password = "";
|
||||
$database = "";
|
||||
|
||||
// result-table name
|
||||
$result_table = "result";
|
||||
?>
|
||||
64
fail/bin/VisualFAIL/README.md
Normal file
64
fail/bin/VisualFAIL/README.md
Normal file
@ -0,0 +1,64 @@
|
||||
VisualFAIL*
|
||||
===========
|
||||
|
||||
Guest-system setup
|
||||
------------------
|
||||
For analysis with VisualFAIL*, the guest-system ELF binary must be compiled with
|
||||
debugging information (gcc/g++/clang/clang++ compiler flag "-g"). Note that
|
||||
debugging information quality/accuracy usually decreases with higher
|
||||
optimization levels.
|
||||
|
||||
Database preparation
|
||||
--------------------
|
||||
1. import-trace -t yourtrace.tc -i MemoryImporter
|
||||
2. import-trace -t yourtrace.tc -i FullTraceImporter
|
||||
3. import-trace -t yourtrace.tc -i ElfImporter -e yourbinary.elf --objdump $(which objdump) --sources
|
||||
|
||||
Step 1 is the prerequisite to run the fault-injection campaign (you may use
|
||||
other importers as well, e.g., the RegisterImporter). Steps 2 and 3 are
|
||||
required for VisualFAIL* to work.
|
||||
|
||||
Setup
|
||||
-----
|
||||
Copy CONFIGURATION.php.dist to CONFIGURATION.php, edit it, and add your MySQL
|
||||
database credentials and the result-table name (usually starting with
|
||||
"result...", "echo SHOW TABLES | mysql yourdatabase" on the command line should
|
||||
give you the correct table name).
|
||||
|
||||
(In a later version of VisualFAIL*, we will probably add automatic loading of
|
||||
~/.my.cnf if available.)
|
||||
|
||||
Running and using VisualFAIL*
|
||||
-----------------------------
|
||||
./StartVF.sh requires PHP 5.4.0 or newer and uses its simple built-in web
|
||||
server. You can connect to it by using http://localhost:1234 in a web browser
|
||||
on the same machine. (If you need to connect from another machine, manually run
|
||||
"php -S 0.0.0.0:1234 -t .")
|
||||
|
||||
Alternatively, VisualFAIL* can be set up using a "real" web server with a recent
|
||||
PHP version (5.x should suffice).
|
||||
|
||||
Once the web server runs, you can use VisualFAIL*:
|
||||
|
||||
- Pick a coloring (currently, only "Right margin" really makes sense), a
|
||||
benchmark and a variant from the drop-down menus. Click "Analyze". Wait.
|
||||
|
||||
- Enable the experiment result types you want to highlight by clicking them in
|
||||
the top row.
|
||||
|
||||
- Scroll down the left column with the disassembled machine code. Instructions
|
||||
that activated faults in the FI experiments, and led to one of the enabled
|
||||
result types, are highlighted with red color. The stronger the coloring, the
|
||||
more experiments led to one of these failure modes. (Actually, not the raw
|
||||
number of actual experiments is used, but is weighted with the size of the
|
||||
corresponding def/use equivalence class.)
|
||||
|
||||
- Click one of the highlighted instructions to display a popup with the actual
|
||||
result numbers, and the distribution among the different failure modes.
|
||||
|
||||
- Pick a source-code file from the right-hand side pulldown to look into the
|
||||
instructions generated from that file. The right column now contains the
|
||||
source code from that file, interspersed with the disassembled machine code
|
||||
generated from it. These disassembled machine-code lines are, just like in
|
||||
the disassembly column, clickable to display details. (The source-code lines
|
||||
are currently not clickable, although the mouse cursor indicates otherwise.)
|
||||
6
fail/bin/VisualFAIL/StartVF.sh
Executable file
6
fail/bin/VisualFAIL/StartVF.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Starts VisualFAIL over php on Port 1234
|
||||
#
|
||||
|
||||
php -S localhost:1234 -t .
|
||||
510
fail/bin/VisualFAIL/core.php
Normal file
510
fail/bin/VisualFAIL/core.php
Normal file
@ -0,0 +1,510 @@
|
||||
<?php
|
||||
require('CONFIGURATION.php');
|
||||
|
||||
// increase default script runtime limit
|
||||
set_time_limit(60*10);
|
||||
|
||||
//Datenbankverbindung aufbauen
|
||||
$db = mysqli_connect ($host,$username, $password)
|
||||
or die ("MySQL connection failed.");
|
||||
|
||||
mysqli_select_db($db, $database) or die ("Cannot select database '$database'.");
|
||||
|
||||
// identify command
|
||||
switch ($_GET['cmd']) {
|
||||
case "dbTest" : dbTest();break;
|
||||
case "getAsmCode" : getAsmCode();break;
|
||||
case "asmToSourceFile" : asmToSourceFile();break;
|
||||
case "getBinarys" : getBinarys();break;
|
||||
case "getVariants" : getVariants();break;
|
||||
case "getSourceFiles" : getSourceFiles();break;
|
||||
case "getResultTypes" : getResulttypesOUT();break;
|
||||
case "getHighlevelCode" : getHighlevelCode();break;
|
||||
case "resultsDB" : resultsDB();break;
|
||||
case "dechex" : echo json_encode(dechex($_GET['dec']));break;
|
||||
}
|
||||
|
||||
mysqli_close($db);
|
||||
|
||||
function dbTest()
|
||||
{
|
||||
|
||||
$check = true;
|
||||
|
||||
$abfrage = "SELECT 1 FROM objdump;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle objdump nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
|
||||
$abfrage = "SELECT 1 FROM fulltrace;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle fulltrace nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
|
||||
$abfrage = "SELECT 1 FROM dbg_filename;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle dbg_filename nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
|
||||
$abfrage = "SELECT 1 FROM dbg_mapping;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle dbg_mapping nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
$abfrage = "SELECT 1 FROM dbg_methods;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle dbg_methods nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
$abfrage = "SELECT 1 FROM dbg_source;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle dbg_source nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
$abfrage = "SELECT 1 FROM dbg_stacktrace;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle dbg_stacktrace nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
|
||||
$abfrage = "SELECT 1 FROM dbg_variables;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
if (!$ergebnis) {
|
||||
echo json_encode('Tabelle dbg_variables nicht gefunden <br>');
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function getBinarys()
|
||||
{
|
||||
$binarys = array();
|
||||
|
||||
$abfrage = "SELECT benchmark FROM variant;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
array_push($binarys, $row->benchmark);
|
||||
}
|
||||
|
||||
$result = array_unique($binarys);
|
||||
|
||||
echo json_encode($result);
|
||||
}
|
||||
|
||||
function getVariants()
|
||||
{
|
||||
$variants = array();
|
||||
|
||||
$abfrage = "SELECT id, variant FROM variant WHERE benchmark = '" . $_GET['datei'] ."';";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
$variants[$row->id] = $row->variant;
|
||||
}
|
||||
|
||||
echo json_encode($variants);
|
||||
}
|
||||
|
||||
function remove_common_prefix($files)
|
||||
{
|
||||
if (count($files) == 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// start with arbitrary file
|
||||
$commonprefix = dirname(current($files));
|
||||
|
||||
foreach ($files AS $id => $file) {
|
||||
for ($i = 0; $i < strlen($commonprefix); ++$i) {
|
||||
if ($i >= strlen($file) || $file[$i] != $commonprefix[$i]) {
|
||||
$commonprefix = substr($commonprefix, 0, $i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strlen($commonprefix) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$out = array();
|
||||
foreach ($files AS $id => $file) {
|
||||
$out[$id] = substr($file, strlen($commonprefix));
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function getSourceFiles()
|
||||
{
|
||||
$sourceFiles = array();
|
||||
|
||||
$abfrage = "SELECT file_id, path FROM dbg_filename WHERE variant_id = '" . $_GET['variant_id']. "';";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
$sourceFiles[$row->file_id] = $row->path;
|
||||
}
|
||||
|
||||
$sourceFiles = remove_common_prefix($sourceFiles);
|
||||
|
||||
echo json_encode($sourceFiles);
|
||||
}
|
||||
|
||||
function asmCode()
|
||||
{
|
||||
$content = "";
|
||||
|
||||
$abfrage = "SELECT instr_address, disassemble FROM objdump WHERE variant_id = '" . $_GET['variant_id'] ."' ORDER BY instr_address;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
$content = $content;
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
$content .= dechex($row->instr_address) . '<br>';
|
||||
}
|
||||
echo json_encode($content);
|
||||
}
|
||||
|
||||
function collapse_repeated($html, $disasm, $force_finish)
|
||||
{
|
||||
static $last_disasm = '';
|
||||
static $collect = array();
|
||||
$limit_before = $limit_after = 3;
|
||||
|
||||
$out = '';
|
||||
if ($force_finish || $last_disasm != $disasm) {
|
||||
if (count($collect) > $limit_before + $limit_after + 1) {
|
||||
for ($i = 0; $i < $limit_before; ++$i) {
|
||||
$out .= $collect[$i];
|
||||
}
|
||||
$out .= '<i>-- omitted ' . (count($collect) - $limit_before - $limit_after) . " repetitions of '$last_disasm'</i><br>";
|
||||
for ($i = count($collect) - $limit_after; $i < count($collect); ++$i) {
|
||||
$out .= $collect[$i];
|
||||
}
|
||||
} else {
|
||||
$out = implode('', $collect);
|
||||
}
|
||||
$last_disasm = $disasm;
|
||||
$collect = array();
|
||||
}
|
||||
|
||||
if ($force_finish) {
|
||||
$out .= $html;
|
||||
} else {
|
||||
$collect[] = $html;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
function getAsmCode()
|
||||
{
|
||||
$content = "";
|
||||
$resulttypes = array();
|
||||
|
||||
$asmAbfrage = "SELECT instr_address, disassemble FROM objdump WHERE variant_id = '" . $_GET['variant_id'] ."' ORDER BY instr_address;";
|
||||
|
||||
$asmcode = mysqli_query($GLOBALS['db'], $asmAbfrage);
|
||||
|
||||
getResulttypes($resulttypes);
|
||||
|
||||
$fehlerdaten = resultsDB($_GET['variant_id'], $_GET['version'], $resulttypes);
|
||||
//$fehlerdaten = askDBFehler($_GET['variant_id'], $resulttypes, $_GET['version']);
|
||||
|
||||
//print_r($fehlerdaten);
|
||||
// FIXME id not unique
|
||||
$content = '<div id="maxFehler" ';
|
||||
foreach ($resulttypes as $value) {
|
||||
$temp = $value . '="' . $fehlerdaten['max'][$value] . '" ';
|
||||
$content .= $temp;
|
||||
}
|
||||
$content .= ' >';
|
||||
while ($row = mysqli_fetch_object($asmcode)) {
|
||||
if (array_key_exists($row->instr_address,$fehlerdaten['Daten'])) {
|
||||
$line = '<span data-address="' . dechex($row->instr_address) . '" class="hasFehler" ';
|
||||
|
||||
foreach ($resulttypes as $value) {
|
||||
$line .= $value . '="' . $fehlerdaten['Daten'][$row->instr_address][$value] . '" ';
|
||||
}
|
||||
|
||||
$line .= ' style="cursor: pointer;">' . dechex($row->instr_address) . ' ' . htmlspecialchars($row->disassemble) . '</span><br>';
|
||||
$content .= collapse_repeated($line, 'dontcare', true);
|
||||
} else {
|
||||
$line = dechex($row->instr_address) . ' ' . htmlspecialchars($row->disassemble) . '<br>';
|
||||
$content .= collapse_repeated($line, htmlspecialchars($row->disassemble), false);
|
||||
}
|
||||
}
|
||||
$content .= collapse_repeated('', '', true);
|
||||
$content .= ' </div>';
|
||||
|
||||
echo json_encode($content);
|
||||
}
|
||||
|
||||
function getHighlevelCode()
|
||||
{
|
||||
$content = "";
|
||||
$resulttypes = array();
|
||||
|
||||
getResulttypes($resulttypes);
|
||||
|
||||
$kleinsteAdresseAbfrage = "SELECT MIN(instr_address) AS instr_address FROM objdump WHERE variant_id = " . $_GET['variant_id'];
|
||||
$kleinsteAdresseErgebnis = mysqli_query($GLOBALS['db'], $kleinsteAdresseAbfrage) or trigger_error($kleinsteAdresseAbfrage, E_USER_NOTICE);
|
||||
$kleinsteAdresse = mysqli_fetch_object($kleinsteAdresseErgebnis);
|
||||
|
||||
$highlevelCodeAbfrage = "SELECT linenumber, line FROM dbg_source WHERE variant_id = '" . $_GET['variant_id']. "' AND file_id = '" . $_GET['file_id']. "' ORDER BY linenumber;";
|
||||
$mappingAbfrage = "SELECT linenumber, instr_absolute, line_range_size FROM dbg_mapping WHERE variant_id = '" . $_GET['variant_id']. "' AND file_id = '" . $_GET['file_id'] . "' AND instr_absolute >= '" . $kleinsteAdresse->instr_address . "' ORDER BY instr_absolute;";
|
||||
|
||||
$highlevelCode = mysqli_query($GLOBALS['db'], $highlevelCodeAbfrage);
|
||||
$mappingInfo = mysqli_query($GLOBALS['db'], $mappingAbfrage);
|
||||
|
||||
$fehlerdaten = resultsDB($_GET['variant_id'], $_GET['version'], $resulttypes);
|
||||
|
||||
// retrieve mapping of linenumber -> array of [start-address;end-address) ranges
|
||||
$mappingRanges = array();
|
||||
while (($row = mysqli_fetch_object($mappingInfo))) {
|
||||
if (!isset($mappingRanges[$row->linenumber])) {
|
||||
$mappingRanges[$row->linenumber] = array();
|
||||
}
|
||||
$mappingRanges[$row->linenumber][] =
|
||||
array(intval($row->instr_absolute),
|
||||
$row->instr_absolute + $row->line_range_size);
|
||||
}
|
||||
|
||||
$mapping = array();
|
||||
// "maxFehler" should be "sumFehler" or alike
|
||||
$maxFehlerMapping = array();
|
||||
|
||||
foreach ($mappingRanges as $lineNumber => $value) {
|
||||
$maxFehler = array();
|
||||
foreach ($resulttypes as $val) {
|
||||
$maxFehler[$val] = 0;
|
||||
}
|
||||
foreach ($value as $index => $ranges) {
|
||||
// was ">" instead of ">=" before
|
||||
$InstrMappingAbfrage = "SELECT instr_address, disassemble FROM objdump WHERE variant_id = '" . $_GET['variant_id']. "' AND instr_address >= '" . $ranges[0] . "' AND instr_address < '" . $ranges[1] . "' ORDER BY instr_address;";
|
||||
$mappingErgebnis = mysqli_query($GLOBALS['db'], $InstrMappingAbfrage);
|
||||
while ($row = mysqli_fetch_object($mappingErgebnis)) {
|
||||
if (array_key_exists($row->instr_address,$fehlerdaten['Daten'])) {
|
||||
$newline = '<span data-address="' . dechex($row->instr_address) . '" class="hasFehler" ';
|
||||
|
||||
foreach ($resulttypes as $value) {
|
||||
// FIXME prefix with 'data-results-', adapt JS
|
||||
$newline .= $value . '="' . $fehlerdaten['Daten'][$row->instr_address][$value] . '" ';
|
||||
$maxFehler[$value] += $fehlerdaten['Daten'][$row->instr_address][$value];
|
||||
}
|
||||
|
||||
$newline .= ' style="cursor: pointer;">' . dechex($row->instr_address) . ' ' . htmlspecialchars($row->disassemble) . '</span><br>';
|
||||
$newline = collapse_repeated($newline, 'dontcare', true);
|
||||
} else {
|
||||
$newline = dechex($row->instr_address) . ' ' . htmlspecialchars($row->disassemble) . '<br>';
|
||||
$newline = collapse_repeated($newline, htmlspecialchars($row->disassemble), false);
|
||||
}
|
||||
$mapping[$lineNumber] [] = $newline;
|
||||
}
|
||||
$mapping[$lineNumber] [] = collapse_repeated('', '', true);
|
||||
}
|
||||
foreach ($resulttypes as $value) {
|
||||
$maxFehlerMapping[$lineNumber][$value] = $maxFehler[$value];
|
||||
}
|
||||
}
|
||||
|
||||
while ($row = mysqli_fetch_object($highlevelCode)) {
|
||||
// FIXME id unique?
|
||||
$content .= '<span data-line="' . $row->linenumber . '" class="sourcecode">' . $row->linenumber . ' : ' . $row->line . '</span><br>';
|
||||
if (array_key_exists($row->linenumber, $mapping)) {
|
||||
$content .= '<div class="mapping">';
|
||||
foreach ($mapping[$row->linenumber] as $index => $span) {
|
||||
$content .= $span;
|
||||
}
|
||||
$content .= '</div><div class="maxFehlerMapping"';
|
||||
foreach ($resulttypes as $value) {
|
||||
$content .= $value . '="' . $maxFehlerMapping[$row->linenumber][$value] . '" ';
|
||||
}
|
||||
$content .= '></div>';
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($content);
|
||||
}
|
||||
|
||||
function getResulttypes(&$resulttypes)
|
||||
{
|
||||
$abfrage = "SELECT resulttype FROM " . $GLOBALS['result_table'] . " GROUP BY resulttype;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
//echo $row->resulttype;
|
||||
array_push($resulttypes, $row->resulttype);
|
||||
}
|
||||
}
|
||||
|
||||
function getResulttypesOUT()
|
||||
{
|
||||
$resulttypes = array();
|
||||
|
||||
$abfrage = "SELECT resulttype FROM " . $GLOBALS['result_table'] . " GROUP BY resulttype;";
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
//echo $row->resulttype;
|
||||
array_push($resulttypes, $row->resulttype);
|
||||
}
|
||||
|
||||
echo json_encode($resulttypes);
|
||||
}
|
||||
|
||||
function askDBFehler($variant_id, $resulttypes, $version)
|
||||
{
|
||||
if ($version == 'onlyRightEdge') {
|
||||
// we don't need fulltrace here at all
|
||||
$abfrage = "SELECT t.instr2 AS instr, t.instr2_absolute AS instr_absolute";
|
||||
foreach ( $resulttypes as $value) {
|
||||
$abfrage .= ", SUM(IF(r.resulttype = '" . $value . "', 1, 0)*(t.time2-t.time1+1)) AS " . $value;
|
||||
}
|
||||
$abfrage .= " FROM trace t
|
||||
JOIN fsppilot p
|
||||
ON t.variant_id = p.variant_id
|
||||
AND t.data_address = p.data_address
|
||||
AND p.instr2 = t.instr2
|
||||
JOIN " . $GLOBALS['result_table'] . " r
|
||||
ON p.id = r.pilot_id
|
||||
WHERE t.variant_id = $variant_id
|
||||
AND t.accesstype = 'R'
|
||||
GROUP BY t.instr2_absolute;";
|
||||
} else if ($version == 'latestip') {
|
||||
$abfrage = "SELECT r.latest_ip ";
|
||||
foreach ( $resulttypes as $value) {
|
||||
$abfrage .= ", SUM(IF(r.resulttype = '" . $value . "', 1, 0)*(t.time2-t.time1+1)) AS " . $value;
|
||||
}
|
||||
$abfrage .= " FROM trace t
|
||||
JOIN fsppilot p
|
||||
ON t.variant_id = p.variant_id
|
||||
AND t.data_address = p.data_address
|
||||
AND p.instr2 = t.instr2
|
||||
JOIN " . $GLOBALS['result_table'] . " r
|
||||
ON p.id = r.pilot_id
|
||||
WHERE t.variant_id = '" . $variant_id . "' AND t.accesstype = 'R'
|
||||
GROUP BY r.latest_ip;";
|
||||
} else {
|
||||
$abfrage = "SELECT ft.instr, ft.instr_absolute ";
|
||||
foreach ( $resulttypes as $value) {
|
||||
$abfrage .= ", SUM(IF(r.resulttype = '" . $value . "', 1, 0)*(t.time2-t.time1+1)) AS " . $value;
|
||||
}
|
||||
$abfrage .= " FROM fulltrace ft
|
||||
LEFT JOIN trace t
|
||||
ON ft.variant_id = '" . $variant_id . "'
|
||||
AND t.variant_id = '" . $variant_id . "'
|
||||
AND ft.instr BETWEEN t.instr1 AND t.instr2
|
||||
AND t.accesstype = 'R'
|
||||
JOIN fsppilot p
|
||||
ON t.variant_id = '" . $variant_id . "'
|
||||
AND p.variant_id = '" . $variant_id . "'
|
||||
AND t.data_address = p.data_address
|
||||
AND p.instr2 = t.instr2
|
||||
JOIN " . $GLOBALS['result_table'] . " r
|
||||
ON p.id = r.pilot_id
|
||||
GROUP BY ft.instr_absolute;";
|
||||
}
|
||||
|
||||
//echo $abfrage;
|
||||
|
||||
$ergebnis = mysqli_query($GLOBALS['db'], $abfrage);
|
||||
|
||||
return $ergebnis;
|
||||
}
|
||||
|
||||
function resultsDB($variant_id, $version, $resulttypes)
|
||||
{
|
||||
getResulttypes($resulttypes);
|
||||
|
||||
//print_r($resulttypes);
|
||||
|
||||
$ergebnis = askDBFehler($variant_id, $resulttypes, $version);
|
||||
|
||||
//print_r($ergebnis);
|
||||
|
||||
$results = array();
|
||||
|
||||
// We find the fields number
|
||||
$numfields=mysqli_num_fields($ergebnis);
|
||||
|
||||
for ($i=0; $i < $numfields; $i++) {
|
||||
$fieldInfo = mysqli_fetch_field_direct($ergebnis, $i);
|
||||
$fieldname[$i] = $fieldInfo->name;
|
||||
}
|
||||
|
||||
for ($i=2; $i < $numfields; $i++) {
|
||||
$results["max"][$fieldname[$i]] = 0;
|
||||
}
|
||||
|
||||
$maxFehler = 0;
|
||||
while ($row = mysqli_fetch_object($ergebnis)) {
|
||||
if ($version != 'latestip') {
|
||||
if ($row->instr_absolute != NULL) {
|
||||
$results["Daten"][$row->instr_absolute] = array();
|
||||
for ($i = 2; $i < $numfields ; $i++) {
|
||||
$fn = $fieldname[$i];
|
||||
$results["Daten"][$row->instr_absolute][$fn] = $row->$fn;
|
||||
|
||||
if ($row->$fn > $results["max"][$fn]) {
|
||||
$results["max"][$fn] = $row->$fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($row->latest_ip != NULL) {
|
||||
$results["Daten"][$row->latest_ip] = array();
|
||||
for ($i = 0 ; $i < $numfields ; $i++) {
|
||||
$fn = $fieldname[$i];
|
||||
$results["Daten"][$row->latest_ip][$fn] = $row->$fn;
|
||||
|
||||
if ($row->$fn > $results["max"][$fn]) {
|
||||
$results["max"][$fn] = $row->$fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
?>
|
||||
397
fail/bin/VisualFAIL/css/bootstrap-theme.css
vendored
Normal file
397
fail/bin/VisualFAIL/css/bootstrap-theme.css
vendored
Normal file
@ -0,0 +1,397 @@
|
||||
/*!
|
||||
* Bootstrap v3.0.3 (http://getbootstrap.com)
|
||||
* Copyright 2013 Twitter, Inc.
|
||||
* Licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
.btn-default,
|
||||
.btn-primary,
|
||||
.btn-success,
|
||||
.btn-info,
|
||||
.btn-warning,
|
||||
.btn-danger {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.btn-default:active,
|
||||
.btn-primary:active,
|
||||
.btn-success:active,
|
||||
.btn-info:active,
|
||||
.btn-warning:active,
|
||||
.btn-danger:active,
|
||||
.btn-default.active,
|
||||
.btn-primary.active,
|
||||
.btn-success.active,
|
||||
.btn-info.active,
|
||||
.btn-warning.active,
|
||||
.btn-danger.active {
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
|
||||
.btn:active,
|
||||
.btn.active {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dbdbdb;
|
||||
border-color: #ccc;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.btn-default:hover,
|
||||
.btn-default:focus {
|
||||
background-color: #e0e0e0;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.btn-default:active,
|
||||
.btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
border-color: #dbdbdb;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #2b669a;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus {
|
||||
background-color: #2d6ca2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.btn-primary:active,
|
||||
.btn-primary.active {
|
||||
background-color: #2d6ca2;
|
||||
border-color: #2b669a;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #3e8f3e;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.btn-success:hover,
|
||||
.btn-success:focus {
|
||||
background-color: #419641;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.btn-success:active,
|
||||
.btn-success.active {
|
||||
background-color: #419641;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
|
||||
.btn-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #e38d13;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.btn-warning:hover,
|
||||
.btn-warning:focus {
|
||||
background-color: #eb9316;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.btn-warning:active,
|
||||
.btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b92c28;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.btn-danger:hover,
|
||||
.btn-danger:focus {
|
||||
background-color: #c12e2a;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.btn-danger:active,
|
||||
.btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #28a4c9;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.btn-info:hover,
|
||||
.btn-info:focus {
|
||||
background-color: #2aabd2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.btn-info:active,
|
||||
.btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
|
||||
.thumbnail,
|
||||
.img-thumbnail {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-color: #e8e8e8;
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
}
|
||||
|
||||
.dropdown-menu > .active > a,
|
||||
.dropdown-menu > .active > a:hover,
|
||||
.dropdown-menu > .active > a:focus {
|
||||
background-color: #357ebd;
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
|
||||
}
|
||||
|
||||
.navbar-default {
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-radius: 4px;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.navbar-brand,
|
||||
.navbar-nav > li > a {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);
|
||||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #222222 0%, #282828 100%);
|
||||
background-image: linear-gradient(to bottom, #222222 0%, #282828 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-brand,
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.navbar-static-top,
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.alert {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b2dba1;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #9acfea;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #f5e79e;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dca7a7;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||
}
|
||||
|
||||
.progress {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
|
||||
}
|
||||
|
||||
.progress-bar-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||
}
|
||||
|
||||
.progress-bar-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||
}
|
||||
|
||||
.progress-bar-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||
}
|
||||
|
||||
.progress-bar-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||
}
|
||||
|
||||
.list-group {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.list-group-item.active,
|
||||
.list-group-item.active:hover,
|
||||
.list-group-item.active:focus {
|
||||
text-shadow: 0 -1px 0 #3071a9;
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #3278b3;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
|
||||
}
|
||||
|
||||
.panel {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.panel-default > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
}
|
||||
|
||||
.panel-primary > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
|
||||
}
|
||||
|
||||
.panel-success > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||
}
|
||||
|
||||
.panel-info > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||
}
|
||||
|
||||
.panel-warning > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||
}
|
||||
|
||||
.panel-danger > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||
}
|
||||
|
||||
.well {
|
||||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dcdcdc;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
7
fail/bin/VisualFAIL/css/bootstrap-theme.min.css
vendored
Normal file
7
fail/bin/VisualFAIL/css/bootstrap-theme.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7118
fail/bin/VisualFAIL/css/bootstrap.css
vendored
Normal file
7118
fail/bin/VisualFAIL/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
fail/bin/VisualFAIL/css/bootstrap.min.css
vendored
Normal file
7
fail/bin/VisualFAIL/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
23
fail/bin/VisualFAIL/css/myStyle.css
Normal file
23
fail/bin/VisualFAIL/css/myStyle.css
Normal file
@ -0,0 +1,23 @@
|
||||
body {
|
||||
min-height: 2000px;
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
/* Custom container */
|
||||
.container-full {
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
padding: 0 0 0 30px;
|
||||
}
|
||||
|
||||
.sourcecode {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#analyse {
|
||||
margin: 20px 0 0 0;
|
||||
}
|
||||
BIN
fail/bin/VisualFAIL/favicon.ico
Normal file
BIN
fail/bin/VisualFAIL/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.eot
Normal file
BIN
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.eot
Normal file
Binary file not shown.
229
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.svg
Normal file
229
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.svg
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
|
||||
<font-face units-per-em="1200" ascent="960" descent="-240" />
|
||||
<missing-glyph horiz-adv-x="500" />
|
||||
<glyph />
|
||||
<glyph />
|
||||
<glyph unicode="
" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
|
||||
<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode=" " horiz-adv-x="652" />
|
||||
<glyph unicode=" " horiz-adv-x="1304" />
|
||||
<glyph unicode=" " horiz-adv-x="652" />
|
||||
<glyph unicode=" " horiz-adv-x="1304" />
|
||||
<glyph unicode=" " horiz-adv-x="434" />
|
||||
<glyph unicode=" " horiz-adv-x="326" />
|
||||
<glyph unicode=" " horiz-adv-x="217" />
|
||||
<glyph unicode=" " horiz-adv-x="217" />
|
||||
<glyph unicode=" " horiz-adv-x="163" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="72" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="326" />
|
||||
<glyph unicode="€" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
|
||||
<glyph unicode="−" d="M200 400h900v300h-900v-300z" />
|
||||
<glyph unicode="☁" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
|
||||
<glyph unicode="✉" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
|
||||
<glyph unicode="✏" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
|
||||
<glyph unicode="" horiz-adv-x="500" d="M0 0z" />
|
||||
<glyph unicode="" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
|
||||
<glyph unicode="" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q17 -55 85.5 -75.5t147.5 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
|
||||
<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
|
||||
<glyph unicode="" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
|
||||
<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
|
||||
<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
|
||||
<glyph unicode="" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
|
||||
<glyph unicode="" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
|
||||
<glyph unicode="" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
|
||||
<glyph unicode="" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
|
||||
<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
|
||||
<glyph unicode="" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 299q-120 -77 -261 -77q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
|
||||
<glyph unicode="" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
|
||||
<glyph unicode="" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
|
||||
<glyph unicode="" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
|
||||
<glyph unicode="" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
|
||||
<glyph unicode="" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
|
||||
<glyph unicode="" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
|
||||
<glyph unicode="" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
|
||||
<glyph unicode="" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
|
||||
<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
|
||||
<glyph unicode="" d="M0 25v475l200 700h800q199 -700 200 -700v-475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
|
||||
<glyph unicode="" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
|
||||
<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
|
||||
<glyph unicode="" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
|
||||
<glyph unicode="" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
|
||||
<glyph unicode="" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
|
||||
<glyph unicode="" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
|
||||
<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
|
||||
<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
|
||||
<glyph unicode="" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
|
||||
<glyph unicode="" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
|
||||
<glyph unicode="" d="M1 700v475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
|
||||
<glyph unicode="" d="M2 700v475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
|
||||
<glyph unicode="" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
|
||||
<glyph unicode="" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
|
||||
<glyph unicode="" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
|
||||
<glyph unicode="" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
|
||||
<glyph unicode="" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v70h471q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
|
||||
<glyph unicode="" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
|
||||
<glyph unicode="" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
|
||||
<glyph unicode="" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
|
||||
<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
|
||||
<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
|
||||
<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
|
||||
<glyph unicode="" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
|
||||
<glyph unicode="" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
|
||||
<glyph unicode="" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
|
||||
<glyph unicode="" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
|
||||
<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
|
||||
<glyph unicode="" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 138.5t-64 210.5zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l566 567l-136 137l-430 -431l-147 147z" />
|
||||
<glyph unicode="" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
|
||||
<glyph unicode="" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
|
||||
<glyph unicode="" d="M200 0l900 550l-900 550v-1100z" />
|
||||
<glyph unicode="" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
|
||||
<glyph unicode="" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
|
||||
<glyph unicode="" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
|
||||
<glyph unicode="" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
|
||||
<glyph unicode="" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
|
||||
<glyph unicode="" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
|
||||
<glyph unicode="" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
|
||||
<glyph unicode="" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM300 500h600v200h-600v-200z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM363 700h144q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5q19 0 30 -10t11 -26 q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-105 0 -172 -56t-67 -183zM500 300h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -300t-217.5 -218t-299.5 -80t-299.5 80t-217.5 218t-80 300zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M0 500v200h194q15 60 36 104.5t55.5 86t88 69t126.5 40.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200 v-206q149 48 201 206h-201v200h200q-25 74 -76 127.5t-124 76.5v-204h-200v203q-75 -24 -130 -77.5t-79 -125.5h209v-200h-210z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
|
||||
<glyph unicode="" d="M0 547l600 453v-300h600v-300h-600v-301z" />
|
||||
<glyph unicode="" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
|
||||
<glyph unicode="" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
|
||||
<glyph unicode="" d="M104 600h296v600h300v-600h298l-449 -600z" />
|
||||
<glyph unicode="" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
|
||||
<glyph unicode="" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
|
||||
<glyph unicode="" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
|
||||
<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-33 14.5h-207q-20 0 -32 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111v6t-1 15t-3 18l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6h-111v-100z M100 0h400v400h-400v-400zM200 900q-3 0 14 48t35 96l18 47l214 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
|
||||
<glyph unicode="" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
|
||||
<glyph unicode="" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
|
||||
<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
|
||||
<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
|
||||
<glyph unicode="" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 33 -48 36t-48 -29l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
|
||||
<glyph unicode="" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -21 -13 -29t-32 1l-94 78h-222l-94 -78q-19 -9 -32 -1t-13 29v64 q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
|
||||
<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
|
||||
<glyph unicode="" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
|
||||
<glyph unicode="" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
|
||||
<glyph unicode="" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
|
||||
<glyph unicode="" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
|
||||
<glyph unicode="" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
|
||||
<glyph unicode="" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
|
||||
<glyph unicode="" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
|
||||
<glyph unicode="" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
|
||||
<glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
|
||||
<glyph unicode="" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
|
||||
<glyph unicode="" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
|
||||
<glyph unicode="" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM99 500v250v5q0 13 0.5 18.5t2.5 13t8 10.5t15 3h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35q-56 337 -56 351z M1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M74 350q0 21 13.5 35.5t33.5 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-22 -9 -63 -23t-167.5 -37 t-251.5 -23t-245.5 20.5t-178.5 41.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
|
||||
<glyph unicode="" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
|
||||
<glyph unicode="" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q123 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 212l100 213h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
|
||||
<glyph unicode="" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q123 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
|
||||
<glyph unicode="" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
|
||||
<glyph unicode="" d="M-101 651q0 72 54 110t139 37h302l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 16.5 -10.5t26 -26t16.5 -36.5v-526q0 -13 -85.5 -93.5t-93.5 -80.5h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l106 89v502l-342 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM999 201v600h200v-600h-200z" />
|
||||
<glyph unicode="" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6v7.5v7v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
|
||||
<glyph unicode="" d="M1 585q-15 -31 7 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85l-1 -302q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM76 565l237 339h503l89 -100v-294l-340 -130 q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 500h300l-2 -194l402 294l-402 298v-197h-298v-201z" />
|
||||
<glyph unicode="" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l400 -294v194h302v201h-300v197z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -34 5.5 -93t7.5 -87q0 -9 17 -44t16 -60q12 0 23 -5.5 t23 -15t20 -13.5q20 -10 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55.5t-20 -57.5q12 -21 22.5 -34.5t28 -27t36.5 -17.5q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q101 -2 221 111q31 30 47 48t34 49t21 62q-14 9 -37.5 9.5t-35.5 7.5q-14 7 -49 15t-52 19 q-9 0 -39.5 -0.5t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q8 16 22 22q6 -1 26 -1.5t33.5 -4.5t19.5 -13q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5 t5.5 57.5q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 41 1 44q31 -13 58.5 -14.5t39.5 3.5l11 4q6 36 -17 53.5t-64 28.5t-56 23 q-19 -3 -37 0q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -46 0t-45 -3q-20 -6 -51.5 -25.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79zM518 915q3 12 16 30.5t16 25.5q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -18 8 -42.5t16.5 -44 t9.5 -23.5q-6 1 -39 5t-53.5 10t-36.5 16z" />
|
||||
<glyph unicode="" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
|
||||
<glyph unicode="" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
|
||||
<glyph unicode="" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM513 609q0 32 21 56.5t52 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-16 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5q-37 0 -62.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
|
||||
<glyph unicode="" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -79.5 -17t-67.5 -51l-388 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23q38 0 53 -36 q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60l517 511 q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
|
||||
<glyph unicode="" d="M79 784q0 131 99 229.5t230 98.5q144 0 242 -129q103 129 245 129q130 0 227 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100l-84.5 84.5t-68 74t-60 78t-33.5 70.5t-15 78z M250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-106 48.5q-73 0 -131 -83l-118 -171l-114 174q-51 80 -124 80q-59 0 -108.5 -49.5t-49.5 -118.5z" />
|
||||
<glyph unicode="" d="M57 353q0 -94 66 -160l141 -141q66 -66 159 -66q95 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-12 12 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141l19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -18q46 -46 77 -99l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
|
||||
<glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
|
||||
<glyph unicode="" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
|
||||
<glyph unicode="" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335l-27 7q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5v-307l64 -14 q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5zM700 237 q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
|
||||
<glyph unicode="" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -11 2.5 -24.5t5.5 -24t9.5 -26.5t10.5 -25t14 -27.5t14 -25.5 t15.5 -27t13.5 -24h242v-100h-197q8 -50 -2.5 -115t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q32 1 102 -16t104 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10 t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5t-30 142.5h-221z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
|
||||
<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
|
||||
<glyph unicode="" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
|
||||
<glyph unicode="" d="M216 519q10 -19 32 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8l9 -1q13 0 26 16l538 630q15 19 6 36q-8 18 -32 16h-300q1 4 78 219.5t79 227.5q2 17 -6 27l-8 8h-9q-16 0 -25 -15q-4 -5 -98.5 -111.5t-228 -257t-209.5 -238.5q-17 -19 -7 -40z" />
|
||||
<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
|
||||
<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 401h700v699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l248 -237v700h-699zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
|
||||
<glyph unicode="" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
|
||||
<glyph unicode="" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -117q-25 -16 -43.5 -50.5t-18.5 -65.5v-359z" />
|
||||
<glyph unicode="" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
|
||||
<glyph unicode="" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
|
||||
<glyph unicode="" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q16 17 13 40.5t-22 37.5l-192 136q-19 14 -45 12t-42 -19l-119 -118q-143 103 -267 227q-126 126 -227 268l118 118q17 17 20 41.5 t-11 44.5l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
|
||||
<glyph unicode="" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -15 -35.5t-35 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
|
||||
<glyph unicode="" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
|
||||
<glyph unicode="" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
|
||||
<glyph unicode="" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300 h200l-300 -300z" />
|
||||
<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104t60.5 178q0 121 -85 207.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
|
||||
<glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
|
||||
<glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -12t1 -11q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 61 KiB |
BIN
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.ttf
Normal file
BIN
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.ttf
Normal file
Binary file not shown.
BIN
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.woff
Normal file
BIN
fail/bin/VisualFAIL/fonts/glyphicons-halflings-regular.woff
Normal file
Binary file not shown.
BIN
fail/bin/VisualFAIL/images/ajax-loader.gif
Normal file
BIN
fail/bin/VisualFAIL/images/ajax-loader.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
BIN
fail/bin/VisualFAIL/images/hintergrund.png
(Stored with Git LFS)
Normal file
BIN
fail/bin/VisualFAIL/images/hintergrund.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
fail/bin/VisualFAIL/images/logos/danceoslogo.jpg
Normal file
BIN
fail/bin/VisualFAIL/images/logos/danceoslogo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
fail/bin/VisualFAIL/images/logos/visualfaillogo.png
(Stored with Git LFS)
Normal file
BIN
fail/bin/VisualFAIL/images/logos/visualfaillogo.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
fail/bin/VisualFAIL/images/logos/visualfaillogo_klein.png
(Stored with Git LFS)
Normal file
BIN
fail/bin/VisualFAIL/images/logos/visualfaillogo_klein.png
(Stored with Git LFS)
Normal file
Binary file not shown.
131
fail/bin/VisualFAIL/index.php
Normal file
131
fail/bin/VisualFAIL/index.php
Normal file
@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
|
||||
|
||||
<title>Visual FAIL*</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="css/myStyle.css" rel="stylesheet">
|
||||
|
||||
<!-- Just for debugging purposes. Don't actually copy this line! -->
|
||||
<!--[if lt IE 9]><script src="../../docs-assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
|
||||
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- Fixed navbar -->
|
||||
<div class="container-full">
|
||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<!--<div class="container"> -->
|
||||
<!--<a class="navbar-brand" href="#">Visual FAIL*</a>-->
|
||||
<img class="navbar-brand logo" src="images/logos/visualfaillogo_klein.png" alt="Visual FAIL* logo" />
|
||||
<!--</div>-->
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Result Mapping</a></li>
|
||||
<li><a href="#about">Aggregation</a></li>
|
||||
<!--
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tools <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="adminer-3.7.1.php" target="_blank">Adminer</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<!-- Main component for a primary marketing message or call to action -->
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Coloring</div>
|
||||
<div class="panel-body">
|
||||
<select class="form-control" id="faerbung">
|
||||
<option value="onlyRightEdge">Right margin (trace.instr2)</option>
|
||||
<option value="latestip">Last instruction (result.latest_ip)</option>
|
||||
<option value="normal">Equivalence classes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Benchmark</div>
|
||||
<div class="panel-body">
|
||||
<select class="form-control" id="binary">
|
||||
<option></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Variant</div>
|
||||
<div class="panel-body">
|
||||
<select class="form-control" id="variant">
|
||||
<option></option>
|
||||
</select>
|
||||
<div class="text-center">
|
||||
<button type="button" class="btn btn-default btn-lg" id="analyse">Analysis</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-10">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="btn-group" id="fehlertypenset" data-toggle="buttons">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<select class="form-control" id="sourceFiles">
|
||||
<option></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<pre class="container col-md-6" id="asm">
|
||||
</pre>
|
||||
<pre class="container col-md-6" id="hcode">
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /container-full -->
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
<script src="js/myscript.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
2006
fail/bin/VisualFAIL/js/bootstrap.js
vendored
Normal file
2006
fail/bin/VisualFAIL/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
fail/bin/VisualFAIL/js/bootstrap.min.js
vendored
Normal file
7
fail/bin/VisualFAIL/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
213
fail/bin/VisualFAIL/js/myscript.js
Normal file
213
fail/bin/VisualFAIL/js/myscript.js
Normal file
@ -0,0 +1,213 @@
|
||||
$.ajaxSetup({
|
||||
async: false
|
||||
});
|
||||
|
||||
|
||||
//Umwandlung von dezimal zu hexadezimal
|
||||
function dec2hex(dec) {
|
||||
var hex = "";
|
||||
|
||||
if (dec < 0) {
|
||||
dec = 0xFFFFFFFF + dec + 1;
|
||||
}
|
||||
|
||||
hex = parseInt(dec, 10).toString(16);
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
//Berechne den Farbwert (z.B.: #FFFFFF) fuer gegebene Fehlerwerte
|
||||
function calcColor(fehler, maxFehler) {
|
||||
//console.log("Farbe Fehler: " + fehler + " Max: " + maxFehler);
|
||||
|
||||
var part = 0;
|
||||
|
||||
if (fehler != 0) {
|
||||
var x = 255/Math.log(maxFehler);
|
||||
part = x*Math.log(fehler);
|
||||
}
|
||||
|
||||
//console.log("Farbe Fehler: " + fehler + " Max: " + maxFehler + " Part: " + part);
|
||||
|
||||
var brightness = 255 - part;
|
||||
var hex = dec2hex(brightness);
|
||||
|
||||
var colorcode;
|
||||
|
||||
if (brightness <= 0xf) {
|
||||
colorcode = "#FF" + "0" + hex + "0" + hex;
|
||||
} else {
|
||||
colorcode = "#FF" + hex + hex;
|
||||
}
|
||||
//console.log("Farbe Fehler: " + fehler + " Max: " + maxFehler + " Part: " + part + " Farbcode: " + colorcode);
|
||||
return colorcode;
|
||||
}
|
||||
|
||||
//Tooltip für Instruktionszeilen mit Fehler
|
||||
$('body').popover({
|
||||
selector: ".hasFehler",
|
||||
html: true,
|
||||
title: function() { return '0x' + $(this).attr("data-address"); },
|
||||
content: function() {
|
||||
var ausgabe = '';
|
||||
var caller = $(this);
|
||||
|
||||
$.getJSON("core.php", {cmd: 'getResultTypes'}, function(data) {
|
||||
$.each(data, function(key, val) {
|
||||
ausgabe = ausgabe + val +': ' + caller.attr(val) + '<br>';
|
||||
});
|
||||
});
|
||||
return ausgabe;
|
||||
}
|
||||
});
|
||||
|
||||
//Einblenden des Modal "Loading" fuer Ajax Requests
|
||||
/*$(document).ajaxStart(function(){
|
||||
//console.log("ajaxstart");
|
||||
$("body").addClass("loading");
|
||||
}).ajaxStop(function(){
|
||||
//console.log("ajaxstop");
|
||||
$("body").removeClass("loading");
|
||||
});*/
|
||||
|
||||
//User-Interaktionen nachdem das DOM geladen ist
|
||||
$(document).ready(function() {
|
||||
|
||||
//DB check
|
||||
$.getJSON("core.php", {cmd: 'dbTest'}, function(data) {
|
||||
|
||||
if(data != "ok") {
|
||||
$('html').html(data);
|
||||
}
|
||||
});
|
||||
|
||||
//Holen der Binarys, die in der DB in der Tabelle Variant vorkommen
|
||||
$.getJSON("core.php", {cmd: 'getBinarys'}, function(data) {
|
||||
$.each(data, function(key, val) {
|
||||
$('#binary').append('<option value="' + val + '">' + val + '</option>');
|
||||
});
|
||||
});
|
||||
|
||||
//Auswahl eines Eintrages aus den Source-Files für die Darstellung des Hochsprachencode
|
||||
$('#sourceFiles').change(function() {
|
||||
if($(this).val() != 'none') {
|
||||
$.getJSON("core.php", {cmd: 'getHighlevelCode', variant_id: $('#variant').val(), file_id: $(this).val(), version: $('#faerbung').val()}, function(data) {
|
||||
|
||||
$('#hcode').html(data);
|
||||
|
||||
$('.maxFehlerMapping').on( "calcColor", function( event, newMaxFehler, activeFehlertypes) {
|
||||
var newFehler = 0;
|
||||
var actualRow = $(this);
|
||||
|
||||
$.each(activeFehlertypes, function(key, val) {
|
||||
newFehler = newFehler + parseInt(actualRow.attr(val));
|
||||
});
|
||||
|
||||
// console.log("jepp" + newMaxFehler + " " + newFehler);
|
||||
|
||||
$(this).prev().prev().prev().css("background-color", calcColor(newFehler, newMaxFehler))
|
||||
.css('cursor', 'pointer');
|
||||
});
|
||||
|
||||
$('.hasFehler').on( "calcColor", function( event, newMaxFehler, activeFehlertypes) {
|
||||
var newFehler = 0;
|
||||
var actualRow = $(this);
|
||||
|
||||
$.each(activeFehlertypes, function(key, val) {
|
||||
newFehler = newFehler + parseInt(actualRow.attr(val));
|
||||
});
|
||||
|
||||
$(this).css("background-color", calcColor(newFehler, newMaxFehler))
|
||||
.css('cursor', 'pointer');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
setTimeout(function(){
|
||||
var activeFehlertypes = new Array();
|
||||
var newMaxFehler = 0;
|
||||
|
||||
$('#fehlertypenset > .active').each(function(){
|
||||
activeFehlertypes.push($(this).attr("id"));
|
||||
//console.log("Hinzugefuegt: " + $(this).attr("id"));
|
||||
});
|
||||
|
||||
|
||||
$.each(activeFehlertypes,function(key, name){
|
||||
|
||||
//Neuen MaxFehler berechnen
|
||||
newMaxFehler = newMaxFehler + parseInt($('#maxFehler').attr(name));
|
||||
});
|
||||
$('.hasFehler').trigger('calcColor', [ newMaxFehler, activeFehlertypes ]);
|
||||
$('.maxFehlerMapping').trigger('calcColor', [ newMaxFehler, activeFehlertypes ]);
|
||||
},100);
|
||||
}
|
||||
});
|
||||
|
||||
//Auswahl eines Eintrages aus den Binarys für die Darstellung des Assembler-Code
|
||||
$('#binary').change(function() {
|
||||
if($(this).val() != 'none') {
|
||||
$('#variant').html('<option value="none" selected="selected"></option>');
|
||||
$.getJSON("core.php", {cmd: 'getVariants', datei: $(this).val()}, function(data) {
|
||||
$.each(data, function(key, val) {
|
||||
$('#variant').append('<option value="' + key + '">' + val + '</option>');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//Analyse Button wird gedrueckt
|
||||
$('#analyse').button().click( function () {
|
||||
|
||||
$.getJSON("core.php", {cmd: 'getAsmCode', variant_id: $('#variant').val(), version: $('#faerbung').val()}, function(data) {
|
||||
$('#asm').html(data);
|
||||
});
|
||||
|
||||
$.getJSON("core.php", {cmd: 'getSourceFiles', variant_id: $('#variant').val()}, function(data) {
|
||||
$.each(data, function(key, val) {
|
||||
$('#sourceFiles').append('<option value="' + key + '">' + val + '</option>');
|
||||
});
|
||||
});
|
||||
|
||||
$.getJSON("core.php", {cmd: 'getResultTypes'}, function(data) {
|
||||
|
||||
$('#fehlertypenset').html('');
|
||||
$.each(data, function(key, val) {
|
||||
$('#fehlertypenset').append('<label class="btn btn-default" id="' + val + '"><input type="checkbox" id="' + val + '">' + val + '</label>');
|
||||
//$('#'+ val +'.btn').button('toggle');
|
||||
});
|
||||
|
||||
$('.hasFehler').on( "calcColor", function( event, newMaxFehler, activeFehlertypes) {
|
||||
var newFehler = 0;
|
||||
var actualRow = $(this);
|
||||
|
||||
$.each(activeFehlertypes, function(key, val) {
|
||||
newFehler = newFehler + parseInt(actualRow.attr(val));
|
||||
});
|
||||
|
||||
$(this).css("background-color", calcColor(newFehler, newMaxFehler))
|
||||
.css('cursor', 'pointer');
|
||||
});
|
||||
|
||||
//Auf Änderungen bzgl. des Fehler-Buttonset horchen
|
||||
$('#fehlertypenset input[type=checkbox]').change(function() {setTimeout(function(){
|
||||
//console.log("aenderung!");
|
||||
var activeFehlertypes = new Array();
|
||||
var newMaxFehler = 0;
|
||||
|
||||
$('#fehlertypenset > .active').each(function(){
|
||||
activeFehlertypes.push($(this).attr("id"));
|
||||
});
|
||||
|
||||
|
||||
$.each(activeFehlertypes,function(key, name){
|
||||
//Neuen MaxFehler berechnen
|
||||
newMaxFehler = newMaxFehler + parseInt($('#maxFehler').attr(name));
|
||||
});
|
||||
|
||||
$('.hasFehler').trigger('calcColor', [ newMaxFehler, activeFehlertypes ]);
|
||||
$('.maxFehlerMapping').trigger('calcColor', [ newMaxFehler, activeFehlertypes ]);
|
||||
},100)});
|
||||
});
|
||||
});
|
||||
});
|
||||
147
fail/bin/bochs-experiment-runner.py
Executable file
147
fail/bin/bochs-experiment-runner.py
Executable file
@ -0,0 +1,147 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import os, sys
|
||||
from optparse import OptionParser
|
||||
from subprocess import *
|
||||
from tempfile import mkstemp, mkdtemp
|
||||
import shutil
|
||||
from distutils.spawn import find_executable
|
||||
import os.path
|
||||
|
||||
def parseArgs():
|
||||
parser = OptionParser()
|
||||
parser.add_option("-e", "--elf-file", dest="elf_file",
|
||||
help="elf file to be executed", metavar="ELF")
|
||||
parser.add_option("-i", "--iso-file", dest="iso_file",
|
||||
help="iso file to be executed", metavar="ISO")
|
||||
parser.add_option("-f", "--fail-client", dest="fail_client",
|
||||
help="fail-client to be executed", metavar="ISO")
|
||||
parser.add_option("-m", "--memory", dest="memory", default="16",
|
||||
help="memory for the bochs VM", metavar="SIZE")
|
||||
|
||||
parser.add_option("-b", "--bios", dest="bios", default="/fs/proj/i4ezs/tools/fail-ws21/buildartifacts/BIOS-bochs-latest",
|
||||
help="bios image for bochs", metavar="BIOS")
|
||||
|
||||
parser.add_option("-V", "--vgabios", dest="vgabios", default="/fs/proj/i4ezs/tools/fail-ws21/buildartifacts/vgabios.bin",
|
||||
help="vgabios image for bochs", metavar="VGABIOS")
|
||||
|
||||
parser.add_option("-F", "--freq", dest="freq", default="5",
|
||||
help="frquency in MHZ", metavar="MHZ")
|
||||
|
||||
parser.add_option("-1", "--once",
|
||||
action="store_false", dest="forever", default=True,
|
||||
help="fail-client to be executed")
|
||||
|
||||
parser.add_option("-j", "--jobs",
|
||||
dest="jobs", default="1",
|
||||
help="parallel execution")
|
||||
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if not (options.elf_file and options.iso_file and options.fail_client):
|
||||
parser.error("elf, iso and fail-client are required")
|
||||
|
||||
return options, args
|
||||
|
||||
def execute(options, args, bochsrc, statedir):
|
||||
failcmd = options.fail_client
|
||||
command = "FAIL_ELF_PATH=%s FAIL_STATEDIR=%s %s -q -f %s %s" % \
|
||||
(options.elf_file, statedir, failcmd, bochsrc, " ".join(args))
|
||||
print("executing: " + command)
|
||||
p = Popen(command, shell=True, stdout=PIPE, stderr=STDOUT)
|
||||
reconnect = 0
|
||||
while p.poll() is None:
|
||||
line = p.stdout.readline()
|
||||
if line is None:
|
||||
break
|
||||
if "Connection refused" in line.decode("utf-8", "ignore"):
|
||||
reconnect += 1
|
||||
print(line),
|
||||
if reconnect > 10:
|
||||
return 1
|
||||
p.wait()
|
||||
|
||||
if reconnect > 0:
|
||||
return 123
|
||||
return p.returncode
|
||||
|
||||
def main(options, args):
|
||||
bochsrc_args = {
|
||||
"memory": options.memory,
|
||||
"bios": options.bios,
|
||||
"vgabios": options.vgabios,
|
||||
"iso": options.iso_file,
|
||||
"ips": int(options.freq) * 1000000,
|
||||
}
|
||||
|
||||
bochsrc_text = """
|
||||
config_interface: textconfig
|
||||
display_library: nogui
|
||||
romimage: file="{bios}"
|
||||
cpu: count=1, ips={ips}, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def"
|
||||
cpuid: mmx=1, sep=1, sse=sse4_2, xapic=1, aes=1, movbe=1, xsave=1, cpuid_limit_winnt=0
|
||||
memory: guest={memory}, host={memory}
|
||||
vgaromimage: file="{vgabios}"
|
||||
vga: extension=vbe
|
||||
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15
|
||||
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
|
||||
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
|
||||
ata0-slave: type=cdrom, path="{iso}", status=inserted
|
||||
port_e9_hack: enabled=1
|
||||
com1: enabled=1, mode=file, dev=serial.out
|
||||
boot: cdrom
|
||||
clock: sync=none, time0=946681200
|
||||
floppy_bootsig_check: disabled=0
|
||||
panic: action=fatal
|
||||
error: action=fatal
|
||||
info: action=ignore
|
||||
debug: action=ignore
|
||||
pass: action=ignore
|
||||
debugger_log: -
|
||||
parport1: enabled=0
|
||||
vga_update_interval: 300000
|
||||
keyboard_serial_delay: 250
|
||||
keyboard_paste_delay: 100000
|
||||
private_colormap: enabled=0
|
||||
i440fxsupport: enabled=0, slot1=pcivga
|
||||
""".format(**bochsrc_args)
|
||||
|
||||
bochsrc = mkstemp()
|
||||
fd = os.fdopen(bochsrc[0], "w")
|
||||
fd.write(bochsrc_text)
|
||||
fd.close()
|
||||
bochsrc = bochsrc[1]
|
||||
|
||||
statedir = mkdtemp()
|
||||
|
||||
if options.forever:
|
||||
while True:
|
||||
res = execute(options, args, bochsrc, statedir)
|
||||
if res != 0:
|
||||
break
|
||||
|
||||
ret = 0
|
||||
else:
|
||||
ret = execute(options, args, bochsrc, statedir)
|
||||
|
||||
os.unlink(bochsrc)
|
||||
shutil.rmtree(statedir)
|
||||
sys.exit(ret)
|
||||
|
||||
if __name__ == "__main__":
|
||||
(options, args) = parseArgs()
|
||||
|
||||
import threading
|
||||
i = 1
|
||||
# n-1 jobs in threads
|
||||
while i < int(options.jobs):
|
||||
fred = threading.Thread(target = main, args = (options, args))
|
||||
fred.start()
|
||||
print("starting: "+str(i))
|
||||
i = i + 1
|
||||
|
||||
main(options, args)
|
||||
|
||||
|
||||
BIN
fail/bin/fail-x86-tracing
(Stored with Git LFS)
Executable file
BIN
fail/bin/fail-x86-tracing
(Stored with Git LFS)
Executable file
Binary file not shown.
BIN
fail/bin/generic-experiment-client
(Stored with Git LFS)
Executable file
BIN
fail/bin/generic-experiment-client
(Stored with Git LFS)
Executable file
Binary file not shown.
BIN
fail/bin/generic-experiment-server
(Stored with Git LFS)
Executable file
BIN
fail/bin/generic-experiment-server
(Stored with Git LFS)
Executable file
Binary file not shown.
BIN
fail/bin/import-trace
(Stored with Git LFS)
Executable file
BIN
fail/bin/import-trace
(Stored with Git LFS)
Executable file
Binary file not shown.
BIN
fail/bin/prune-trace
(Stored with Git LFS)
Executable file
BIN
fail/bin/prune-trace
(Stored with Git LFS)
Executable file
Binary file not shown.
1
fail/bin/resultbrowser.py
Symbolic link
1
fail/bin/resultbrowser.py
Symbolic link
@ -0,0 +1 @@
|
||||
./resultbrowser/run.py
|
||||
19
fail/bin/resultbrowser/README
Normal file
19
fail/bin/resultbrowser/README
Normal file
@ -0,0 +1,19 @@
|
||||
FAIL* Result Browser
|
||||
|
||||
Requirements:
|
||||
* Python
|
||||
* Flask (sudo pip install Flask)
|
||||
* MySQLDB (sudo aptitude install python-mysqldb)
|
||||
* YAML (sudo aptitude install python-yaml)
|
||||
|
||||
Based on Flask web microframework (Werkzeug, Jinja 2)
|
||||
and old school MySQL bindings.
|
||||
|
||||
Connects to a FAIL* result database given by a mysql config file.
|
||||
|
||||
Usage:
|
||||
./run.py
|
||||
Defaults to mysql config file ~/.my.cnf, or
|
||||
./run.py -c <path to sqlconfig.cnf>
|
||||
|
||||
YAML based configuration for table and variant details.
|
||||
4
fail/bin/resultbrowser/app/__init__.py
Normal file
4
fail/bin/resultbrowser/app/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from flask import Flask
|
||||
|
||||
app = Flask(__name__)
|
||||
from app import views
|
||||
143
fail/bin/resultbrowser/app/data.py
Normal file
143
fail/bin/resultbrowser/app/data.py
Normal file
@ -0,0 +1,143 @@
|
||||
from pprint import pprint
|
||||
from . import details
|
||||
from . import model
|
||||
|
||||
def scrub(table_name):
|
||||
return ''.join( chr for chr in table_name if chr.isalnum() or chr == '_' )
|
||||
|
||||
class Resulttype:
|
||||
def __init__(self, name, count):
|
||||
self.name = name
|
||||
self.count = count
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getCount(self):
|
||||
return self.count
|
||||
|
||||
class Variant:
|
||||
def __init__(self, id, name, table, benchmark, detail):
|
||||
self.id = id
|
||||
self.dbname = name
|
||||
self.parenttable = table # TableDetails
|
||||
self.details = detail # VariantDetails
|
||||
self.benchmark = benchmark # BenchmarkDetails
|
||||
self.results = {}
|
||||
self.totalresults = 0
|
||||
|
||||
|
||||
def getMapper(self):
|
||||
mapper = self.benchmark.getMapper()
|
||||
if not mapper: #try benchmark mapper
|
||||
mapper = self.details.getMapper()
|
||||
if not mapper: # of not there, try parent tables mapper
|
||||
mapper = self.parenttable.getMapper()
|
||||
if not mapper: # no mapper found at all, try default mapper
|
||||
mapper = model.detaildealer.getDefaultMapper()
|
||||
return mapper
|
||||
|
||||
|
||||
def addResulttype(self, name, count):
|
||||
mapper = self.getMapper()
|
||||
label = mapper.getLabel(name)
|
||||
oldcount = self.results.setdefault(label, 0)
|
||||
self.results[label] = oldcount + count
|
||||
self.totalresults += count
|
||||
|
||||
def getResultLabels(self):
|
||||
return self.results.keys()
|
||||
|
||||
def getDBName(self):
|
||||
return str(self.name)
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
def getResults(self):
|
||||
return self.results
|
||||
|
||||
def getTableDetails(self):
|
||||
return self.parenttable
|
||||
|
||||
def getBenchmarkDetails(self):
|
||||
return self.benchmark
|
||||
|
||||
def getDetails(self):
|
||||
return self.details
|
||||
|
||||
def getTotals(self):
|
||||
return self.totalresults
|
||||
|
||||
def __str__(self):
|
||||
ret = "Variant: " + self.getDetails().getTitle() + " - " + self.getBenchmarkDetails().getTitle() +" (id: " + str( self.id )+ ")" + " "
|
||||
ret += "Total Results: " + str( self.totalresults ) + "\n"
|
||||
for v in self.results:
|
||||
ret += "\t" + v.name + ": " + str( v.count ) + "\n"
|
||||
return ret
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
'''A ResultTable contains n Variants'''
|
||||
class ResultTable:
|
||||
|
||||
def __init__(self, name, cfg):
|
||||
self.name = scrub(name)
|
||||
self.details = cfg.getTable(name)
|
||||
self.variants = {}
|
||||
|
||||
def addVariant(self, var):
|
||||
if var.getId() in self.variants:
|
||||
return
|
||||
self.variants[var.getId()] = var # Add if not existing yet
|
||||
|
||||
def getVariant(self, id):
|
||||
if id in self.variants:
|
||||
return self.variants[id]
|
||||
return None
|
||||
|
||||
def getVariantById(self, varid):
|
||||
for k,v in self.variants.items():
|
||||
if int(v.getId()) == int(varid):
|
||||
return v
|
||||
return None
|
||||
|
||||
def getDetails(self):
|
||||
return self.details
|
||||
|
||||
def getVariants(self):
|
||||
return self.variants
|
||||
|
||||
def __str__(self):
|
||||
ret = "Result: " + self.getDetails().getTitle() + "\n"
|
||||
for k,v in self.variants.items():
|
||||
ret += "\t" + str(v) + "\n"
|
||||
return ret
|
||||
__repr__ = __str__
|
||||
|
||||
'''Overview has n ResultTables'''
|
||||
class Overview:
|
||||
def __init__(self):
|
||||
self.tables = {}
|
||||
|
||||
def add(self, table):
|
||||
self.tables[table.getDetails().getDBName()] = table
|
||||
|
||||
def getTables(self):
|
||||
return self.tables
|
||||
|
||||
def getTable(self, dbname):
|
||||
return self.tables.get(dbname, None)
|
||||
|
||||
def getVariantById(self, variant_id):
|
||||
for key,table in self.tables.items():
|
||||
variant = table.getVariantById(variant_id)
|
||||
if variant:
|
||||
return variant
|
||||
print("Variant not found.")
|
||||
return None
|
||||
|
||||
def length(self):
|
||||
return len(self.tables)
|
||||
|
||||
|
||||
216
fail/bin/resultbrowser/app/details.py
Normal file
216
fail/bin/resultbrowser/app/details.py
Normal file
@ -0,0 +1,216 @@
|
||||
|
||||
class BasicDetails(object):
|
||||
|
||||
def __init__(self,name):
|
||||
self.dbname = name
|
||||
self.title = name
|
||||
self.details = ''
|
||||
self.mapper = None
|
||||
|
||||
def getDBName(self):
|
||||
return self.dbname
|
||||
|
||||
def getDetails(self):
|
||||
return self.details
|
||||
|
||||
def setDetails(self,det):
|
||||
self.details = det
|
||||
|
||||
def getTitle(self):
|
||||
return self.title
|
||||
|
||||
def addMapper(self, mapper):
|
||||
self.mapper = mapper
|
||||
|
||||
def getMapper(self):
|
||||
return self.mapper
|
||||
|
||||
def extractDetails(self, dictionary):
|
||||
self.details = dictionary.pop(('details'), '')
|
||||
self.title = dictionary.pop(('title'), self.dbname)
|
||||
custommapping = dictionary.pop(('mapping'), None)
|
||||
if custommapping:
|
||||
self.mapper = ResulttypeMapper()
|
||||
self.mapper.add(custommapping)
|
||||
else:
|
||||
self.mapper = None
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return self.getTitle() + ": " + self.getDetails()
|
||||
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
|
||||
class BenchmarkDetails(BasicDetails):
|
||||
|
||||
def __init__(self, dbname):
|
||||
BasicDetails.__init__(self, dbname)
|
||||
|
||||
def __repr__(self):
|
||||
return "Benchmark: " + BasicDetails.__repr__(self)
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
|
||||
class VariantDetails(BasicDetails):
|
||||
|
||||
def __init__(self, dbname):
|
||||
BasicDetails.__init__(self, dbname)
|
||||
self.benchmarks = {}
|
||||
|
||||
def addBenchmark(self, bm):
|
||||
self.benchmarks[bm.getDBName()] = bm
|
||||
|
||||
def getBenchmark(self, dbbm):
|
||||
return self.benchmarks.get(dbbm, BenchmarkDetails(dbbm))
|
||||
|
||||
def __repr__(self):
|
||||
ret = "Variant: " + BasicDetails.__repr__(self)
|
||||
for v in self.benchmarks.values():
|
||||
ret += "\n\t\t" + str(v)
|
||||
return ret
|
||||
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
class TableDetails(BasicDetails):
|
||||
|
||||
def __init__(self, tbl):
|
||||
BasicDetails.__init__(self, tbl)
|
||||
self.variants = {}
|
||||
|
||||
def addVariant(self, var):
|
||||
self.variants[var.getDBName()] = var
|
||||
|
||||
def getVariant(self, varname):
|
||||
return self.variants.get(varname, VariantDetails(varname))
|
||||
|
||||
def __repr__(self):
|
||||
ret = "Table: " + BasicDetails.__repr__(self) + "(" + self.getDBName() + ")"
|
||||
for v in self.variants.values():
|
||||
ret += "\n\t" + str(v)
|
||||
return ret
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
class ResulttypeMapper(object):
|
||||
|
||||
def __init__(self):
|
||||
self.mappings = {}
|
||||
|
||||
def add(self, mapping):
|
||||
for label, dbnamelist in mapping.items():
|
||||
self.mappings[label] = dbnamelist
|
||||
|
||||
def getLabel(self, dbname):
|
||||
for label, dbnamelist in self.mappings.items():
|
||||
if dbname in dbnamelist:
|
||||
return label
|
||||
return dbname
|
||||
|
||||
def getLabelList(self):
|
||||
return self.mappings.keys()
|
||||
|
||||
def getDBNames(self, label):
|
||||
return self.mappings.get(label, None)
|
||||
|
||||
def __repr__(self):
|
||||
ret = "Resulttype Mapper:"
|
||||
for label,dbnames in self.mappings.items():
|
||||
ret += "\n\t" + label
|
||||
for db in dbnames:
|
||||
ret += "\n\t\t" + db
|
||||
return ret
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
import yaml
|
||||
class DetailDealer:
|
||||
|
||||
def __init__(self, configfile=None):
|
||||
self.tables = {}
|
||||
self.defaultMapper = ResulttypeMapper()
|
||||
|
||||
if not configfile:
|
||||
return
|
||||
self.reload(configfile)
|
||||
|
||||
if not self.tables:
|
||||
print("DetailDealer: no details found for " + configfile)
|
||||
|
||||
def reload(self, configfile):
|
||||
self.tables = {}
|
||||
self.defaultMapper = ResulttypeMapper()
|
||||
if not configfile:
|
||||
return # no details.
|
||||
f = open(configfile)
|
||||
# use safe_load instead load
|
||||
cfg = yaml.safe_load(f)
|
||||
f.close()
|
||||
# Read out default mapping, if existent
|
||||
self.extractDefaults(cfg)
|
||||
tables = cfg.pop('tables', None)
|
||||
if tables:
|
||||
for tablename,details in tables.items():
|
||||
tab = TableDetails(tablename)
|
||||
# pop: return and remove when key present, else return 'notfound'
|
||||
tab.extractDetails(details)
|
||||
variants = details.pop('variants')
|
||||
for variantname, vdetails in variants.items():
|
||||
var = VariantDetails(variantname)
|
||||
var.extractDetails(vdetails)
|
||||
benchmarks = vdetails.pop('benchmarks')
|
||||
for benchmark, bdetails in benchmarks.items():
|
||||
bm = BenchmarkDetails(benchmark)
|
||||
bm.extractDetails(bdetails)
|
||||
var.addBenchmark(bm)
|
||||
tab.addVariant(var)
|
||||
self.tables[tab.getDBName()] = (tab)
|
||||
|
||||
|
||||
def extractDefaults(self, cfg):
|
||||
defs = cfg.pop('defaults', None)
|
||||
if defs:
|
||||
defmap = defs.pop('mapping', None)
|
||||
if defmap:
|
||||
self.defaultMapper.add(defmap)
|
||||
|
||||
def getDefaultMapper(self):
|
||||
return self.defaultMapper
|
||||
|
||||
def getTable(self, tablename):
|
||||
tab = self.tables.get(tablename, None)
|
||||
if tab:
|
||||
return tab
|
||||
return TableDetails(tablename)
|
||||
|
||||
def getVariant(self, tablename, variantname):
|
||||
tab = self.getTable(tablename)
|
||||
if tab:
|
||||
return tab.getVariant(variantname)
|
||||
return VariantDetails(variantname) # Default
|
||||
|
||||
def getBenchmark(self, table, variant, bechmark):
|
||||
tab = self.getTable(table)
|
||||
if tab:
|
||||
var = tab.getVariant(variant)
|
||||
if var:
|
||||
return var.getBenchmark(bechmark)
|
||||
return BenchmarkDetails(benchmark) # Default
|
||||
|
||||
def __repr__(self):
|
||||
ret = str(self.defaultMapper) + '\n'
|
||||
for tabledetails in self.tables.values():
|
||||
ret += str(tabledetails) + '\n'
|
||||
return ret
|
||||
|
||||
if __name__ == "__main__":
|
||||
dd = DetailDealer('./test.yml')
|
||||
pprint(dd)
|
||||
211
fail/bin/resultbrowser/app/model.py
Executable file
211
fail/bin/resultbrowser/app/model.py
Executable file
@ -0,0 +1,211 @@
|
||||
#!/usr/bin/env python
|
||||
import MySQLdb
|
||||
import MySQLdb.cursors
|
||||
import yaml
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
from pprint import pprint
|
||||
from . import data
|
||||
from . import details
|
||||
|
||||
"""Get command line options"""
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser()
|
||||
parser.add_option("-c", "--conf", type="string", help="MySQL config file", dest="config", default= os.path.join(os.path.expanduser("~"),".my.cnf"))
|
||||
parser.add_option("-s", "--host", type="string", help="Webserver hostname", dest="host", default="localhost")
|
||||
parser.add_option("-d", "--details", type="string", help="Detailed information (YAML configuration file)", dest="details", default=None)
|
||||
parser.add_option("-p", "--port", type="string", help="Webserver port", dest="port", default="5000")
|
||||
opts, args = parser.parse_args()
|
||||
|
||||
"""Check if configuration files exist"""
|
||||
def checkConfigFile(msg, fname):
|
||||
if not os.path.isfile(fname):
|
||||
sys.exit("Error: '" + fname + "' not found")
|
||||
else:
|
||||
print(msg, "->", fname)
|
||||
|
||||
# Check sql config
|
||||
sqlconfig = opts.config
|
||||
checkConfigFile("MySQL config", sqlconfig)
|
||||
|
||||
# Check details file
|
||||
if opts.details:
|
||||
checkConfigFile("Details", opts.details)
|
||||
|
||||
# Instantiate global detail dealer, will be initialized in reloadOverview
|
||||
detaildealer = details.DetailDealer()
|
||||
|
||||
|
||||
"""Remove all characters from string except alphanuermics and _"""
|
||||
def scrub(table_name):
|
||||
return ''.join( chr for chr in table_name if chr.isalnum() or chr == '_' )
|
||||
|
||||
"""Global mysql handles"""
|
||||
db = None
|
||||
cur = None
|
||||
def loadSession(dbconf):
|
||||
global db
|
||||
if db:
|
||||
db.close()
|
||||
db = MySQLdb.connect(read_default_file=dbconf, cursorclass=MySQLdb.cursors.DictCursor)
|
||||
return db.cursor()
|
||||
|
||||
|
||||
def closeSession():
|
||||
if cur: cur.close()
|
||||
global db
|
||||
db.close()
|
||||
db = None
|
||||
|
||||
|
||||
'''Populate variant results for overview data'''
|
||||
def getVariants(cur, table):
|
||||
restbl = table.getDetails().getDBName()
|
||||
cur.execute("""SELECT sum((t.time2 - t.time1 + 1) * width) AS total, resulttype,variant, v.id as variant_id, benchmark, details FROM variant v JOIN trace t ON v.id = t.variant_id JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address JOIN %s r ON r.pilot_id = g.pilot_id JOIN fsppilot p ON r.pilot_id = p.id GROUP BY v.id, resulttype, details""" % (restbl)) # % is used here, as a tablename must not be quoted
|
||||
res = cur.fetchall()
|
||||
rdic = {}
|
||||
# Build dict with variant id as key
|
||||
for r in res:
|
||||
# if variant entry already exists:
|
||||
variant = table.getVariant(int(r['variant_id']))
|
||||
if not variant: # if variant did not exist yet, create it:
|
||||
variant_details = detaildealer.getVariant(restbl, r['variant'])
|
||||
benchmark_details = detaildealer.getBenchmark(restbl, r['variant'], r['benchmark'])
|
||||
table_details = detaildealer.getTable(restbl)
|
||||
variant = data.Variant(int(r['variant_id']), r['variant'], table_details, benchmark_details, variant_details)
|
||||
variant.addResulttype(r['resulttype'], r['total'])
|
||||
table.addVariant(variant)
|
||||
|
||||
'''Get overview data for index page'''
|
||||
def reloadOverview():
|
||||
overview = data.Overview()
|
||||
detaildealer.reload(opts.details)
|
||||
cur = loadSession(sqlconfig)
|
||||
cur.execute("show tables like 'result_%'")
|
||||
result_tables = cur.fetchall()
|
||||
results = {}
|
||||
for rdic in result_tables:
|
||||
# r is the tablename, -> result_FOOBAR
|
||||
for key, tablename in rdic.items():
|
||||
table = data.ResultTable(tablename,detaildealer)
|
||||
getVariants(cur, table)
|
||||
overview.add(table)
|
||||
# Check if objdump table exists
|
||||
cur.execute("SHOW TABLES like 'objdump'")
|
||||
objdump_exists = (len(cur.fetchall()) == 1)
|
||||
closeSession()
|
||||
return overview, objdump_exists
|
||||
|
||||
"""Load overview data at server startup"""
|
||||
print("Loading overview data from database. This may take a while ...")
|
||||
overview_data, objdump_exists = reloadOverview()
|
||||
print("done.")
|
||||
## Get overview data for views.index()
|
||||
def getOverview():
|
||||
return overview_data
|
||||
|
||||
def objdumpExists():
|
||||
return objdump_exists
|
||||
|
||||
|
||||
"""Get Results for one variant id"""
|
||||
def getVariantResult(table, variantid):
|
||||
cur = loadSession(sqlconfig)
|
||||
restbl = scrub(table)
|
||||
|
||||
stmt = "SELECT resulttype, count(*) as total from %s r join fsppilot on r.pilot_id=fsppilot.id join variant on fsppilot.variant_id=variant.id" % (restbl)
|
||||
where = " WHERE variant.id = %s group by resulttype ORDER BY resulttype "
|
||||
stmt = stmt + where
|
||||
cur.execute(stmt, variantid)
|
||||
res = cur.fetchall()
|
||||
closeSession()
|
||||
return res
|
||||
|
||||
'''Show objdump together with according injection result types.'''
|
||||
def getCode(result_table, variant_id, resultlabel=None):
|
||||
result_table = scrub(result_table)
|
||||
filt = ''
|
||||
if not variant_id or not result_table:
|
||||
return None
|
||||
variant = overview_data.getVariantById(variant_id)
|
||||
mapper = variant.getMapper()
|
||||
if resultlabel:
|
||||
dbnames = mapper.getDBNames(resultlabel)
|
||||
if dbnames:
|
||||
filt = " and ( "
|
||||
for dbn in dbnames[:-1]:
|
||||
filt += "resulttype = '" + dbn + "' OR "
|
||||
filt += "resulttype = '" + dbnames[-1] +"' ) "
|
||||
else:
|
||||
filt = " and resulttype = '" + resultlabel + "' "
|
||||
|
||||
# I especially like this one:
|
||||
select = "SELECT instr_address, opcode, disassemble, comment, sum(t.time2 - t.time1 + 1) as totals, GROUP_CONCAT(DISTINCT resulttype SEPARATOR ', ') as results FROM variant v "
|
||||
join = " JOIN trace t ON v.id = t.variant_id JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_address = t.data_address JOIN %s r ON r.pilot_id = g.pilot_id JOIN fsppilot p ON r.pilot_id = p.id JOIN objdump ON objdump.variant_id = v.id AND objdump.instr_address = injection_instr_absolute " %(scrub(result_table))
|
||||
where = "WHERE v.id = %s "
|
||||
group = "GROUP BY injection_instr_absolute ORDER BY totals DESC "
|
||||
|
||||
cur = loadSession(sqlconfig)
|
||||
stmt = select + join + where + filt + group
|
||||
cur.execute(stmt, (variant_id))
|
||||
dump = cur.fetchall()
|
||||
|
||||
closeSession()
|
||||
resulttypes = variant.getResultLabels()
|
||||
return dump, resulttypes
|
||||
|
||||
def getCodeExcerpt(variant_id, instr_addr):
|
||||
code = {}
|
||||
limit = 8
|
||||
cur = loadSession(sqlconfig)
|
||||
cur.execute( """(SELECT instr_address, opcode, disassemble, comment FROM objdump \
|
||||
WHERE instr_address < %s AND variant_id = %s \
|
||||
ORDER BY instr_address DESC LIMIT %s) \
|
||||
ORDER BY instr_address ASC""" , (instr_addr, variant_id, limit))
|
||||
below = cur.fetchall()
|
||||
code['below'] = below
|
||||
cur.execute("""SELECT instr_address, opcode, disassemble, comment FROM objdump \
|
||||
WHERE instr_address >= %s AND variant_id = %s \
|
||||
ORDER BY instr_address ASC LIMIT %s""", (instr_addr, variant_id, limit+1))
|
||||
upper = cur.fetchall()
|
||||
code['upper'] = upper
|
||||
closeSession()
|
||||
return code
|
||||
|
||||
def getResultsbyInstruction(result_table, variant_id, instr_addr, resultlabel=None):
|
||||
restypefilter = None
|
||||
if resultlabel:
|
||||
variant = overview_data.getVariantById(variant_id)
|
||||
mapper = variant.getMapper()
|
||||
if resultlabel:
|
||||
dbnames = mapper.getDBNames(resultlabel)
|
||||
if dbnames:
|
||||
restypefilter = " and ( "
|
||||
for dbn in dbnames[:-1]:
|
||||
restypefilter += "resulttype = '" + dbn + "' OR "
|
||||
restypefilter += "resulttype = '" + dbnames[-1] +"' ) "
|
||||
|
||||
select = "SELECT bitoffset as 'Bit Offset', hex(injection_instr_absolute) as 'Instruction Address', hex(original_value) as 'Original Value', hex(data_address) as 'Data Address', resulttype as 'Result Type', details as 'Details' from %s " % scrub(result_table)
|
||||
join = "JOIN fsppilot ON pilot_id = fsppilot.id "
|
||||
where = "WHERE variant_id = %s and injection_instr_absolute = %s "
|
||||
order = "ORDER BY data_address, bitoffset"
|
||||
|
||||
cur = loadSession(sqlconfig)
|
||||
if not restypefilter:
|
||||
stmt = select + join + where + order
|
||||
cur.execute(stmt, (variant_id, instr_addr))
|
||||
else:
|
||||
stmt = select + join + where + restypefilter + order
|
||||
cur.execute(stmt, (variant_id, instr_addr))
|
||||
|
||||
res = cur.fetchall()
|
||||
closeSession()
|
||||
return res
|
||||
|
||||
def showDBstatus():
|
||||
res = "TODO"
|
||||
return res
|
||||
|
||||
|
||||
5
fail/bin/resultbrowser/app/static/css/barchart.css
Normal file
5
fail/bin/resultbrowser/app/static/css/barchart.css
Normal file
@ -0,0 +1,5 @@
|
||||
dl.horizontal {font-size:12px; width:850px;}
|
||||
dl.horizontal dt {float:left; width:300px; clear:both; margin:0 0 5px 0; padding:3px;}
|
||||
dl.horizontal dd {float:left; width:500px; border:1px solid #aaaaaa; margin:0 0 5px 0; padding:2px; -moz-box-shadow: 1px 1px 3px #aaaaaa;}
|
||||
dl.horizontal dd span {background:#91b4e6; display:block; color:black; text-indent:4px;}
|
||||
|
||||
214
fail/bin/resultbrowser/app/static/css/main.css
Normal file
214
fail/bin/resultbrowser/app/static/css/main.css
Normal file
@ -0,0 +1,214 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color : #444;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color : #444;
|
||||
text-decoration: none;
|
||||
}
|
||||
/*
|
||||
* Create dark grey header with a white logo
|
||||
*/
|
||||
|
||||
header {
|
||||
background-color: #2B2B2B;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
opacity: .9;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
header h1.logo {
|
||||
margin: 0;
|
||||
font-size: 1.5em;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
float: left;
|
||||
}
|
||||
|
||||
header h1.logo:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Center the body content
|
||||
*/
|
||||
|
||||
.container {
|
||||
width: 95%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
div.jumbo {
|
||||
padding: 10px 0 30px 0;
|
||||
background-color: #eeeeee;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.0em;
|
||||
font-weight: 100;
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
/*letter-spacing: -1px;*/
|
||||
color: #999;
|
||||
}
|
||||
|
||||
|
||||
#footer {
|
||||
text-align: center;
|
||||
color: #444;
|
||||
font-size:10pt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Table styles
|
||||
*/
|
||||
|
||||
.codetable, .resulttable, .overviewtable{
|
||||
font-family: monospace;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.overviewtable {
|
||||
border: 1px gray solid;
|
||||
margin: auto;
|
||||
}
|
||||
/*
|
||||
.overviewtable tr:nth-child(4n), .overviewtable tr:nth-child(4n-1) {
|
||||
background: #fff;
|
||||
}
|
||||
.overviewtable tr:nth-child(4n-2), .overviewtable tr:nth-child(4n-3) {
|
||||
background: #e8ffb3;
|
||||
}
|
||||
*/
|
||||
|
||||
.resulttable, .codetable, .overviewtable{
|
||||
margin: auto;
|
||||
border: solid #ccc 1px;
|
||||
-moz-border-radius: 6px;
|
||||
-webkit-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
-webkit-box-shadow: 0 1px 1px #ccc;
|
||||
-moz-box-shadow: 0 1px 1px #ccc;
|
||||
box-shadow: 0 1px 1px #ccc;
|
||||
}
|
||||
|
||||
.codetable tr:hover, .resulttable tr:hover {
|
||||
background: #fbf8e9;
|
||||
/* -o-transition: all 0.1s ease-in-out;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
-moz-transition: all 0.1s ease-in-out;
|
||||
-ms-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
*/
|
||||
}
|
||||
|
||||
.resulttable td, .resulttable th, .codetable td, .codetable th {
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
padding: 2px;
|
||||
text-align: left;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.codetable td a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.resulttable th, .codetable th, .overviewtable th {
|
||||
background-color: #dce9f9;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#efe), to(#91b4e6));
|
||||
background-image: -webkit-linear-gradient(top, #efe, #91b4e6);
|
||||
background-image: -moz-linear-gradient(top, #efe, #91b4e6);
|
||||
background-image: -ms-linear-gradient(top, #efe, #91b4e6);
|
||||
background-image: -o-linear-gradient(top, #efe, #91b4e6);
|
||||
background-image: linear-gradient(top, #efe, #91b4e6);
|
||||
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
|
||||
-moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset;
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
|
||||
border-top: none;
|
||||
text-shadow: 0 1px 0 rgba(255,255,255,.5);
|
||||
}
|
||||
|
||||
.resulttable td:first-child, .resulttable th:first-child, .codetable td:first-child, .codetable th:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.resulttable th:first-child, .codetable th:first-child {
|
||||
-moz-border-radius: 6px 0 0 0;
|
||||
-webkit-border-radius: 6px 0 0 0;
|
||||
border-radius: 6px 0 0 0;
|
||||
}
|
||||
|
||||
.resulttable th:last-child, .codetable th:last-child {
|
||||
-moz-border-radius: 0 6px 0 0;
|
||||
-webkit-border-radius: 0 6px 0 0;
|
||||
border-radius: 0 6px 0 0;
|
||||
}
|
||||
|
||||
.resulttable th:only-child, .codetable th:only-child{
|
||||
-moz-border-radius: 6px 6px 0 0;
|
||||
-webkit-border-radius: 6px 6px 0 0;
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
|
||||
.resulttable tr:last-child td:first-child, .codetable tr:last-child td:first-child {
|
||||
-moz-border-radius: 0 0 0 6px;
|
||||
-webkit-border-radius: 0 0 0 6px;
|
||||
border-radius: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.resulttable tr:last-child td:last-child, .codetable tr:last-child td:last-child {
|
||||
-moz-border-radius: 0 0 6px 0;
|
||||
-webkit-border-radius: 0 0 6px 0;
|
||||
border-radius: 0 0 6px 0;
|
||||
}
|
||||
|
||||
.resulttypemenu {
|
||||
text-align: center;
|
||||
font-size: 12px
|
||||
}
|
||||
/*
|
||||
* Display navigation links inline
|
||||
*/
|
||||
|
||||
.menu {
|
||||
float: right;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.menu li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.menu li + li {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
.menu li a {
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
}
|
||||
BIN
fail/bin/resultbrowser/app/static/favicon.ico
Normal file
BIN
fail/bin/resultbrowser/app/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
11
fail/bin/resultbrowser/app/templates/about.html
Normal file
11
fail/bin/resultbrowser/app/templates/about.html
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if status %}
|
||||
<h2>About</h2>
|
||||
{{ status }}
|
||||
{% else %}
|
||||
<h2> Sorry, no status information.</h2>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
50
fail/bin/resultbrowser/app/templates/code.html
Normal file
50
fail/bin/resultbrowser/app/templates/code.html
Normal file
@ -0,0 +1,50 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Variant Results</h1>
|
||||
|
||||
{% if resulttypes %}
|
||||
<table>
|
||||
<tr><td>Result Table</td><td><b>{{ variant_details.getTableDetails().getTitle() }}</b><td></tr>
|
||||
<tr><td>Variant </td><td><b>{{ variant_details.getDetails().getTitle() }}</b></td></tr>
|
||||
<tr><td>Details </td><td><b>{{ variant_details.getDetails().getDetails() }}</b></td></tr>
|
||||
<tr><td>Benchmark </td><td><b>{{ variant_details.getBenchmarkDetails().getTitle() }}</b></td></tr>
|
||||
<tr><td>Details </td><td><b>{{ variant_details.getBenchmarkDetails().getDetails() }}</b></td></tr>
|
||||
<tr><td>Result Count </td><td><b>{{ results|length }}</b></td></tr>
|
||||
</table>
|
||||
<hr>
|
||||
<p class='resulttypemenu'>| <a href="{{ url_for('code', variant_id=request.args.get('variant_id'), table=request.args.get('table')) }}">All Results</a> |
|
||||
{% for restype in resulttypes %}
|
||||
<a href="{{ url_for('code', variant_id=request.args.get('variant_id'), table=request.args.get('table'), resulttype=restype )}}">{{ restype}}</a> |
|
||||
{% endfor %}
|
||||
</p>
|
||||
<hr>
|
||||
<table class="codetable">
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Opcode</th>
|
||||
<th>Disassembly</th>
|
||||
<th>Comment</th>
|
||||
<th>Results</th>
|
||||
<th># Results</th>
|
||||
</tr>
|
||||
{% for d in results %}
|
||||
{% set link = url_for('instr_details', table=request.args.get('table'), variant_id=request.args.get('variant_id'), benchmark=request.args.get('benchmark'), variant=request.args.get('variant'), resulttype=request.args.get('resulttype'), instr_address=d['instr_address'] ) %}
|
||||
<tr>
|
||||
<td><a href="{{ link }}">{{ "0x%x"|format(d['instr_address']) }}</a></td>
|
||||
<td><a href="{{ link }}">{{ d['opcode'] }}</a></td>
|
||||
<td><a href="{{ link }}">{{ d['disassemble'] }}</a></td>
|
||||
<td><a href="{{ link }}">{{ d['comment'] }}</a></td>
|
||||
<td><a href="{{ link }}">{{ d['results'] }}</a></td>
|
||||
<td><a href="{{ link }}">{{ d['totals'] }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<h1> Sorry, no dump found.</h1>
|
||||
{% endif %}
|
||||
|
||||
{%endblock %}
|
||||
|
||||
|
||||
55
fail/bin/resultbrowser/app/templates/index.html
Normal file
55
fail/bin/resultbrowser/app/templates/index.html
Normal file
@ -0,0 +1,55 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
{%if overview %}
|
||||
{% for tablekey, resulttable in overview.getTables().items() %}
|
||||
<h2>Result table: {{ resulttable.getDetails().getTitle() }}</h2>
|
||||
-> <a href="{{ url_for('index', reload=1) }}">Reload data</a> <-
|
||||
<dl>
|
||||
<dt>Details:</td>
|
||||
<dd>
|
||||
{{ resulttable.getDetails().getDetails() }}
|
||||
<dd>
|
||||
</dl>
|
||||
{% if not objdump_there %}
|
||||
No objdump found
|
||||
{% endif %}
|
||||
<table class="overviewtable" cellspacing="0px">
|
||||
{% for varid, variant in resulttable.getVariants().items() %}
|
||||
<tr><th>
|
||||
{% set variant_title=variant.getDetails().getTitle() ~ " - " ~ variant.getBenchmarkDetails().getTitle() ~ " id: " ~ variant.getId() %}
|
||||
{% if objdump_there %}
|
||||
<a href="{{ url_for('code',table=resulttable.getDetails().getDBName(), variant_id=variant.getId() ) }}">{{ variant_title }}</a>
|
||||
{% else %}
|
||||
{{ variant_title }}
|
||||
{% endif %}
|
||||
(Total: {{ variant.getTotals() }})</a>
|
||||
</th></tr>
|
||||
<tr><td>
|
||||
{% if variant.getDetails().getDetails() %}
|
||||
Variant Details: {{ variant.getDetails().getDetails() }}
|
||||
{% endif %}
|
||||
{% if variant.getBenchmarkDetails().getDetails() %}
|
||||
<br> Benchmark Details: {{ variant.getBenchmarkDetails().getDetails() }}</td></tr>
|
||||
{% endif %}
|
||||
<tr><td>
|
||||
<dl class="horizontal">
|
||||
{% for reslabel,count in variant.getResults().items() %}
|
||||
<dt>
|
||||
{% if objdump_there %}
|
||||
<a href="{{ url_for('code', table=resulttable.getDetails().getDBName(), variant_id=variant.getId(), resulttype=reslabel ) }}">{{ reslabel }}</a>
|
||||
{% else %}
|
||||
{{ reslabel }}
|
||||
{% endif %}
|
||||
</dt>
|
||||
<dd><span style="width:{{count * 100 / variant.getTotals() }}%;">{{count}}</span></dd>
|
||||
{% endfor %}
|
||||
</dl></td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<h2> Sorry, no results found.</h2>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
65
fail/bin/resultbrowser/app/templates/instr_details.html
Normal file
65
fail/bin/resultbrowser/app/templates/instr_details.html
Normal file
@ -0,0 +1,65 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% if code %}
|
||||
<h1>Result by Instruction</h1>
|
||||
<table>
|
||||
<tr><td>Result Table</td><td><b>{{ variant_details.getTableDetails().getTitle() }}</b><td></tr>
|
||||
<tr><td>Variant </td><td><b>{{ variant_details.getDetails().getTitle() }}</b></td></tr>
|
||||
<tr><td>Benchmark </td><td><b>{{ variant_details.getBenchmarkDetails().getTitle() }}</b></td></tr>
|
||||
<tr><td>Details </td><td><b>{{ variant_details.getDetails().getDetails() }}</b></td></tr>
|
||||
<tr><td>Instruction Address </td><td><b>{{ "0x%x (Dec: %d)"|format(request.args.get('instr_address')|int, request.args.get('instr_address')|int) }}</b></td></tr>
|
||||
<tr><td>Total Results</td><td><b>{{ result|length }}</b></td></tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2>Code</h2>
|
||||
<table class="codetable">
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<th>Opcode</th>
|
||||
<th>Disassembly</th>
|
||||
<th>Comment</th>
|
||||
</tr>
|
||||
{% for d in code['below'] %}
|
||||
<tr>
|
||||
<td>{{ "0x%x"|format(d['instr_address']) }}</td>
|
||||
<td>{{ d['opcode'] }}</td>
|
||||
<td>{{ d['disassemble'] }}</td>
|
||||
<td>{{ d['comment'] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr style="font-weight: bold">
|
||||
<td>{{ "0x%x"|format(code['upper'][0]['instr_address']) }}</td>
|
||||
<td>{{ code['upper'][0]['opcode'] }}</td>
|
||||
<td>{{ code['upper'][0]['disassemble'] }}</td>
|
||||
<td>{{ code['upper'][0]['comment'] }}</td>
|
||||
</tr>
|
||||
{% for d in code['upper'][1:] %}
|
||||
<tr>
|
||||
<td>{{ "0x%x"|format(d['instr_address']) }}</td>
|
||||
<td>{{ d['opcode'] }}</td>
|
||||
<td>{{ d['disassemble'] }}</td>
|
||||
<td>{{ d['comment'] }}</td>
|
||||
</tr>
|
||||
{% endfor %}</table>
|
||||
<hr>
|
||||
<h2>Results ({{ result|length }})</h2>
|
||||
<table class="resulttable">
|
||||
<tr>
|
||||
{% for key, value in result[0].items() -%}
|
||||
<th>{{ key }}</th>
|
||||
{% endfor -%}
|
||||
</tr>
|
||||
{% for r in result -%}
|
||||
<tr>
|
||||
{% for k,v in r.items() -%}
|
||||
<td>{{ v }}</td>
|
||||
{% endfor -%}
|
||||
</tr>
|
||||
{% endfor -%}
|
||||
</tr>
|
||||
</table>
|
||||
{% else %}
|
||||
<h2> Sorry, no details found.</h2>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
32
fail/bin/resultbrowser/app/templates/layout.html
Normal file
32
fail/bin/resultbrowser/app/templates/layout.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>FAIL* Results</title>
|
||||
<strong><link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}"></strong>
|
||||
<strong><link rel="stylesheet" href="{{ url_for('static', filename='css/barchart.css') }}"></strong>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
<h1 class="logo">FAIL*</h1>
|
||||
<strong><nav>
|
||||
<ul class="menu">
|
||||
<li><a href="{{ url_for('index') }}">Home</a></li>
|
||||
<li><a href="{{ url_for('about') }}">About</a></li>
|
||||
</ul>
|
||||
</nav></strong>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div id="footer">
|
||||
© FAIL* - Fault Injection Leveraged
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
42
fail/bin/resultbrowser/app/views.py
Normal file
42
fail/bin/resultbrowser/app/views.py
Normal file
@ -0,0 +1,42 @@
|
||||
from flask import render_template,request
|
||||
from app import app
|
||||
|
||||
# import model
|
||||
# import data
|
||||
|
||||
from . import model
|
||||
from . import data
|
||||
|
||||
@app.route('/')
|
||||
@app.route('/index')
|
||||
def index():
|
||||
reload_overview = request.args.get('reload', False)
|
||||
if reload_overview:
|
||||
print("Reloading overview...")
|
||||
model.reloadOverview()
|
||||
return render_template("index.html", overview=model.getOverview(), objdump_there = model.objdumpExists())
|
||||
|
||||
@app.route('/code')
|
||||
def code():
|
||||
variant_id = request.args.get('variant_id', None)
|
||||
resulttype = request.args.get('resulttype', None)
|
||||
table = request.args.get('table', None)
|
||||
res,restypes = model.getCode(table, variant_id, resulttype)
|
||||
var_dets = model.getOverview().getVariantById(variant_id)
|
||||
return render_template("code.html", results=res, resulttypes=restypes, variant_details=var_dets )
|
||||
|
||||
@app.route('/instr_details')
|
||||
def instr_details():
|
||||
table = request.args.get('table', None)
|
||||
variant_id = request.args.get('variant_id', None)
|
||||
instr_addr = request.args.get('instr_address', None)
|
||||
resulttype = request.args.get('resulttype', None)
|
||||
codeexcerpt = model.getCodeExcerpt(variant_id, instr_addr)
|
||||
var_dets = model.getOverview().getVariantById(variant_id)
|
||||
results = model.getResultsbyInstruction(table, variant_id, instr_addr, resulttype)
|
||||
return render_template("instr_details.html", code=codeexcerpt, result=results, variant_details=var_dets)
|
||||
|
||||
@app.route('/about')
|
||||
def about():
|
||||
stat = model.showDBstatus()
|
||||
return render_template("about.html", status=stat)
|
||||
69
fail/bin/resultbrowser/conf.yml
Normal file
69
fail/bin/resultbrowser/conf.yml
Normal file
@ -0,0 +1,69 @@
|
||||
# YAML-based: http://yaml.org/
|
||||
# Online parser for testing: http://yaml-online-parser.appspot.com/
|
||||
# Some notes:
|
||||
# YAML is case-sensitive and structured by indention!
|
||||
#
|
||||
# The 'defaults' section describes an *optional* default result type mapping for all tables.
|
||||
# The 'tables' section describes result tables in more detail.
|
||||
# A table consists of variants, each variant of benchmarks.
|
||||
# Each of these configuration items
|
||||
# title: Table title
|
||||
# details: Some textual description
|
||||
# mapping: A distinct mapping, if not set, the parent item's mapping is used
|
||||
|
||||
defaults:
|
||||
mapping:
|
||||
Everything OK:
|
||||
- OK
|
||||
- OK_DETECTED_ERROR
|
||||
- OK_WRONG_CONTROL_FLOW
|
||||
Outside Data Section:
|
||||
- ERR_OUTSIDE_DATA
|
||||
Hardware Trap:
|
||||
- ERR_OUTSIDE_TEXT
|
||||
- ERR_TRAP
|
||||
Silent Data Corruption:
|
||||
- ERR_WRONG_RESULT
|
||||
|
||||
tables:
|
||||
result_CoredVoterProtoMsg:
|
||||
title: CoRed Voter Experiment Results
|
||||
variants:
|
||||
x86_cored_voter:
|
||||
title: x86 CoRed Voter Experiment
|
||||
details: Some interesting details about the experiment.
|
||||
|
||||
benchmarks:
|
||||
ean-random-4:
|
||||
title: Random 4 bit injections
|
||||
details: |
|
||||
The details can also written this way.
|
||||
The pipe insert the newlines. Cool, isn't it?
|
||||
|
||||
ean-random-5:
|
||||
title: Random 5 bit injections
|
||||
details: Details about 5 bit random injection benchmark.
|
||||
mapping:
|
||||
Alright:
|
||||
- OK
|
||||
- OK_DETECTED_ERROR
|
||||
- OK_WRONG_CONTROL_FLOW
|
||||
Not Alright:
|
||||
- ERR_OUTSIDE_DATA
|
||||
- ERR_OUTSIDE_TEXT
|
||||
- ERR_TRAP
|
||||
- ERR_WRONG_RESULT
|
||||
Timeout:
|
||||
- ERR_TIMEOUT
|
||||
# Another variant within result_CoredVoterProtoMsg
|
||||
x86_cored_voter2:
|
||||
title: variant title
|
||||
details: variant details
|
||||
benchmarks:
|
||||
ean-random-2:
|
||||
title: benchmarktitle
|
||||
details: some benchmark details
|
||||
|
||||
ean-random-3:
|
||||
title: benchmark random 3
|
||||
details: some benchmark 3 details
|
||||
5
fail/bin/resultbrowser/run.py
Executable file
5
fail/bin/resultbrowser/run.py
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
from app import app
|
||||
from app import model
|
||||
|
||||
app.run(debug=False, port=int(model.opts.port), host=model.opts.host)
|
||||
1
fail/bin/visualfail.sh
Symbolic link
1
fail/bin/visualfail.sh
Symbolic link
@ -0,0 +1 @@
|
||||
./VisualFAIL/StartVF.sh
|
||||
BIN
fail/share/BIOS-bochs-latest
(Stored with Git LFS)
Executable file
BIN
fail/share/BIOS-bochs-latest
(Stored with Git LFS)
Executable file
Binary file not shown.
BIN
fail/share/vgabios.bin
(Stored with Git LFS)
Executable file
BIN
fail/share/vgabios.bin
(Stored with Git LFS)
Executable file
Binary file not shown.
1
fail/src
Submodule
1
fail/src
Submodule
Submodule fail/src added at dda6da2a50
6
flake.lock
generated
6
flake.lock
generated
@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1773110118,
|
||||
"narHash": "sha256-mPAG8phMbCReKSiKAijjjd3v7uVcJOQ75gSjGJjt/Rk=",
|
||||
"lastModified": 1776329215,
|
||||
"narHash": "sha256-a8BYi3mzoJ/AcJP8UldOx8emoPRLeWqALZWu4ZvjPXw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e607cb5360ff1234862ac9f8839522becb853bb9",
|
||||
"rev": "b86751bc4085f48661017fa226dee99fab6c651b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
547
flake.nix
547
flake.nix
@ -12,208 +12,387 @@ rec {
|
||||
flake-utils,
|
||||
}:
|
||||
# Create a shell (and possibly package) for each possible system, not only x86_64-linux
|
||||
flake-utils.lib.eachDefaultSystem (system: let
|
||||
# =========================================================================================
|
||||
# Define pkgs/stdenvs
|
||||
# =========================================================================================
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
overlays = [];
|
||||
};
|
||||
|
||||
boost174_pkgs =
|
||||
import (builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/824421b1796332ad1bcb35bc7855da832c43305f.tar.gz";
|
||||
sha256 = "sha256:1w6cjnakz1yi66rs8c6nmhymsr7bj82vs2hz200ipi1sfiq8dy4y";
|
||||
}) {
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
# =========================================================================================
|
||||
# Define pkgs/stdenvs
|
||||
# =========================================================================================
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
overlays = [];
|
||||
};
|
||||
|
||||
inherit (pkgs) lib stdenv;
|
||||
i386_pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
overlays = [];
|
||||
|
||||
# =========================================================================================
|
||||
# Define shell environment
|
||||
# =========================================================================================
|
||||
|
||||
# Setup the shell when entering the "nix develop" environment (bash script).
|
||||
shellHook = let
|
||||
mkCmakeScript = type: let
|
||||
typeLower = lib.toLower type;
|
||||
in
|
||||
pkgs.writers.writeFish "cmake-${typeLower}.fish" ''
|
||||
cd $FLAKE_PROJECT_ROOT
|
||||
|
||||
echo "Removing build directory ./cmake-build-${typeLower}/"
|
||||
rm -rf ./cmake-build-${typeLower}
|
||||
|
||||
echo "Creating build directory"
|
||||
mkdir cmake-build-${typeLower}
|
||||
cd cmake-build-${typeLower}
|
||||
|
||||
echo "Running cmake"
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="${type}" -DCMAKE_EXPORT_COMPILE_COMMANDS="On" ..
|
||||
|
||||
echo "Linking compile_commands.json"
|
||||
cd ..
|
||||
ln -sf ./cmake-build-${typeLower}/compile_commands.json ./compile_commands.json
|
||||
'';
|
||||
|
||||
cmakeDebug = mkCmakeScript "Debug";
|
||||
cmakeRelease = mkCmakeScript "Release";
|
||||
|
||||
mkBuildScript = type: let
|
||||
typeLower = lib.toLower type;
|
||||
in
|
||||
pkgs.writers.writeFish "cmake-build.fish" ''
|
||||
cd $FLAKE_PROJECT_ROOT/cmake-build-${typeLower}
|
||||
|
||||
echo "Running cmake"
|
||||
cmake --build .
|
||||
'';
|
||||
|
||||
buildDebug = mkBuildScript "Debug";
|
||||
buildRelease = mkBuildScript "Release";
|
||||
|
||||
# Use this to specify commands that should be ran after entering fish shell
|
||||
initProjectShell = pkgs.writers.writeFish "init-shell.fish" ''
|
||||
echo "Entering \"${description}\" environment..."
|
||||
|
||||
# Determine the project root, used e.g. in cmake scripts
|
||||
set -g -x FLAKE_PROJECT_ROOT (git rev-parse --show-toplevel)
|
||||
|
||||
# Rust Bevy:
|
||||
# abbr -a build-release-windows "CARGO_FEATURE_PURE=1 cargo xwin build --release --target x86_64-pc-windows-msvc"
|
||||
|
||||
# C/C++:
|
||||
# abbr -a cmake-debug "${cmakeDebug}"
|
||||
# abbr -a cmake-release "${cmakeRelease}"
|
||||
# abbr -a build-debug "${buildDebug}"
|
||||
# abbr -a build-release "${buildRelease}"
|
||||
'';
|
||||
in
|
||||
builtins.concatStringsSep "\n" [
|
||||
# Launch into pure fish shell
|
||||
''
|
||||
exec "$(type -p fish)" -C "source ${initProjectShell} && abbr -a menu '${pkgs.bat}/bin/bat "${initProjectShell}"'"
|
||||
''
|
||||
];
|
||||
|
||||
# ===========================================================================================
|
||||
# Define custom dependencies
|
||||
# ===========================================================================================
|
||||
|
||||
python = pkgs.python314.withPackages (p:
|
||||
with p; [
|
||||
setuptools
|
||||
flask
|
||||
flask-mysqldb
|
||||
pyyaml
|
||||
]);
|
||||
|
||||
boost174 = boost174_pkgs.boost174;
|
||||
|
||||
libpcl = stdenv.mkDerivation rec {
|
||||
pname = "libpcl1";
|
||||
version = "1.12-2";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
url = "http://launchpadlibrarian.net/521269537/libpcl1_1.12-2_amd64.deb";
|
||||
hash = "sha256-GL3mjPAccAtRMAJPnDMCHiDf6xNvGi4oUWylOIqBjP0=";
|
||||
# Build crosscompiler
|
||||
crossSystem = {
|
||||
config = "i386-elf";
|
||||
libc = "newlib";
|
||||
};
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
boost_pkgs =
|
||||
import
|
||||
(builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/824421b1796332ad1bcb35bc7855da832c43305f.tar.gz";
|
||||
sha256 = "sha256:1w6cjnakz1yi66rs8c6nmhymsr7bj82vs2hz200ipi1sfiq8dy4y";
|
||||
})
|
||||
{
|
||||
inherit system;
|
||||
};
|
||||
|
||||
libdwarf_pkgs =
|
||||
import
|
||||
(builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/f597e7e9fcf37d8ed14a12835ede0a7d362314bd.tar.gz";
|
||||
sha256 = "sha256:1l79hh7jh7m8yc5mvc8dbg6s8rf30bgm994kf07xriqbzwfn158r";
|
||||
})
|
||||
{
|
||||
inherit system;
|
||||
};
|
||||
|
||||
inherit (pkgs) lib stdenv;
|
||||
|
||||
# =========================================================================================
|
||||
# Define shell environment
|
||||
# =========================================================================================
|
||||
|
||||
# Setup the shell when entering the "nix develop" environment (bash script).
|
||||
shellHook = let
|
||||
# Add project-local fish abbrs here
|
||||
abbrs = {
|
||||
fail = "perl ./scripts/menu.pl";
|
||||
|
||||
# C/C++:
|
||||
# cmake-debug = "${cmakeDebug}";
|
||||
# cmake-release = "${cmakeRelease}";
|
||||
# build-debug = "${buildDebug}";
|
||||
# build-release = "${buildRelease}";
|
||||
};
|
||||
|
||||
eraseAbbr = name: value: "abbr --erase ${name} 2>/dev/null";
|
||||
createAbbr = name: value: ''abbr -a ${name} "${value}"'';
|
||||
|
||||
# This will be sourced by the global fish config if INIT_PROJECT_SHELL gets unset
|
||||
unloadProjectShell = pkgs.writers.writeFish "unload-shell.fish" ''
|
||||
echo "Unloading \"${description}\" environment..."
|
||||
|
||||
${builtins.concatStringsSep "\n" (lib.mapAttrsToList eraseAbbr abbrs)}
|
||||
'';
|
||||
|
||||
# This will be sourced by the global fish config if INIT_PROJECT_SHELL gets set
|
||||
initProjectShell = pkgs.writers.writeFish "init-shell.fish" ''
|
||||
# Unload just in case, to not have redefinition errors
|
||||
source ${unloadProjectShell}
|
||||
|
||||
echo "Sourcing \"${description}\" environment..."
|
||||
|
||||
${builtins.concatStringsSep "\n" (lib.mapAttrsToList createAbbr abbrs)}
|
||||
'';
|
||||
in
|
||||
builtins.concatStringsSep "\n" [
|
||||
# Launch into pure fish shell
|
||||
''
|
||||
# Can't do the "exec" with nix-direnv
|
||||
# - The "exec fish" would call direnv again => Infinite loop
|
||||
# - The shellHook is Bash/POSIX, so fish syntax doesn't work
|
||||
# exec "$(type -p fish)" -C "source ${initProjectShell} && abbr -a menu '${pkgs.bat}/bin/bat "${initProjectShell}"'"
|
||||
|
||||
# Determine the project root, used e.g. in cmake scripts
|
||||
export FLAKE_PROJECT_ROOT="$(git rev-parse --show-toplevel)"
|
||||
export INIT_PROJECT_SHELL="${initProjectShell}"
|
||||
export UNLOAD_PROJECT_SHELL="${unloadProjectShell}"
|
||||
''
|
||||
];
|
||||
|
||||
# ===========================================================================================
|
||||
# Define custom dependencies
|
||||
# ===========================================================================================
|
||||
|
||||
python = pkgs.python314.withPackages (
|
||||
p:
|
||||
with p; [
|
||||
setuptools
|
||||
flask
|
||||
flask-mysqldb
|
||||
pyyaml
|
||||
tabulate
|
||||
]
|
||||
);
|
||||
|
||||
# perl = pkgs.perl.withPackages (p:
|
||||
# with p; [
|
||||
# # Those are already installed system-wide
|
||||
# # PLS
|
||||
# # PerlTidy
|
||||
#
|
||||
# NetOpenSSH
|
||||
# ]);
|
||||
|
||||
libpcl = stdenv.mkDerivation rec {
|
||||
pname = "libpcl1";
|
||||
version = "1.12-2";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
url = "http://launchpadlibrarian.net/521269537/${pname}_${version}_amd64.deb";
|
||||
hash = "sha256-GL3mjPAccAtRMAJPnDMCHiDf6xNvGi4oUWylOIqBjP0=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
nativeBuildInputs = with pkgs; [
|
||||
dpkg
|
||||
autoPatchelfHook
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/lib
|
||||
cp -rv usr/lib/x86_64-linux-gnu/* $out/lib/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
# Provides clang to compile C++ to Wasm
|
||||
wasi-sdk = stdenv.mkDerivation rec {
|
||||
pname = "wasi-sdk";
|
||||
version = "29";
|
||||
|
||||
src = let
|
||||
baseurl = "https://github.com/WebAssembly/wasi-sdk/releases/download";
|
||||
in
|
||||
builtins.fetchTarball {
|
||||
url = "${baseurl}/${pname}-${version}/${pname}-${version}.0-x86_64-linux.tar.gz";
|
||||
sha256 = "sha256:16afis71iqfvwiny4dz0lk9f7wbary0wa67ybwyhywr8g57ss6hq";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
autoPatchelfHook
|
||||
];
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
libgcc.lib
|
||||
];
|
||||
|
||||
dontBuild = true;
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
cp -rv ./* $out/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
# Provides the iwasm interpreter
|
||||
iwasm = stdenv.mkDerivation rec {
|
||||
pname = "iwasm";
|
||||
version = "2.4.4";
|
||||
|
||||
src = let
|
||||
baseurl = "https://github.com/bytecodealliance/wasm-micro-runtime/releases/download";
|
||||
in
|
||||
builtins.fetchTarball {
|
||||
url = "${baseurl}/WAMR-${version}/${pname}-${version}-x86_64-ubuntu-22.04.tar.gz";
|
||||
sha256 = "sha256:05irihz3yf7hpc0a59qz9i62imhrsni9xy9nxwsn6b8s92c1yzrp";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
autoPatchelfHook
|
||||
];
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
libz
|
||||
zstd
|
||||
libgcc.lib
|
||||
];
|
||||
|
||||
dontBuild = true;
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/bin
|
||||
cp -rv ./* $out/bin/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
# Provides the wamrc compiler
|
||||
wamrc = stdenv.mkDerivation rec {
|
||||
pname = "wamrc";
|
||||
version = "2.4.4";
|
||||
|
||||
src = let
|
||||
baseurl = "https://github.com/bytecodealliance/wasm-micro-runtime/releases/download";
|
||||
in
|
||||
builtins.fetchTarball {
|
||||
url = "${baseurl}/WAMR-${version}/${pname}-${version}-x86_64-ubuntu-22.04.tar.gz";
|
||||
sha256 = "sha256:0264arh03gc35z0zdvw07qdvqgfvsxr3qgl1aszghwicmdmh4sqj";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
autoPatchelfHook
|
||||
];
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
libz
|
||||
zstd
|
||||
libgcc.lib
|
||||
];
|
||||
|
||||
dontBuild = true;
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/bin
|
||||
cp -rv ./* $out/bin/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
# ===========================================================================================
|
||||
# Specify dependencies
|
||||
# https://nixos.org/manual/nixpkgs/stable/#ssec-stdenv-dependencies-overview
|
||||
# Just for a "nix develop" shell, buildInputs can be used for everything.
|
||||
# ===========================================================================================
|
||||
|
||||
# Add dependencies to nativeBuildInputs if they are executed during the build:
|
||||
# - Those which are needed on $PATH during the build, for example cmake and pkg-config
|
||||
# - Setup hooks, for example makeWrapper/autoPatchelfHook
|
||||
# - Interpreters needed by patchShebangs for build scripts (with the --build flag), which can be the case for e.g. perl
|
||||
nativeBuildInputs = with pkgs; [
|
||||
dpkg
|
||||
autoPatchelfHook
|
||||
cmake
|
||||
gdb
|
||||
xxd
|
||||
wabt
|
||||
grub2
|
||||
xorriso
|
||||
mariadb.client
|
||||
# dbeaver-bin
|
||||
# beekeeper-studio
|
||||
# tableplus
|
||||
lazysql
|
||||
iwasm
|
||||
wamrc
|
||||
fail-bin
|
||||
php
|
||||
|
||||
# perl
|
||||
|
||||
# Don't install to not pollute our PATH. Just export as environment variable.
|
||||
# wasi-sdk
|
||||
# libiwasm_debug
|
||||
# libiwasm_release
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
# Add dependencies to buildInputs if they will end up copied or linked into the final output or otherwise used at runtime:
|
||||
# - Libraries used by compilers, for example zlib
|
||||
# - Interpreters needed by patchShebangs for scripts which are installed, which can be the case for e.g. perl
|
||||
buildInputs = with pkgs; [];
|
||||
|
||||
ls -al
|
||||
# dpkg-deb -x ${pname}_${version}_amd64.deb libpcl
|
||||
# ===========================================================================================
|
||||
# Define buildable + installable packages
|
||||
# ===========================================================================================
|
||||
|
||||
mkdir -p $out/lib
|
||||
cp -rv usr/lib/x86_64-linux-gnu/* $out/lib/
|
||||
fail-bin = stdenv.mkDerivation {
|
||||
pname = "fail";
|
||||
version = "1.0.0";
|
||||
src = ./.;
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
dontStrip = true;
|
||||
|
||||
# ===========================================================================================
|
||||
# Specify dependencies
|
||||
# https://nixos.org/manual/nixpkgs/stable/#ssec-stdenv-dependencies-overview
|
||||
# Just for a "nix develop" shell, buildInputs can be used for everything.
|
||||
# ===========================================================================================
|
||||
nativeBuildInputs = with pkgs; [
|
||||
autoPatchelfHook
|
||||
];
|
||||
|
||||
# Add dependencies to nativeBuildInputs if they are executed during the build:
|
||||
# - Those which are needed on $PATH during the build, for example cmake and pkg-config
|
||||
# - Setup hooks, for example makeWrapper
|
||||
# - Interpreters needed by patchShebangs for build scripts (with the --build flag), which can be the case for e.g. perl
|
||||
nativeBuildInputs = with pkgs; [
|
||||
autoPatchelfHook
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
# FAIL runtime dependencies
|
||||
python # bochs-experiment-runner.py, resultbrowser.py
|
||||
|
||||
# Add dependencies to buildInputs if they will end up copied or linked into the final output or otherwise used at runtime:
|
||||
# - Libraries used by compilers, for example zlib
|
||||
# - Interpreters needed by patchShebangs for scripts which are installed, which can be the case for e.g. perl
|
||||
buildInputs = with pkgs; [
|
||||
python # For resultbrowser
|
||||
# For old VSS FAIL
|
||||
# alsa-lib # libasound.so.2
|
||||
# boost_pkgs.boost174 # libboost_coroutine.so.1.74.0, libboost_regex.so.1.74.0, libboost_thread.so.1.74.0
|
||||
# capstone_4 # libcapstone.so.4
|
||||
# libdwarf_pkgs.libdwarf # libdwarf.so.1
|
||||
# elfutils # libelf.so.1
|
||||
# mariadb # libmariadb.so.3
|
||||
# libpcl # libpcl.so.1
|
||||
# protobuf_21 # libprotobuf.so.32
|
||||
# SDL # libSDL-1.2.so.0
|
||||
# libx11 # libX11.so.6
|
||||
# libxrandr # libXrandr.so.2
|
||||
# libz # libz.so.1
|
||||
|
||||
alsa-lib # libasound.so.2
|
||||
boost174 # libboost_coroutine.so.1.74.0, libboost_regex.so.1.74.0, libboost_thread.so.1.74.0
|
||||
capstone_4 # libcapstone.so.4
|
||||
libdwarf # libdwarf.so.1
|
||||
libelf # libelf.so.1
|
||||
mariadb-connector-c # libmariadb.so.3
|
||||
libpcl # libpcl.so.1
|
||||
protobuf # libprotobuf.so.32
|
||||
SDL # libSDL-1.2.so.0
|
||||
libx11 # libX11.so.6
|
||||
libxrandr # libXrandr.so.2
|
||||
libz # libz.so.1
|
||||
];
|
||||
# ===========================================================================================
|
||||
# Define buildable + installable packages
|
||||
# ===========================================================================================
|
||||
package = stdenv.mkDerivation rec {
|
||||
inherit nativeBuildInputs buildInputs;
|
||||
pname = "fail";
|
||||
version = "1.0.0";
|
||||
src = ./.;
|
||||
# For current FAIL
|
||||
boost183
|
||||
capstone # libcapstone.so.5
|
||||
libdwarf_pkgs.libdwarf # libdwarf.so.1
|
||||
elfutils # libelf.so.1
|
||||
mariadb # libmariadb.so.3
|
||||
protobuf_21 # libprotobuf.so.32
|
||||
libz # libz.so.1
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
cp -rv ./bin $out/bin
|
||||
cp -rv ./share $out/share
|
||||
mkdir -p $out
|
||||
cp -rv ./fail/bin $out/bin
|
||||
cp -rv ./fail/share $out/share
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
in rec {
|
||||
# Provide package for "nix build"
|
||||
packages = {
|
||||
default = package;
|
||||
};
|
||||
apps.default = flake-utils.lib.mkApp {drv = package;};
|
||||
|
||||
devShells = {
|
||||
# Provide default environment for "nix develop".
|
||||
# Other environments can be added below.
|
||||
default = pkgs.mkShell {
|
||||
inherit nativeBuildInputs buildInputs shellHook;
|
||||
name = description;
|
||||
|
||||
# =========================================================================================
|
||||
# Define environment variables
|
||||
# =========================================================================================
|
||||
|
||||
# Dynamic libraries from buildinputs:
|
||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
in {
|
||||
# Provide package for "nix build"
|
||||
packages = {
|
||||
default = fail-bin;
|
||||
fail = fail-bin;
|
||||
wasi-sdk = wasi-sdk;
|
||||
iwasm = iwasm;
|
||||
wamrc = wamrc;
|
||||
};
|
||||
apps = {
|
||||
default = flake-utils.lib.mkApp {drv = fail-bin;};
|
||||
fail = fail-bin;
|
||||
wasi-sdk = wasi-sdk;
|
||||
iwasm = iwasm;
|
||||
wamrc = wamrc;
|
||||
};
|
||||
|
||||
devShells = {
|
||||
# Provide default environment for "nix develop".
|
||||
# Other environments can be added below.
|
||||
default = pkgs.mkShell {
|
||||
inherit nativeBuildInputs buildInputs shellHook;
|
||||
name = description;
|
||||
|
||||
# =========================================================================================
|
||||
# Define environment variables
|
||||
# =========================================================================================
|
||||
|
||||
# Dynamic libraries from buildinputs:
|
||||
# LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
||||
|
||||
# Those are read by compile.pl / build.pl
|
||||
FAIL_SHARE = "${fail-bin}/share";
|
||||
FAIL_PYTHON = "${python}/bin/python";
|
||||
WASI_ROOT = wasi-sdk;
|
||||
WAMR_ROOT = "/home/christoph/Notes/TU/MastersThesis/FailNix/wamr";
|
||||
CROSS_CC = "${i386_pkgs.stdenv.cc}/bin/i386-elf-gcc";
|
||||
CROSS_CXX = "${i386_pkgs.stdenv.cc}/bin/i386-elf-g++";
|
||||
LINUX_CC = "${pkgs.multiStdenv.cc}/bin/gcc";
|
||||
LINUX_CXX = "${pkgs.multiStdenv.cc}/bin/g++";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
BIN
ggplot2_a.png
(Stored with Git LFS)
Normal file
BIN
ggplot2_a.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
ggplot2_b.png
(Stored with Git LFS)
Normal file
BIN
ggplot2_b.png
(Stored with Git LFS)
Normal file
Binary file not shown.
72
schema.sql
Normal file
72
schema.sql
Normal file
@ -0,0 +1,72 @@
|
||||
CREATE TABLE `fspmethod` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`method` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `method` (`method`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE `fsppilot` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`known_outcome` tinyint(4) NOT NULL,
|
||||
`variant_id` int(11) NOT NULL,
|
||||
`instr2` int(10) unsigned NOT NULL,
|
||||
`injection_instr` int(10) unsigned NOT NULL,
|
||||
`injection_instr_absolute` bigint(10) unsigned DEFAULT NULL,
|
||||
`data_physical_address` bigint(10) unsigned NOT NULL,
|
||||
`bit_pos` tinyint(3) unsigned DEFAULT NULL,
|
||||
`data_width` int(10) unsigned NOT NULL,
|
||||
`fspmethod_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `fspmethod_id` (`fspmethod_id`,`variant_id`,`data_physical_address`,`instr2`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=6327 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE `fspgroup` (
|
||||
`variant_id` int(11) NOT NULL,
|
||||
`instr2` int(11) unsigned NOT NULL,
|
||||
`data_physical_address` bigint(10) unsigned NOT NULL,
|
||||
`bit_pos` tinyint(3) unsigned DEFAULT NULL,
|
||||
`fspmethod_id` int(11) NOT NULL,
|
||||
`pilot_id` int(11) NOT NULL,
|
||||
`weight` int(11) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`pilot_id`),
|
||||
KEY `joinresults` (`pilot_id`,`fspmethod_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE `variant` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`variant` varchar(100) NOT NULL,
|
||||
`benchmark` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `variant` (`variant`,`benchmark`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE `trace` (
|
||||
`variant_id` int(11) NOT NULL,
|
||||
`instr1` int(10) unsigned NOT NULL,
|
||||
`instr1_absolute` bigint(10) unsigned DEFAULT NULL,
|
||||
`instr2` int(10) unsigned NOT NULL,
|
||||
`instr2_absolute` bigint(10) unsigned DEFAULT NULL,
|
||||
`time1` bigint(10) unsigned NOT NULL,
|
||||
`time2` bigint(10) unsigned NOT NULL,
|
||||
`data_linear_address` bigint(10) unsigned NOT NULL,
|
||||
`data_physical_address` bigint(10) unsigned NOT NULL,
|
||||
`width` tinyint(3) unsigned NOT NULL,
|
||||
`accesstype` enum('R','W') NOT NULL,
|
||||
`cr3` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`variant_id`,`data_physical_address`,`instr2`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE `result_GenericExperimentMessage` (
|
||||
`pilot_id` int(10) unsigned NOT NULL,
|
||||
`inject_bursts` tinyint(4) NOT NULL,
|
||||
`inject_single_bit` tinyint(4) NOT NULL,
|
||||
`register_injection_mode` enum('OFF','AUTO','FORCE','RANDOMJUMP') DEFAULT NULL,
|
||||
`data_physical_address` bigint(20) unsigned NOT NULL,
|
||||
`bitoffset` int(10) unsigned NOT NULL,
|
||||
`original_value` int(10) unsigned NOT NULL,
|
||||
`injection_width` int(10) unsigned NOT NULL,
|
||||
`resulttype` enum('OK_MARKER','FAIL_MARKER','DETECTED_MARKER','GROUP1_MARKER','GROUP2_MARKER','GROUP3_MARKER','GROUP4_MARKER','TIMEOUT','TRAP','WRITE_TEXTSEGMENT','ACCESS_OUTERSPACE','SDC','UNKNOWN') NOT NULL,
|
||||
`crash_time` bigint(20) unsigned NOT NULL,
|
||||
`details` bigint(20) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`pilot_id`,`data_physical_address`,`bitoffset`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
133
scripts/Modules/Filters.pm
Normal file
133
scripts/Modules/Filters.pm
Normal file
@ -0,0 +1,133 @@
|
||||
package Filters;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin;
|
||||
use Util;
|
||||
|
||||
my %CONFIGS = (
|
||||
no_aot_instr => {
|
||||
label => "Exclude WAMR AOT array (instr)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_aot_start', '_wamr_aot_end',
|
||||
'p.injection_instr_absolute'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_aot_data => {
|
||||
label => "Exclude WAMR AOT array (data)",
|
||||
regions =>
|
||||
[ [ '_wamr_aot_start', '_wamr_aot_end', 'g.data_physical_address' ] ],
|
||||
},
|
||||
no_mmap_instr => {
|
||||
label => "Exclude WAMR mmap (instr)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_mmap_start', '_wamr_mmap_end',
|
||||
'p.injection_instr_absolute'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_mmap_data => {
|
||||
label => "Exclude WAMR mmap (data)",
|
||||
regions => [
|
||||
[ '_wamr_mmap_start', '_wamr_mmap_end', 'g.data_physical_address' ]
|
||||
],
|
||||
},
|
||||
no_runtime_pool_instr => {
|
||||
label => "Exclude WAMR runtime pool (instr)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_runtime_pool_start', '_wamr_runtime_pool_end',
|
||||
'p.injection_instr_absolute'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_runtime_pool_data => {
|
||||
label => "Exclude WAMR runtime pool (data)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_runtime_pool_start', '_wamr_runtime_pool_end',
|
||||
'g.data_physical_address'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_linear_pool_instr => {
|
||||
label => "Exclude WAMR linear pool (instr)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_linear_pool_start', '_wamr_linear_pool_end',
|
||||
'p.injection_instr_absolute'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_linear_pool_data => {
|
||||
label => "Exclude WAMR linear pool (data)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_linear_pool_start', '_wamr_linear_pool_end',
|
||||
'g.data_physical_address'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_global_heap_instr => {
|
||||
label => "Exclude WAMR global heap (instr)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_global_heap_start', '_wamr_global_heap_end',
|
||||
'p.injection_instr_absolute'
|
||||
]
|
||||
],
|
||||
},
|
||||
no_global_heap_data => {
|
||||
label => "Exclude WAMR global heap (data)",
|
||||
regions => [
|
||||
[
|
||||
'_wamr_global_heap_start', '_wamr_global_heap_end',
|
||||
'g.data_physical_address'
|
||||
]
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
# Those will be executed automatically by runner.pl (+ no filter at all)
|
||||
my @DEFAULT_CONFIGS = ('no_aot_data');
|
||||
|
||||
sub get_configs {
|
||||
return \%CONFIGS;
|
||||
}
|
||||
|
||||
sub get_default_configs {
|
||||
return @DEFAULT_CONFIGS;
|
||||
}
|
||||
|
||||
sub build_filter_clause {
|
||||
my ( $experiment_dir, $config_name ) = @_;
|
||||
|
||||
return "" unless defined $config_name && length($config_name) > 0;
|
||||
|
||||
my $regions = $CONFIGS{$config_name}{regions};
|
||||
return "" unless defined $regions;
|
||||
|
||||
return ""
|
||||
unless defined $experiment_dir && -f "$experiment_dir/system.elf";
|
||||
|
||||
my @filters;
|
||||
for my $pair (@$regions) {
|
||||
my ( $start_sym, $end_sym, $col ) = @$pair;
|
||||
my $start =
|
||||
Util::elf_sym_addr( "$experiment_dir/system.elf", $start_sym );
|
||||
my $end = Util::elf_sym_addr( "$experiment_dir/system.elf", $end_sym );
|
||||
next unless defined $start && defined $end && $end > $start;
|
||||
push @filters, "$col NOT BETWEEN $start AND @{[$end - 1]}";
|
||||
}
|
||||
|
||||
return "" unless @filters;
|
||||
return "\nAND " . join( "\nAND ", @filters );
|
||||
}
|
||||
|
||||
1;
|
||||
181
scripts/Modules/Mars.pm
Normal file
181
scripts/Modules/Mars.pm
Normal file
@ -0,0 +1,181 @@
|
||||
package Mars;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use DBI;
|
||||
use Net::OpenSSH;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
|
||||
my $_remote = undef;
|
||||
my $remote_host = 'mars'; # smchurla@mars.cs.tu-dortmund.de
|
||||
|
||||
# The mars db is bound to local port 3306 over SSH.
|
||||
# - This requires using the configured 'mars'
|
||||
# remote_host instead of smchurla@mars
|
||||
# or setting up another tunnel here
|
||||
my $_db = undef;
|
||||
my $db_host = "127.0.0.1";
|
||||
my $db_port = "3306";
|
||||
my $db_user = "smchurla";
|
||||
my $_db_password = undef;
|
||||
|
||||
sub ssh_connect {
|
||||
if ( !defined $_remote ) {
|
||||
|
||||
# Initialize SSH connection
|
||||
# - This connection also sets up the database tunnel
|
||||
$_remote = Net::OpenSSH->new(
|
||||
$remote_host,
|
||||
timeout => 30,
|
||||
master_opts => [
|
||||
-o => 'BatchMode=yes',
|
||||
-o => 'StrictHostKeyChecking=accept-new',
|
||||
-o => 'ServerAliveInterval=60',
|
||||
],
|
||||
);
|
||||
$_remote->error and die 'SSH connection failed: ' . $_remote->error;
|
||||
say 'Connected to mars.cs.tu-dortmund.de';
|
||||
}
|
||||
|
||||
return $_remote;
|
||||
}
|
||||
|
||||
sub ssh_system {
|
||||
my (@cmd) = @_;
|
||||
|
||||
my $ssh = ssh_connect();
|
||||
|
||||
$ssh->system(@cmd);
|
||||
$ssh->error and die "Remote command failed (@cmd): " . $ssh->error;
|
||||
}
|
||||
|
||||
sub ssh_capture {
|
||||
my (@cmd) = @_;
|
||||
|
||||
my $ssh = ssh_connect();
|
||||
|
||||
my $out = $ssh->capture(@cmd);
|
||||
$ssh->error and die "Remote command failed (@cmd): " . $ssh->error;
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub upload_dir {
|
||||
my ( $source_dir, $target_dir ) = @_;
|
||||
|
||||
my $ssh = ssh_connect();
|
||||
|
||||
say " - Uploading $source_dir to $target_dir...";
|
||||
$ssh->scp_put(
|
||||
{
|
||||
recursive => 1,
|
||||
copy_attrs => 1
|
||||
},
|
||||
$source_dir,
|
||||
$target_dir,
|
||||
) or die "Failed to upload $source_dir: " . $ssh->error;
|
||||
}
|
||||
|
||||
sub download_dir {
|
||||
my ( $source_dir, $target_dir ) = @_;
|
||||
|
||||
my $ssh = ssh_connect();
|
||||
|
||||
say " - Downloading $source_dir to $target_dir...";
|
||||
$ssh->scp_get(
|
||||
{
|
||||
recursive => 1,
|
||||
copy_attrs => 1
|
||||
},
|
||||
$source_dir,
|
||||
$target_dir,
|
||||
) or die "Failed to download $source_dir: " . $ssh->error;
|
||||
}
|
||||
|
||||
sub find_remote_subdirs {
|
||||
my ($dir) = @_;
|
||||
|
||||
my $out = ssh_capture(
|
||||
'find', $dir, '-mindepth', '1',
|
||||
'-maxdepth', '1', '-type', 'd',
|
||||
'-printf', '%f' . "\n",
|
||||
);
|
||||
|
||||
my @subdirs = sort grep { length } split /\n/, $out;
|
||||
|
||||
return @subdirs;
|
||||
}
|
||||
|
||||
sub read_db_password_file {
|
||||
if ( !defined $_db_password ) {
|
||||
open( my $fhandle, '<', "$local_root/mars-db.conf" )
|
||||
or die "Failed to read mars-db.conf: $!";
|
||||
chomp( $_db_password = <$fhandle> );
|
||||
close($fhandle);
|
||||
}
|
||||
|
||||
return $_db_password;
|
||||
}
|
||||
|
||||
sub db_connect {
|
||||
|
||||
# Opens tunnel for db_port
|
||||
my $ssh = ssh_connect();
|
||||
|
||||
if ( !defined $_db ) {
|
||||
$_db = DBI->connect( "DBI:MariaDB:host=$db_host;port=$db_port",
|
||||
$db_user, read_db_password_file() )
|
||||
or die 'Failed to connect to database: ' . $DBI::errstr;
|
||||
say 'Connected to database';
|
||||
}
|
||||
|
||||
return $_db;
|
||||
}
|
||||
|
||||
sub db_disconnect {
|
||||
if ( defined $_db ) {
|
||||
$_db->disconnect or warn $_db->errstr;
|
||||
}
|
||||
}
|
||||
|
||||
sub db_prefix {
|
||||
return $db_user;
|
||||
}
|
||||
|
||||
sub db_list {
|
||||
my $db = db_connect();
|
||||
|
||||
my @db_names =
|
||||
sort
|
||||
map { s/DBI:MariaDB://r }
|
||||
grep { !/information_schema|smchurla_ll/ } $db->data_sources();
|
||||
|
||||
return @db_names;
|
||||
}
|
||||
|
||||
sub db_do {
|
||||
my (@cmd) = @_;
|
||||
|
||||
my $db = db_connect();
|
||||
|
||||
$db->do(@cmd) or die "Database command failed (@cmd): " . $db->errstr;
|
||||
}
|
||||
|
||||
sub db_create {
|
||||
my ($db_name) = @_;
|
||||
say " - Creating database $db_name...";
|
||||
db_do("create database `$db_name`");
|
||||
}
|
||||
|
||||
sub db_drop {
|
||||
my ($db_name) = @_;
|
||||
say " - Dropping database $db_name...";
|
||||
db_do("drop database `$db_name`");
|
||||
}
|
||||
|
||||
1;
|
||||
110
scripts/Modules/TUI.pm
Normal file
110
scripts/Modules/TUI.pm
Normal file
@ -0,0 +1,110 @@
|
||||
package TUI;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use Curses::UI;
|
||||
|
||||
# Singleton
|
||||
my $_cui;
|
||||
|
||||
sub init_cui {
|
||||
if ( !defined $_cui ) {
|
||||
$_cui = new Curses::UI(
|
||||
-color_support => 1,
|
||||
-mouse_support => 1,
|
||||
|
||||
# -clear_on_exit => 1,
|
||||
);
|
||||
}
|
||||
|
||||
return $_cui;
|
||||
}
|
||||
|
||||
sub select_from_list {
|
||||
my ( $title, $multiselect, @items ) = @_;
|
||||
die "No items to choose from" unless @items;
|
||||
|
||||
my @values = $multiselect ? ( '__ALL__', @items ) : @items;
|
||||
my %labels =
|
||||
$multiselect
|
||||
? ( '__ALL__' => '[ALL]', map { $_ => $_ } @items, )
|
||||
: map { $_ => $_ } @items;
|
||||
|
||||
my @selection;
|
||||
my @selection_order; # multiselect only: items in toggle order
|
||||
|
||||
my $cui = init_cui();
|
||||
my $win = $cui->add( 'root', 'Window', );
|
||||
|
||||
my $listbox;
|
||||
$listbox = $win->add(
|
||||
'item_list',
|
||||
'Listbox',
|
||||
-title => $title,
|
||||
-border => 1,
|
||||
-values => \@values,
|
||||
-labels => \%labels,
|
||||
-multi => $multiselect == 1,
|
||||
-radio => $multiselect == 0,
|
||||
-padbottom => 1,
|
||||
-onchange => sub {
|
||||
return unless $multiselect;
|
||||
my %now = map { $_ => 1 } $listbox->get();
|
||||
|
||||
# Append newly selected items in toggle order
|
||||
for my $item (@items) {
|
||||
if ( $now{$item} && !grep { $_ eq $item } @selection_order ) {
|
||||
push @selection_order, $item;
|
||||
}
|
||||
}
|
||||
|
||||
# Drop deselected items
|
||||
@selection_order = grep { $now{$_} } @selection_order;
|
||||
},
|
||||
);
|
||||
|
||||
$win->add(
|
||||
'info', 'Label',
|
||||
-y => -1,
|
||||
-text => "Space/Enter = toggle, C = confirm, Q = quit",
|
||||
);
|
||||
|
||||
$listbox->clear_binding('loose-focus');
|
||||
|
||||
$listbox->set_binding(
|
||||
sub {
|
||||
my @picked = $listbox->get();
|
||||
if ( $multiselect && grep { $_ eq '__ALL__' } @picked ) {
|
||||
@selection = @items;
|
||||
}
|
||||
elsif ($multiselect) {
|
||||
@selection = @selection_order;
|
||||
}
|
||||
else {
|
||||
@selection = @picked;
|
||||
}
|
||||
$cui->mainloopExit();
|
||||
},
|
||||
'c',
|
||||
);
|
||||
|
||||
$listbox->set_binding(
|
||||
sub {
|
||||
@selection = ();
|
||||
$cui->mainloopExit();
|
||||
},
|
||||
'q',
|
||||
);
|
||||
|
||||
$listbox->focus();
|
||||
$cui->mainloop();
|
||||
|
||||
$cui->leave_curses();
|
||||
$cui->delete('root');
|
||||
|
||||
return @selection;
|
||||
}
|
||||
|
||||
1;
|
||||
330
scripts/Modules/Util.pm
Normal file
330
scripts/Modules/Util.pm
Normal file
@ -0,0 +1,330 @@
|
||||
package Util;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use DateTime;
|
||||
use FindBin;
|
||||
|
||||
# Include this for running from runner.pl
|
||||
use lib "$FindBin::Bin/../../scripts/Queries";
|
||||
|
||||
# Include this for running from menu.pl
|
||||
use lib "$FindBin::Bin/Queries";
|
||||
|
||||
use feature 'say';
|
||||
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_archive_dir = "$local_root/injections";
|
||||
|
||||
my $ntfy_url = 'https://ntfy.vps.chriphost.de';
|
||||
my $ntfy_token = 'tk_rx8fd6hojuz4ekcb72j7juugkbmga'; # May be public
|
||||
my $ntfy_topic = 'fail-alerts';
|
||||
|
||||
sub notify {
|
||||
my ($msg) = @_;
|
||||
|
||||
system( 'curl', '-H', "Authorization: Bearer $ntfy_token",
|
||||
'-d', $msg, "$ntfy_url/$ntfy_topic" );
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
sub notify_file {
|
||||
my ($file) = @_;
|
||||
|
||||
system(
|
||||
'curl', '-H', "Authorization: Bearer $ntfy_token",
|
||||
'-T', $file, '-H', "Filename: $file",
|
||||
"$ntfy_url/$ntfy_topic"
|
||||
);
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
sub shell_quote {
|
||||
my ($string) = @_;
|
||||
$string =~ s/'/'"'"'/g;
|
||||
return "'$string'";
|
||||
}
|
||||
|
||||
sub date_now {
|
||||
my $dt = DateTime->now( time_zone => 'local' );
|
||||
my $date = $dt->iso8601;
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
sub run {
|
||||
my @cmd = @_;
|
||||
say "Running: @cmd";
|
||||
system(@cmd) == 0
|
||||
or die "Command failed (exit " . ( $? >> 8 ) . "): @cmd\n";
|
||||
}
|
||||
|
||||
sub read_file {
|
||||
my ($file) = @_;
|
||||
open( my $readhandle, '<', $file ) or die "failed to open $file: $!";
|
||||
local $/;
|
||||
my $content = <$readhandle> // die "failed to read $file: $!";
|
||||
close($readhandle) or die "failed to close $file: $!";
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub write_file {
|
||||
my ( $file, $content ) = @_;
|
||||
open( my $writehandle, '>', $file ) or die "failed to open $file: $!";
|
||||
print $writehandle $content or die "failed to write $file: $!";
|
||||
close($writehandle) or die "failed to close $file: $!";
|
||||
}
|
||||
|
||||
sub rewrite_file {
|
||||
my ( $file, $matches, $replacement ) = @_;
|
||||
|
||||
open( my $readhandle, '<', $file ) or die "failed to open $file: $!";
|
||||
my @lines;
|
||||
my $found = 0;
|
||||
while ( my $line = <$readhandle> ) {
|
||||
if ( index( $line, $matches ) != -1 ) {
|
||||
$line = $replacement;
|
||||
$found = 1;
|
||||
}
|
||||
push @lines, $line;
|
||||
}
|
||||
close($readhandle) or die "failed to close $file: $!";
|
||||
|
||||
die "no line containing $matches found in $file" unless $found;
|
||||
|
||||
open( my $writehandle, '>', $file ) or die "failed to open $file: $!";
|
||||
print $writehandle @lines or die "failed to write $file: $!";
|
||||
close($writehandle) or die "failed to close $file: $!";
|
||||
|
||||
say "Updated $file with $replacement";
|
||||
}
|
||||
|
||||
sub cpu_count {
|
||||
open( my $handle, '/proc/cpuinfo' ) or die "Can't open cpuinfo: $!\n";
|
||||
my $count = scalar( map /^processor/, <$handle> );
|
||||
close $handle;
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
sub find_files {
|
||||
my ($dir) = @_;
|
||||
|
||||
opendir( my $dhandle, $dir ) or die "opendir($dir): $!";
|
||||
my @files = sort grep { -f "$dir/$_" } readdir($dhandle);
|
||||
closedir($dhandle);
|
||||
|
||||
return @files;
|
||||
}
|
||||
|
||||
sub find_subdirs {
|
||||
my ($dir) = @_;
|
||||
|
||||
opendir( my $dhandle, $dir ) or die "opendir($dir): $!";
|
||||
my @subdirs =
|
||||
sort grep { $_ ne '.' && $_ ne '..' && -d "$dir/$_" } readdir($dhandle);
|
||||
closedir($dhandle);
|
||||
|
||||
return @subdirs;
|
||||
}
|
||||
|
||||
sub execute_query {
|
||||
my ( $experiment, $queryname, $db_conf, $builds_dir, $do_notify_file,
|
||||
$filter_config_name )
|
||||
= @_;
|
||||
|
||||
my $module = "$queryname";
|
||||
my $file = "$module.pm";
|
||||
$file =~ s/::/\//g;
|
||||
|
||||
require $file;
|
||||
|
||||
my $query = $module->can('query') or die "$module can't query()";
|
||||
my $args = $module->can('args') or die "$module can't args()";
|
||||
my $filename = $module->can('filename') or die "$module can't filename()";
|
||||
my $postprocess = $module->can('postprocess')
|
||||
or die "$module can't postprocess()";
|
||||
|
||||
my $querystring =
|
||||
$query->( $experiment, "$builds_dir/$experiment", $filter_config_name );
|
||||
my $argsstring = $args->();
|
||||
my $filenamestring = $filename->($filter_config_name);
|
||||
|
||||
# TODO: Pass the values instead of rewriting db.conf.
|
||||
# Can also use DBI's database handle directly.
|
||||
my $result =
|
||||
qx{mariadb --defaults-file=$db_conf $argsstring -e "$querystring"};
|
||||
die "Query failed: $?" if $? != 0;
|
||||
|
||||
$postprocess->($result);
|
||||
|
||||
system( 'mkdir', '-p', "$builds_dir/$experiment" );
|
||||
open( my $results_handle, '>', "$builds_dir/$experiment/$filenamestring" )
|
||||
or die "failed to open file: $!";
|
||||
print $results_handle $result;
|
||||
close($results_handle) or die "failed to close file: $!";
|
||||
|
||||
if ( defined $do_notify_file and $do_notify_file == 1 ) {
|
||||
notify_file("$builds_dir/$experiment/$filenamestring");
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub format_number_sep {
|
||||
my ($number) = @_;
|
||||
1 while $number =~ s/^(-?\d+)(\d{3})/$1.$2/;
|
||||
return $number;
|
||||
}
|
||||
|
||||
sub elf_sym_addr {
|
||||
my ( $elffile, $sym ) = @_;
|
||||
my $line = qx{nm "$elffile" 2>/dev/null | grep " $sym\$"};
|
||||
return undef unless $line =~ /^([0-9a-f]+)/i;
|
||||
return hex($1);
|
||||
}
|
||||
|
||||
sub elf_read_sections {
|
||||
my ($elffile) = @_;
|
||||
|
||||
my $readelf_out = qx{readelf -S $elffile};
|
||||
my @lines = split "\n", $readelf_out;
|
||||
|
||||
my @sections;
|
||||
foreach my $line (@lines) {
|
||||
|
||||
# [ 1] .text PROGBITS 00100000 001000 0000f0 00 AX 0 0 4
|
||||
next
|
||||
unless $line =~
|
||||
/^\s*\[\s*\d+\]\s+(\..+?)\s+([A-Z]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+.*$/;
|
||||
|
||||
push @sections, {
|
||||
name => $1,
|
||||
type => $2,
|
||||
address => $3, # Memory location
|
||||
offset => $4, # File location
|
||||
size => $5,
|
||||
};
|
||||
}
|
||||
|
||||
return @sections;
|
||||
}
|
||||
|
||||
sub get_section_name {
|
||||
my ( $address, @sections ) = @_;
|
||||
|
||||
my $name;
|
||||
my $last_address = 0;
|
||||
foreach my $section (@sections) {
|
||||
my $cur_address = hex( $section->{address} );
|
||||
if ( hex($address) >= $cur_address && $cur_address > $last_address ) {
|
||||
$name = $section->{name};
|
||||
$last_address = $cur_address;
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
sub read_experiment_info {
|
||||
my ($exp) = @_;
|
||||
|
||||
return unless ( -f "$local_archive_dir/$exp/0.info" );
|
||||
|
||||
open( my $fhandle, '<', "$local_archive_dir/$exp/0.info" )
|
||||
or die "Failed to open 0.info: $!";
|
||||
my $info = <$fhandle>;
|
||||
chomp $info if defined $info;
|
||||
close($fhandle);
|
||||
|
||||
return defined $info ? $info : "";
|
||||
}
|
||||
|
||||
sub read_marker_info {
|
||||
my ( $experiment, $benchmark, $address ) = @_;
|
||||
|
||||
return ""
|
||||
unless (
|
||||
-f "$local_archive_dir/$experiment/markers/$benchmark-$address.info" );
|
||||
|
||||
open( my $fhandle, '<',
|
||||
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" )
|
||||
or die "Failed to open $benchmark-$address.info: $!";
|
||||
local $/;
|
||||
my $info = <$fhandle>;
|
||||
chomp $info;
|
||||
close($fhandle);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
sub overwrite_marker_info {
|
||||
my ( $experiment, $benchmark, $address, $info ) = @_;
|
||||
|
||||
system( 'mkdir', '-p', "$local_archive_dir/$experiment/markers" );
|
||||
|
||||
open( my $fhandle, '>',
|
||||
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" )
|
||||
or die "Failed to open $benchmark-$address.info: $!";
|
||||
print $fhandle $info;
|
||||
close($fhandle);
|
||||
}
|
||||
|
||||
sub delete_marker_info {
|
||||
my ( $experiment, $benchmark, $address ) = @_;
|
||||
|
||||
system( 'rm',
|
||||
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" );
|
||||
}
|
||||
|
||||
sub pick_data_file {
|
||||
my ( $dir, $prefix ) = @_;
|
||||
|
||||
# \Q...\E treats ... as literal string
|
||||
my @files = sort grep { /^\Q$prefix\E.*\.csv$/ } find_files($dir);
|
||||
|
||||
return "$prefix.csv" unless @files > 1;
|
||||
|
||||
# Make sure the unfiltered file is at the top
|
||||
my @sorted = sort {
|
||||
( $a eq "$prefix.csv" ) ? -1
|
||||
: ( $b eq "$prefix.csv" ) ? 1
|
||||
: $a cmp $b
|
||||
} @files;
|
||||
|
||||
my @selected =
|
||||
TUI::select_from_list( "Select $prefix CSV file", 0, @sorted );
|
||||
die "No $prefix CSV file selected" unless @selected;
|
||||
return $selected[0];
|
||||
}
|
||||
|
||||
sub select_experiment {
|
||||
my ($multi) = @_;
|
||||
|
||||
my @experiments = find_subdirs($local_archive_dir);
|
||||
|
||||
my @exp_with_notes;
|
||||
foreach my $exp (@experiments) {
|
||||
my $info = read_experiment_info($exp);
|
||||
|
||||
push @exp_with_notes,
|
||||
( defined $info && length($info) > 0 )
|
||||
? sprintf( "%-50s (%s)", $exp, $info )
|
||||
: $exp;
|
||||
}
|
||||
|
||||
my @selected_experiments =
|
||||
TUI::select_from_list( "Select Experiment", $multi, @exp_with_notes );
|
||||
die "No experiment selected" unless @selected_experiments;
|
||||
|
||||
@selected_experiments =
|
||||
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_experiments;
|
||||
|
||||
return $multi == 1 ? @selected_experiments : $selected_experiments[0];
|
||||
}
|
||||
|
||||
1;
|
||||
48
scripts/Queries/Faults.pm
Normal file
48
scripts/Queries/Faults.pm
Normal file
@ -0,0 +1,48 @@
|
||||
package Faults;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../Modules";
|
||||
use Filters;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
sub query {
|
||||
my ( $experiment, $experiment_dir, $filter_config_name ) = @_;
|
||||
$filter_config_name //= '';
|
||||
|
||||
my $filters =
|
||||
Filters::build_filter_clause( $experiment_dir, $filter_config_name );
|
||||
|
||||
my $querystring = "SELECT
|
||||
benchmark, resulttype, SUM(t.time2 - t.time1 + 1) AS faults,
|
||||
CONCAT('0x', HEX(p.injection_instr_absolute)) AS fault_address
|
||||
FROM variant v
|
||||
JOIN trace t ON v.id = t.variant_id
|
||||
JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_physical_address = t.data_physical_address
|
||||
JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
||||
JOIN fsppilot p ON r.pilot_id = p.id
|
||||
WHERE v.variant = '$experiment'$filters
|
||||
GROUP BY benchmark, resulttype, p.injection_instr_absolute
|
||||
ORDER BY benchmark, resulttype, SUM(t.time2 - t.time1 + 1) DESC;";
|
||||
|
||||
say $querystring;
|
||||
|
||||
return $querystring;
|
||||
}
|
||||
|
||||
sub args { return "--batch --raw"; }
|
||||
|
||||
sub filename {
|
||||
my ($filter_config_name) = @_;
|
||||
$filter_config_name //= '';
|
||||
my $suffix = length($filter_config_name) ? "_$filter_config_name" : "";
|
||||
return "faults${suffix}.csv";
|
||||
}
|
||||
|
||||
sub postprocess { $_[0] =~ s/\t/,/g; }
|
||||
|
||||
1;
|
||||
47
scripts/Queries/Results.pm
Normal file
47
scripts/Queries/Results.pm
Normal file
@ -0,0 +1,47 @@
|
||||
package Results;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../Modules";
|
||||
use Filters;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
sub query {
|
||||
my ( $experiment, $experiment_dir, $filter_config_name ) = @_;
|
||||
$filter_config_name //= '';
|
||||
|
||||
my $extra =
|
||||
Filters::build_filter_clause( $experiment_dir, $filter_config_name );
|
||||
|
||||
my $querystring = "SELECT
|
||||
benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults
|
||||
FROM variant v
|
||||
JOIN trace t ON v.id = t.variant_id
|
||||
JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_physical_address = t.data_physical_address
|
||||
JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
||||
JOIN fsppilot p ON r.pilot_id = p.id
|
||||
WHERE v.variant = '$experiment'$extra
|
||||
GROUP BY v.id, resulttype
|
||||
ORDER BY variant, benchmark, resulttype;";
|
||||
|
||||
say $querystring;
|
||||
|
||||
return $querystring;
|
||||
}
|
||||
|
||||
sub args { return "-t"; }
|
||||
|
||||
sub filename {
|
||||
my ($filter_config_name) = @_;
|
||||
$filter_config_name //= '';
|
||||
my $suffix = length($filter_config_name) ? "_$filter_config_name" : "";
|
||||
return "results${suffix}.txt";
|
||||
}
|
||||
|
||||
sub postprocess { }
|
||||
|
||||
1;
|
||||
47
scripts/Queries/ResultsData.pm
Normal file
47
scripts/Queries/ResultsData.pm
Normal file
@ -0,0 +1,47 @@
|
||||
package ResultsData;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../Modules";
|
||||
use Filters;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
sub query {
|
||||
my ( $experiment, $experiment_dir, $filter_config_name ) = @_;
|
||||
$filter_config_name //= '';
|
||||
|
||||
my $extra =
|
||||
Filters::build_filter_clause( $experiment_dir, $filter_config_name );
|
||||
|
||||
my $querystring = "SELECT
|
||||
benchmark, resulttype, sum(t.time2 - t.time1 + 1) AS faults
|
||||
FROM variant v
|
||||
JOIN trace t ON v.id = t.variant_id
|
||||
JOIN fspgroup g ON g.variant_id = t.variant_id AND g.instr2 = t.instr2 AND g.data_physical_address = t.data_physical_address
|
||||
JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
||||
JOIN fsppilot p ON r.pilot_id = p.id
|
||||
WHERE v.variant = '$experiment'$extra
|
||||
GROUP BY v.id, resulttype
|
||||
ORDER BY variant, benchmark, resulttype;";
|
||||
|
||||
say $querystring;
|
||||
|
||||
return $querystring;
|
||||
}
|
||||
|
||||
sub args { return "--batch --raw"; }
|
||||
|
||||
sub filename {
|
||||
my ($filter_config_name) = @_;
|
||||
$filter_config_name //= '';
|
||||
my $suffix = length($filter_config_name) ? "_$filter_config_name" : "";
|
||||
return "resultsdata${suffix}.csv";
|
||||
}
|
||||
|
||||
sub postprocess { $_[0] =~ s/\t/,/g; }
|
||||
|
||||
1;
|
||||
307
scripts/build.pl
Executable file
307
scripts/build.pl
Executable file
@ -0,0 +1,307 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
|
||||
use Util;
|
||||
use TUI;
|
||||
|
||||
use POSIX qw(strftime);
|
||||
use feature 'say';
|
||||
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_builds_dir = "$local_root/builds";
|
||||
my $local_experiments_dir = "$local_root/targets/wasm-module";
|
||||
my $compile_pl = "$local_root/scripts/compile.pl";
|
||||
|
||||
sub compile {
|
||||
my ( $module, $target, $mode ) = @_;
|
||||
say "Running: WAMR_USE_AOT_IN_TEXT=$ENV{WAMR_USE_AOT_IN_TEXT}",
|
||||
" WAMR_USE_MMAP_IN_TEXT=$ENV{WAMR_USE_MMAP_IN_TEXT}",
|
||||
" WAMR_USE_XIP=$ENV{WAMR_USE_XIP}",
|
||||
" WAMR_USE_ALLOCATOR=$ENV{WAMR_USE_ALLOCATOR}",
|
||||
" WAMR_USE_GLOBAL_HEAP_IN_TEXT=$ENV{WAMR_USE_GLOBAL_HEAP_IN_TEXT}",
|
||||
" WAMR_USE_RUNTIME_POOL_IN_TEXT=$ENV{WAMR_USE_RUNTIME_POOL_IN_TEXT}",
|
||||
" WAMR_USE_LINEAR_POOL_IN_TEXT=$ENV{WAMR_USE_LINEAR_POOL_IN_TEXT}",
|
||||
" compile.pl $module $target $mode";
|
||||
|
||||
system(
|
||||
"perl $compile_pl $module $target $mode > $local_root/build.log 2>&1")
|
||||
== 0
|
||||
or die "Build failed\n";
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
# Find and select experiments
|
||||
my @experiments = map { s/\.cpp//r } Util::find_files($local_experiments_dir);
|
||||
my @selected_experiments =
|
||||
TUI::select_from_list( "Select Experiments to Build", 1, @experiments );
|
||||
die "No experiment selected" unless @selected_experiments;
|
||||
|
||||
# Select targets
|
||||
my @targets = ( "fail", "linux", "linux-baremetal" );
|
||||
my @selected_targets =
|
||||
TUI::select_from_list( "Select Target Platforms", 1, @targets );
|
||||
die "No target selected" unless @selected_targets;
|
||||
|
||||
# Select modes
|
||||
my @modes = ( "c", "aot", "interp" );
|
||||
my @selected_modes =
|
||||
TUI::select_from_list( "Select Execution Modes", 1, @modes );
|
||||
die "No mode selected" unless @selected_modes;
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select WAMR allocator variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @allocator_variants = (
|
||||
"Pool allocator (Alloc_With_Pool)",
|
||||
"Allocator with usage (Alloc_With_Allocator)",
|
||||
);
|
||||
my $selected_allocator_variant = $allocator_variants[1];
|
||||
if ( grep { $_ eq "aot" or $_ eq "interp" } @selected_modes ) {
|
||||
($selected_allocator_variant) =
|
||||
TUI::select_from_list( "Select WAMR Allocator Variant",
|
||||
0, @allocator_variants );
|
||||
die "No allocator variant selected" unless $selected_allocator_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_ALLOCATOR} =
|
||||
( $selected_allocator_variant eq $allocator_variants[1] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select XIP variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @xip_variants = ( "Compile AOT with --xip", "Compile AOT without --xip" );
|
||||
my $selected_xip_variant = $xip_variants[0];
|
||||
if ( grep { $_ eq "aot" } @selected_modes ) {
|
||||
($selected_xip_variant) =
|
||||
TUI::select_from_list( "Select WAMRC XIP Variant", 0, @xip_variants );
|
||||
die "No XIP variant selected" unless $selected_xip_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_XIP} =
|
||||
( $selected_xip_variant eq $xip_variants[0] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select .text.wamr_mmap variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @mmap_variants = (
|
||||
"Place mmap_space in .text.wamr_mmap",
|
||||
"Let the linker decide where mmap_space is located"
|
||||
);
|
||||
my $selected_mmap_variant = $mmap_variants[1];
|
||||
if ( grep { $_ eq "aot" or $_ eq "interp" } @selected_modes ) {
|
||||
($selected_mmap_variant) =
|
||||
TUI::select_from_list( "Select WAMR Mmap.Text Variant",
|
||||
0, @mmap_variants );
|
||||
die "No variant selected" unless $selected_mmap_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_MMAP_IN_TEXT} =
|
||||
( $selected_mmap_variant eq $mmap_variants[0] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select .text.wamr_aot variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @aot_section_variants = (
|
||||
"Place AOT array in .text.wamr_aot",
|
||||
"Let the linker decide where the AOT array is located",
|
||||
);
|
||||
my $selected_aot_variant = $aot_section_variants[1];
|
||||
if ( grep { $_ eq "aot" } @selected_modes ) {
|
||||
($selected_aot_variant) =
|
||||
TUI::select_from_list( "Select WAMR Array.Text Variant",
|
||||
0, @aot_section_variants );
|
||||
die "No AOT section variant selected" unless $selected_aot_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_AOT_IN_TEXT} =
|
||||
( $selected_aot_variant eq $aot_section_variants[0] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select .text.wamr_global_heap variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @global_heap_variants = (
|
||||
"Place pool allocator's global_heap in .text.wamr_global_heap",
|
||||
"Let the linker decide where global_heap is located"
|
||||
);
|
||||
my $selected_global_heap_variant = $global_heap_variants[1];
|
||||
if ( grep { $_ eq "aot" or $_ eq "interp" } @selected_modes
|
||||
and $selected_allocator_variant eq $allocator_variants[0] )
|
||||
{
|
||||
($selected_global_heap_variant) =
|
||||
TUI::select_from_list( "Select WAMR Global Heap Variant",
|
||||
0, @global_heap_variants );
|
||||
die "No global heap variant selected" unless $selected_global_heap_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_GLOBAL_HEAP_IN_TEXT} =
|
||||
( $selected_global_heap_variant eq $global_heap_variants[0] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select .text.wamr_runtime_pool variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @runtime_pool_variants = (
|
||||
"Place usage allocator's runtime_pool in .text.wamr_runtime_pool",
|
||||
"Let the linker decide where runtime_pool is located"
|
||||
);
|
||||
my $selected_runtime_pool_variant = $runtime_pool_variants[1];
|
||||
if ( grep { $_ eq "aot" or $_ eq "interp" } @selected_modes
|
||||
and $selected_allocator_variant eq $allocator_variants[1] )
|
||||
{
|
||||
($selected_runtime_pool_variant) =
|
||||
TUI::select_from_list( "Select WAMR Runtime Pool Variant",
|
||||
0, @runtime_pool_variants );
|
||||
die "No runtime pool variant selected"
|
||||
unless $selected_runtime_pool_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_RUNTIME_POOL_IN_TEXT} =
|
||||
( $selected_runtime_pool_variant eq $runtime_pool_variants[0] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select .text.wamr_linear_pool variant
|
||||
# ========================================================================================= #
|
||||
|
||||
my @linear_pool_variants = (
|
||||
"Place usage allocator's linear_pool in .text.wamr_linear_pool",
|
||||
"Let the linker decide where linear_pool is located"
|
||||
);
|
||||
my $selected_linear_pool_variant = $linear_pool_variants[1];
|
||||
if ( grep { $_ eq "aot" or $_ eq "interp" } @selected_modes
|
||||
and $selected_allocator_variant eq $allocator_variants[1] )
|
||||
{
|
||||
($selected_linear_pool_variant) =
|
||||
TUI::select_from_list( "Select WAMR Linear Pool Variant",
|
||||
0, @linear_pool_variants );
|
||||
die "No linear pool variant selected" unless $selected_linear_pool_variant;
|
||||
}
|
||||
local $ENV{WAMR_USE_LINEAR_POOL_IN_TEXT} =
|
||||
( $selected_linear_pool_variant eq $linear_pool_variants[0] )
|
||||
? "true"
|
||||
: "false";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Select FAIL catch flags (written to runner_flags in each build dir)
|
||||
# ========================================================================================= #
|
||||
|
||||
# NOTE: The runner will prefix "-Wf," to each flag
|
||||
my %catch_flag_map = (
|
||||
"--catch-outer" => "--catch-outerspace",
|
||||
"--catch-text" => "--catch-write-textsegment",
|
||||
"--wamr-exceptions" => "--group1-marker=fail_marker_group1",
|
||||
);
|
||||
my @selected_catch_flags;
|
||||
if ( grep { $_ eq "fail" } @selected_targets ) {
|
||||
@selected_catch_flags =
|
||||
TUI::select_from_list( "Select FAIL Flags", 1,
|
||||
sort keys %catch_flag_map );
|
||||
}
|
||||
|
||||
# ========================================================================================= #
|
||||
# Build everything
|
||||
# ========================================================================================= #
|
||||
|
||||
# TODO: linux-baremetal target is broken
|
||||
system( "mkdir", "-p", "$local_builds_dir" );
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
foreach my $target (@selected_targets) {
|
||||
foreach my $mode (@selected_modes) {
|
||||
|
||||
my $allocator_info = "";
|
||||
if ( $mode eq "aot" || $mode eq "interp" ) {
|
||||
$allocator_info =
|
||||
$selected_allocator_variant eq $allocator_variants[0]
|
||||
? "alloc_pool"
|
||||
: "alloc_usage";
|
||||
}
|
||||
my $xip_info =
|
||||
( $mode eq "aot"
|
||||
&& $selected_xip_variant
|
||||
&& $selected_xip_variant eq $xip_variants[0] )
|
||||
? "xip"
|
||||
: "";
|
||||
my $aot_info =
|
||||
( $mode eq "aot"
|
||||
&& $selected_aot_variant
|
||||
&& $selected_aot_variant eq $aot_section_variants[0] )
|
||||
? "wamr_aot"
|
||||
: "";
|
||||
my $mmap_info =
|
||||
( ( $mode eq "aot" || $mode eq "interp" )
|
||||
&& $selected_mmap_variant eq $mmap_variants[0] )
|
||||
? "wamr_mmap"
|
||||
: "";
|
||||
my $global_heap_info =
|
||||
( ( $mode eq "aot" || $mode eq "interp" )
|
||||
&& $selected_global_heap_variant
|
||||
&& $selected_global_heap_variant eq $global_heap_variants[0] )
|
||||
? "wamr_global_heap"
|
||||
: "";
|
||||
my $runtime_pool_info =
|
||||
( ( $mode eq "aot" || $mode eq "interp" )
|
||||
&& $selected_runtime_pool_variant
|
||||
&& $selected_runtime_pool_variant eq
|
||||
$runtime_pool_variants[0] )
|
||||
? "wamr_runtime_pool"
|
||||
: "";
|
||||
my $linear_pool_info =
|
||||
( ( $mode eq "aot" || $mode eq "interp" )
|
||||
&& $selected_linear_pool_variant
|
||||
&& $selected_linear_pool_variant eq $linear_pool_variants[0] )
|
||||
? "wamr_linear_pool"
|
||||
: "";
|
||||
my $flags_info = join " ", @selected_catch_flags;
|
||||
|
||||
my $info_str = join " ",
|
||||
grep { length } (
|
||||
$mode, $aot_info, $mmap_info,
|
||||
$allocator_info, $global_heap_info, $runtime_pool_info,
|
||||
$linear_pool_info, $xip_info, $flags_info
|
||||
);
|
||||
|
||||
# Build experiment
|
||||
my $date = strftime( "%m-%d_%H-%M-%S", localtime );
|
||||
compile( $experiment, $target, $mode );
|
||||
|
||||
# Write extra info for the menu
|
||||
system("echo '$info_str' > $local_root/build-$experiment/0.info");
|
||||
|
||||
# Write runner_flags so runner.pl knows which FAIL flags to use
|
||||
my $runner_flags_path =
|
||||
"$local_root/build-$experiment/runner_flags";
|
||||
open( my $fhandle, '>', $runner_flags_path )
|
||||
or die "Cannot write $runner_flags_path: $!";
|
||||
print $fhandle "$catch_flag_map{$_}\n" for @selected_catch_flags;
|
||||
close($fhandle);
|
||||
|
||||
system( "mv", "$local_root/build.log",
|
||||
"$local_root/build-$experiment/build.log" );
|
||||
|
||||
system(
|
||||
join " ",
|
||||
(
|
||||
"mv",
|
||||
"$local_root/build-$experiment",
|
||||
"$local_builds_dir/${date}_${experiment}_${mode}_${target}",
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
scripts/charts/combined_sankey.r
Normal file
83
scripts/charts/combined_sankey.r
Normal file
@ -0,0 +1,83 @@
|
||||
library(ggplot2)
|
||||
library(ggalluvial)
|
||||
|
||||
# Usage: Rscript combined_comparion.r exp_abspath1 exp_abspath2 ...
|
||||
|
||||
args <- commandArgs(trailingOnly = TRUE)
|
||||
argc <- length(args)
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
print("Expecting two or three arguments: exp1 exp2 [faults_file]")
|
||||
stop()
|
||||
}
|
||||
|
||||
faults_file <- if (argc == 3) args[3] else "faults.csv"
|
||||
suffix <- gsub("^faults|\\.csv$", "", faults_file)
|
||||
|
||||
for (experiment in args[1:2]) {
|
||||
datafile <- file.path(experiment, faults_file)
|
||||
if (!file.exists(datafile)) {
|
||||
print(paste("Input file", datafile, "is missing"))
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
resulttype_labels <- c(
|
||||
OK_MARKER = "OK",
|
||||
FAIL_MARKER = "FAIL",
|
||||
DETECTED_MARKER = "DETECTED",
|
||||
TIMEOUT = "TIMEOUT",
|
||||
TRAP = "TRAP",
|
||||
ACCESS_OUTERSPACE = "OUTERSPC",
|
||||
WRITE_TEXTSEGMENT = "WRITETXT"
|
||||
)
|
||||
|
||||
# Read data
|
||||
datafile1 <- file.path(args[1], faults_file)
|
||||
data1 <- readr::read_csv(datafile1)
|
||||
data1$fault_address <- strtoi(data1$fault_address)
|
||||
data1$resulttype <- resulttype_labels[data1$resulttype]
|
||||
# tibble::glimpse(data1)
|
||||
|
||||
datafile2 <- file.path(args[2], faults_file)
|
||||
data2 <- readr::read_csv(datafile2)
|
||||
data2$fault_address <- strtoi(data2$fault_address)
|
||||
data2$resulttype <- resulttype_labels[data2$resulttype]
|
||||
# tibble::glimpse(data2)
|
||||
|
||||
# https://corybrunson.github.io/ggalluvial/
|
||||
joined <- merge(
|
||||
data1[, c("fault_address", "resulttype", "faults")],
|
||||
data2[, c("fault_address", "resulttype", "faults")],
|
||||
by = "fault_address",
|
||||
suffixes = c("_bench1", "_bench2")
|
||||
)
|
||||
|
||||
streams <- aggregate(
|
||||
faults_bench2 ~ resulttype_bench1 + resulttype_bench2,
|
||||
data = joined,
|
||||
sum
|
||||
)
|
||||
names(streams) <- c("bench1", "bench2", "faults")
|
||||
|
||||
plot <- ggplot(
|
||||
data = streams,
|
||||
aes(axis1 = bench1, axis2 = bench2, y = faults)
|
||||
) +
|
||||
scale_x_discrete(
|
||||
# TODO: Name the benchmarks
|
||||
# limits = c(args[1], args[2])
|
||||
limits = c("Bench A", "Bench B")
|
||||
) +
|
||||
labs(x = "Benchmark", y = "Faults") +
|
||||
geom_alluvium(aes(fill = bench1)) +
|
||||
geom_stratum() +
|
||||
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
|
||||
theme_minimal() +
|
||||
theme(legend.position = "none")
|
||||
|
||||
# TODO: Name the file according to the benchmarks
|
||||
ggsave(
|
||||
paste0(args[2], "/../sankey", suffix, ".svg"),
|
||||
plot = plot,
|
||||
)
|
||||
511
scripts/charts/single_heatmap.r
Normal file
511
scripts/charts/single_heatmap.r
Normal file
@ -0,0 +1,511 @@
|
||||
library(ggplot2)
|
||||
library(readr) # read_csv
|
||||
library(dplyr) # filter, mutate
|
||||
library(tidyr) # complete
|
||||
library(scales)
|
||||
|
||||
# Usage: Rscript single_heatmap.r exp_abspath
|
||||
|
||||
# =============================================================================
|
||||
# CONFIG
|
||||
# =============================================================================
|
||||
|
||||
# Starting row width (might be scaled up)
|
||||
row_width_init <- 16L
|
||||
|
||||
# Max number of occupied rows before row_width is doubled
|
||||
max_rows <- 64L
|
||||
|
||||
# How many x-axis tick labels to show
|
||||
n_x_ticks <- 16L
|
||||
|
||||
# Target size (inches, no margins)
|
||||
target_w <- 10.0
|
||||
target_h <- 6.0
|
||||
|
||||
# Max size so small grids don't produce huge tiles
|
||||
max_tile <- 0.5
|
||||
|
||||
# Generate all heatmaps with crossproduct of this
|
||||
benchmarks <- c("ip", "mem", "regs")
|
||||
markers <- c(
|
||||
"OK_MARKER",
|
||||
"FAIL_MARKER",
|
||||
"DETECTED_MARKER",
|
||||
"ACCESS_OUTERSPACE",
|
||||
"WRITE_TEXTSEGMENT",
|
||||
"GROUP1_MARKER",
|
||||
"TRAP",
|
||||
"TIMEOUT"
|
||||
)
|
||||
|
||||
# Labels for _start/_end symbols from linker.ld
|
||||
regions <- list(
|
||||
list(label = "WAMR AOT", start = "_wamr_aot_start", end = "_wamr_aot_end"),
|
||||
list(
|
||||
label = "WAMR os_mmap",
|
||||
start = "_wamr_mmap_start",
|
||||
end = "_wamr_mmap_end"
|
||||
),
|
||||
list(
|
||||
label = "WAMR runtime mem",
|
||||
start = "_wamr_runtime_pool_start",
|
||||
end = "_wamr_runtime_pool_end"
|
||||
),
|
||||
list(
|
||||
label = "WAMR linear mem",
|
||||
start = "_wamr_linear_pool_start",
|
||||
end = "_wamr_linear_pool_end"
|
||||
),
|
||||
list(
|
||||
label = "WAMR global heap",
|
||||
start = "_wamr_global_heap_start",
|
||||
end = "_wamr_global_heap_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM AOT runtime",
|
||||
start = "_iwasm_aot_runtime_start",
|
||||
end = "_iwasm_aot_runtime_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM bh/util",
|
||||
start = "_iwasm_bh_start",
|
||||
end = "_iwasm_bh_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM mem_alloc",
|
||||
start = "_iwasm_mem_alloc_start",
|
||||
end = "_iwasm_mem_alloc_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM platform",
|
||||
start = "_iwasm_platform_init_start",
|
||||
end = "_iwasm_platform_init_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM exec_env",
|
||||
start = "_iwasm_exec_env_start",
|
||||
end = "_iwasm_exec_env_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM interp",
|
||||
start = "_iwasm_interp_classic_start",
|
||||
end = "_iwasm_interp_classic_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM memory",
|
||||
start = "_iwasm_memory_start",
|
||||
end = "_iwasm_memory_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM native",
|
||||
start = "_iwasm_native_start",
|
||||
end = "_iwasm_native_end"
|
||||
),
|
||||
list(
|
||||
label = "IWASM runtime",
|
||||
start = "_iwasm_runtime_start",
|
||||
end = "_iwasm_runtime_end"
|
||||
),
|
||||
list(label = "TEXT", start = "_text_start", end = "_text_end"),
|
||||
list(label = "BSS", start = "_sbss", end = "_ebss")
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# HELPER
|
||||
# =============================================================================
|
||||
|
||||
# Count the number of unique row base-addresses
|
||||
# - %/% to sort to bins
|
||||
# - * to map to base address
|
||||
n_occupied_rows <- function(addr_ints, rw) {
|
||||
length(unique((addr_ints %/% rw) * rw))
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# CLI
|
||||
# =============================================================================
|
||||
|
||||
args <- commandArgs(trailingOnly = TRUE)
|
||||
if (length(args) < 1) {
|
||||
stop("Usage: Rscript single_heatmap.r <experiment_dir>")
|
||||
}
|
||||
|
||||
experiment <- args[1]
|
||||
faults_file <- if (length(args) >= 2) args[2] else "faults.csv"
|
||||
suffix <- gsub("^faults|\\.csv$", "", faults_file)
|
||||
|
||||
# =============================================================================
|
||||
# INPUT DATA (read once)
|
||||
# =============================================================================
|
||||
|
||||
datafile <- file.path(experiment, faults_file)
|
||||
if (!file.exists(datafile)) {
|
||||
stop(paste("Input file not found:", datafile))
|
||||
}
|
||||
|
||||
raw <- read_csv(
|
||||
datafile,
|
||||
col_types = cols(
|
||||
benchmark = col_character(),
|
||||
resulttype = col_character(),
|
||||
faults = col_double(),
|
||||
fault_address = col_character() # hex string "0x10001A"; converted below
|
||||
)
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# ELF SYMBOLS (parsed once)
|
||||
# =============================================================================
|
||||
|
||||
# Names vector: sym_addr["_text_start"] = 0x10001a
|
||||
sym_addr <- setNames(integer(0), character(0))
|
||||
|
||||
elf_file <- file.path(experiment, "system.elf")
|
||||
|
||||
if (!file.exists(elf_file)) {
|
||||
message("system.elf not found")
|
||||
} else {
|
||||
# Parse elf regions
|
||||
nm_lines <- tryCatch(
|
||||
system2("nm", args = elf_file, stdout = TRUE, stderr = FALSE),
|
||||
error = function(e) {
|
||||
message("nm failed (", conditionMessage(e), ")")
|
||||
NULL
|
||||
}
|
||||
)
|
||||
|
||||
if (!is.null(nm_lines) && length(nm_lines) > 0) {
|
||||
# Each nm line: "0010001a T _text_start"
|
||||
# Groups: 1 = hex address, 2 = symbol name
|
||||
pattern <- "^([0-9a-fA-F]+)\\s+\\S+\\s+(\\S+)"
|
||||
matches <- regmatches(nm_lines, regexec(pattern, nm_lines))
|
||||
valid <- Filter(function(m) length(m) == 3, matches)
|
||||
sym_addr <- setNames(
|
||||
strtoi(sapply(valid, `[[`, 2), 16L),
|
||||
sapply(valid, `[[`, 3)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# HEATMAP
|
||||
# =============================================================================
|
||||
|
||||
make_heatmap <- function(target_resulttype, target_benchmark) {
|
||||
# ===========================================================================
|
||||
# FILTER
|
||||
# ===========================================================================
|
||||
|
||||
filtered <- raw |>
|
||||
filter(
|
||||
.data$resulttype == target_resulttype,
|
||||
.data$benchmark == target_benchmark
|
||||
)
|
||||
|
||||
# Nothing to draw — skip without error
|
||||
if (nrow(filtered) == 0) {
|
||||
return(invisible(NULL))
|
||||
}
|
||||
|
||||
aggregated <- filtered |>
|
||||
select(fault_address, faults)
|
||||
|
||||
# ===========================================================================
|
||||
# ADDRESS HEX -> INT
|
||||
# ===========================================================================
|
||||
|
||||
# "0x10001A" -> substr strips "0x" -> strtoi parses base-16 -> integer
|
||||
aggregated <- aggregated |>
|
||||
mutate(
|
||||
addr_int = strtoi(
|
||||
substr(.data$fault_address, 3L, nchar(.data$fault_address)),
|
||||
16L
|
||||
)
|
||||
)
|
||||
|
||||
# ===========================================================================
|
||||
# SCALE ROWS
|
||||
# ===========================================================================
|
||||
|
||||
# Local copy so different combinations can scale independently.
|
||||
row_width <- row_width_init
|
||||
|
||||
# Double row_width until occupied rows <= max_rows
|
||||
while (
|
||||
row_width < 65536L &&
|
||||
n_occupied_rows(
|
||||
aggregated$addr_int,
|
||||
row_width
|
||||
) >
|
||||
max_rows
|
||||
) {
|
||||
row_width <- row_width * 2L
|
||||
}
|
||||
|
||||
if (row_width > row_width_init) {
|
||||
message(sprintf(
|
||||
"Note: [%s/%s] row_width auto-scaled to %d (%d occupied rows)",
|
||||
target_resulttype,
|
||||
target_benchmark,
|
||||
row_width,
|
||||
n_occupied_rows(aggregated$addr_int, row_width)
|
||||
))
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# GRID COORDINATES
|
||||
# ===========================================================================
|
||||
|
||||
# col = addr %% row_width -> byte offset within the row (0 ... row_width-1)
|
||||
# row = (addr %/% row_width) * row_width -> base address of the row
|
||||
grid_data <- aggregated |>
|
||||
mutate(
|
||||
col = .data$addr_int %% row_width,
|
||||
row = (.data$addr_int %/% row_width) * row_width
|
||||
)
|
||||
|
||||
# ===========================================================================
|
||||
# GAPS
|
||||
# ===========================================================================
|
||||
|
||||
rows_sorted <- sort(unique(grid_data$row))
|
||||
n_data_rows <- length(rows_sorted)
|
||||
|
||||
# - diff() returns the successive differences between consecutive elements
|
||||
# - has_gap_before[i] = TRUE when that distance > row_width
|
||||
# - First row never has a predecessor, so it's FALSE
|
||||
has_gap_before <- c(FALSE, diff(rows_sorted) > row_width)
|
||||
|
||||
# - cumsum(has_gap_before) counts how many gaps precede each row
|
||||
# - Adding that offset to 1...n gives the row_idx values with gap slots
|
||||
cumulative_gaps <- cumsum(has_gap_before)
|
||||
row_order <- tibble(
|
||||
row = rows_sorted,
|
||||
row_idx = seq_len(n_data_rows) + cumulative_gaps,
|
||||
has_gap_before = has_gap_before
|
||||
)
|
||||
|
||||
gap_marker_indices <- row_order$row_idx[has_gap_before] - 1L
|
||||
total_slots <- n_data_rows + sum(has_gap_before)
|
||||
|
||||
# ===========================================================================
|
||||
# FILL EMPTY CELLS
|
||||
# ===========================================================================
|
||||
|
||||
# - complete() adds a row for every missing (row, col) tuple
|
||||
# - left_join attaches row_idx to every cell
|
||||
grid_complete <- grid_data |>
|
||||
complete(row, col = 0L:(row_width - 1L)) |>
|
||||
left_join(row_order, by = "row")
|
||||
|
||||
# ===========================================================================
|
||||
# GAP TILES
|
||||
# ===========================================================================
|
||||
|
||||
gap_markers <- data.frame(row_idx = gap_marker_indices)
|
||||
|
||||
# ===========================================================================
|
||||
# ELF REGION RECTANGLES
|
||||
# ===========================================================================
|
||||
|
||||
region_rects <- data.frame(
|
||||
label = character(0),
|
||||
ymin = numeric(0),
|
||||
ymax = numeric(0)
|
||||
)
|
||||
|
||||
if (length(sym_addr) > 0) {
|
||||
rects_list <- lapply(regions, function(reg) {
|
||||
s <- sym_addr[reg$start]
|
||||
e <- sym_addr[reg$end]
|
||||
|
||||
if (is.na(s) || is.na(e) || s >= e) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
# Row with base address r covers bytes r ... r + row_width - 1.
|
||||
# Overlap if r < e && r + row_width > s
|
||||
overlapping <- row_order[
|
||||
row_order$row < e & (row_order$row + row_width) > s,
|
||||
,
|
||||
drop = FALSE
|
||||
]
|
||||
|
||||
if (nrow(overlapping) == 0) {
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
data.frame(
|
||||
label = reg$label,
|
||||
ymin = min(overlapping$row_idx) - 0.5,
|
||||
ymax = max(overlapping$row_idx) + 0.5
|
||||
)
|
||||
})
|
||||
|
||||
rects_list <- Filter(Negate(is.null), rects_list)
|
||||
if (length(rects_list) > 0) {
|
||||
region_rects <- do.call(rbind, rects_list)
|
||||
}
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# TILE SIZE
|
||||
# ===========================================================================
|
||||
|
||||
tile_size <- min(target_w / row_width, target_h / total_slots, max_tile)
|
||||
|
||||
# ===========================================================================
|
||||
# X-AXIS TICKS
|
||||
# ===========================================================================
|
||||
|
||||
# Minimum step to keep labels from overlapping at this tile size
|
||||
min_tick_step <- as.integer(ceiling(0.25 / tile_size))
|
||||
|
||||
# Snap to a power of 2 so labels stay round
|
||||
x_tick_step <- max(1L, row_width %/% n_x_ticks)
|
||||
x_tick_step <- 2L^as.integer(
|
||||
ceiling(log2(max(x_tick_step, min_tick_step, 1L)))
|
||||
)
|
||||
col_tick_values <- seq(0L, row_width - 1L, by = x_tick_step)
|
||||
col_tick_labels <- sprintf("+0x%X", col_tick_values)
|
||||
|
||||
# ===========================================================================
|
||||
# Y-AXIS TICKS
|
||||
# ===========================================================================
|
||||
|
||||
# Show 15 labels max (gaps are ignored)
|
||||
label_step <- max(1L, ceiling(n_data_rows / 15L))
|
||||
label_at <- row_order[seq(1L, n_data_rows, by = label_step), ]
|
||||
|
||||
# ===========================================================================
|
||||
# PLOT
|
||||
# ===========================================================================
|
||||
|
||||
plot <- ggplot(
|
||||
grid_complete,
|
||||
aes(
|
||||
x = col,
|
||||
y = .data$row_idx,
|
||||
fill = .data$faults
|
||||
)
|
||||
) +
|
||||
|
||||
# One rectangle per (col, row_idx) tuple
|
||||
geom_tile(width = 1, height = 1, colour = NA) +
|
||||
|
||||
# Separators at address gaps
|
||||
geom_rect(
|
||||
data = gap_markers,
|
||||
aes(ymin = .data$row_idx - 0.5, ymax = .data$row_idx + 0.5),
|
||||
xmin = -0.5,
|
||||
xmax = row_width - 0.5,
|
||||
fill = "grey40",
|
||||
colour = NA,
|
||||
inherit.aes = FALSE
|
||||
) +
|
||||
|
||||
# Heatmap color ramp
|
||||
scale_fill_viridis_c(
|
||||
name = "Faults",
|
||||
trans = "log1p",
|
||||
na.value = "grey85",
|
||||
option = "viridis"
|
||||
) +
|
||||
|
||||
# X-axis hex labels
|
||||
scale_x_continuous(
|
||||
breaks = col_tick_values,
|
||||
labels = col_tick_labels,
|
||||
limits = c(-0.5, row_width - 0.5),
|
||||
expand = c(0, 0)
|
||||
) +
|
||||
|
||||
# Y-axis hex labels, lowest address at the top
|
||||
scale_y_reverse(
|
||||
breaks = label_at$row_idx,
|
||||
labels = sprintf("0x%X", label_at$row),
|
||||
limits = c(total_slots + 0.5, 0.5), # includes gaps
|
||||
expand = c(0, 0)
|
||||
) +
|
||||
|
||||
# Title + axis labels
|
||||
labs(
|
||||
title = paste(target_resulttype, "/", target_benchmark),
|
||||
subtitle = paste(
|
||||
"Total:",
|
||||
format(
|
||||
sum(aggregated$faults, na.rm = TRUE),
|
||||
big.mark = ","
|
||||
)
|
||||
),
|
||||
x = "Byte Offset",
|
||||
y = "Base Address"
|
||||
) +
|
||||
|
||||
# Theme
|
||||
theme_minimal() +
|
||||
theme(
|
||||
axis.text.x = element_text(
|
||||
family = "mono",
|
||||
angle = 45,
|
||||
hjust = 1,
|
||||
size = 9
|
||||
),
|
||||
axis.text.y = element_text(family = "mono", size = 9),
|
||||
panel.grid = element_blank(),
|
||||
panel.border = element_rect(colour = "grey50", fill = NA, linewidth = 0.5)
|
||||
) +
|
||||
|
||||
# Force square tiles
|
||||
coord_fixed(ratio = 1)
|
||||
|
||||
# ELF region borders
|
||||
if (nrow(region_rects) > 0) {
|
||||
plot <- plot +
|
||||
geom_rect(
|
||||
data = region_rects,
|
||||
aes(ymin = .data$ymin, ymax = .data$ymax, colour = .data$label),
|
||||
xmin = -0.5,
|
||||
xmax = row_width - 0.5,
|
||||
fill = NA,
|
||||
linewidth = 1.5,
|
||||
inherit.aes = FALSE
|
||||
) +
|
||||
scale_colour_brewer(name = "Region", palette = "Dark2")
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# SAVE
|
||||
# ===========================================================================
|
||||
|
||||
fig_w <- row_width * tile_size + 4.5
|
||||
fig_h <- total_slots * tile_size + 2.5
|
||||
|
||||
outfile <- file.path(
|
||||
experiment,
|
||||
paste0(
|
||||
"heatmap_",
|
||||
target_resulttype,
|
||||
"_",
|
||||
target_benchmark,
|
||||
suffix,
|
||||
".svg"
|
||||
)
|
||||
)
|
||||
|
||||
ggsave(outfile, plot = plot, width = fig_w, height = fig_h, units = "in")
|
||||
message(sprintf("Saved: %s", basename(outfile)))
|
||||
invisible(NULL)
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# GENERATE HEATMAPS
|
||||
# =============================================================================
|
||||
|
||||
# Combinations with missing data are skipped
|
||||
for (bm in benchmarks) {
|
||||
for (marker in markers) {
|
||||
make_heatmap(marker, bm)
|
||||
}
|
||||
}
|
||||
28
scripts/charts/single_result.r
Normal file
28
scripts/charts/single_result.r
Normal file
@ -0,0 +1,28 @@
|
||||
library(ggplot2)
|
||||
|
||||
# Usage: Rscript single_result.r exp_abspath [resultsdata_file]
|
||||
|
||||
args <- commandArgs(trailingOnly = TRUE)
|
||||
experiment <- args[1]
|
||||
resultsdata_file <- if (length(args) >= 2) args[2] else "resultsdata.csv"
|
||||
suffix <- gsub("^resultsdata|\\.csv$", "", resultsdata_file)
|
||||
datafile <- file.path(experiment, resultsdata_file)
|
||||
|
||||
if (!file.exists(datafile)) {
|
||||
print(paste("Input file", datafile, "is missing"))
|
||||
stop()
|
||||
}
|
||||
|
||||
data <- readr::read_csv(datafile)
|
||||
tibble::glimpse(data)
|
||||
|
||||
plot <- ggplot(data, aes(x = benchmark, y = faults, fill = resulttype)) +
|
||||
geom_col(position = "dodge") +
|
||||
scale_y_log10() +
|
||||
labs(x = "Benchmark", y = "Faults", fill = "Result Type") +
|
||||
theme_minimal()
|
||||
|
||||
ggsave(
|
||||
paste0(experiment, "/single_result", suffix, ".svg"),
|
||||
plot = plot,
|
||||
)
|
||||
34
scripts/charts/single_scatter.r
Normal file
34
scripts/charts/single_scatter.r
Normal file
@ -0,0 +1,34 @@
|
||||
library(ggplot2)
|
||||
|
||||
# Usage: Rscript single_scatter.r exp_abspath
|
||||
|
||||
# TODO: Allow filtering resulttypes (or at least exclude OK_MARKER)
|
||||
|
||||
args <- commandArgs(trailingOnly = TRUE)
|
||||
experiment <- args[1]
|
||||
faults_file <- if (length(args) >= 2) args[2] else "faults.csv"
|
||||
suffix <- gsub("^faults|\\.csv$", "", faults_file)
|
||||
datafile <- file.path(experiment, faults_file)
|
||||
|
||||
if (!file.exists(datafile)) {
|
||||
print(paste("Input file", datafile, "is missing"))
|
||||
stop()
|
||||
}
|
||||
|
||||
data <- readr::read_csv(datafile)
|
||||
data$fault_address <- strtoi(data$fault_address)
|
||||
tibble::glimpse(data)
|
||||
|
||||
plot <- ggplot(data, aes(x = fault_address, y = faults)) +
|
||||
geom_point(aes(color = resulttype)) +
|
||||
scale_x_continuous(
|
||||
labels = function(x) sprintf("0x%X", as.integer(x))
|
||||
) +
|
||||
scale_y_log10() +
|
||||
labs(x = "Address", y = "Faults", color = "Type") +
|
||||
theme_minimal()
|
||||
|
||||
ggsave(
|
||||
paste0(experiment, "/scatter", suffix, ".svg"),
|
||||
plot = plot,
|
||||
)
|
||||
441
scripts/compile.pl
Normal file
441
scripts/compile.pl
Normal file
@ -0,0 +1,441 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use File::Copy qw(copy);
|
||||
use File::Path qw(rmtree make_path);
|
||||
use Cwd qw(abs_path);
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
use Util;
|
||||
|
||||
# ========================================================================================= #
|
||||
# Project root
|
||||
# ========================================================================================= #
|
||||
|
||||
my $root = abs_path("$FindBin::Bin/..");
|
||||
chdir($root) or die "Cannot chdir to $root: $!\n";
|
||||
|
||||
# ========================================================================================= #
|
||||
# Environment set by "nix develop"
|
||||
# ========================================================================================= #
|
||||
|
||||
sub require_env {
|
||||
my ($name) = @_;
|
||||
return $ENV{$name}
|
||||
// die "$name is not set (run from 'nix develop' shell)\n";
|
||||
}
|
||||
|
||||
my $wasi_root = require_env('WASI_ROOT');
|
||||
my $wamr_root = require_env('WAMR_ROOT');
|
||||
my $cross_cc = require_env('CROSS_CC');
|
||||
my $linux_cc = require_env('LINUX_CC');
|
||||
|
||||
my $use_aot_in_text = ( $ENV{WAMR_USE_AOT_IN_TEXT} // 'false' ) eq 'true';
|
||||
my $use_mmap_in_text = ( $ENV{WAMR_USE_MMAP_IN_TEXT} // 'false' ) eq 'true';
|
||||
my $use_xip = ( $ENV{WAMR_USE_XIP} // 'false' ) eq 'true';
|
||||
my $use_allocator = ( $ENV{WAMR_USE_ALLOCATOR} // 'false' ) eq 'true';
|
||||
my $use_global_heap_in_text =
|
||||
( $ENV{WAMR_USE_GLOBAL_HEAP_IN_TEXT} // 'false' ) eq 'true';
|
||||
my $use_runtime_pool_in_text =
|
||||
( $ENV{WAMR_USE_RUNTIME_POOL_IN_TEXT} // 'false' ) eq 'true';
|
||||
my $use_linear_pool_in_text =
|
||||
( $ENV{WAMR_USE_LINEAR_POOL_IN_TEXT} // 'false' ) eq 'true';
|
||||
|
||||
# ========================================================================================= #
|
||||
# WAMR cmake configuration
|
||||
# ========================================================================================= #
|
||||
|
||||
# Flags common to all platforms
|
||||
my @wamr_cmake_base = (
|
||||
'-DCMAKE_BUILD_TYPE=Debug', '-DWAMR_BUILD_TARGET=X86_32',
|
||||
'-DWAMR_BUILD_AOT=1', '-DWAMR_BUILD_WAMR_COMPILER=0',
|
||||
'-DWAMR_BUILD_INTERP=1', '-DWAMR_BUILD_FAST_INTERP=0',
|
||||
'-DWAMR_BUILD_JIT=0', '-DWAMR_BUILD_FAST_JIT=0',
|
||||
'-DWAMR_BUILD_LIBC_BUILTIN=1', '-DWAMR_BUILD_LIBC_WASI=0',
|
||||
'-DWAMR_BUILD_SIMD=0',
|
||||
);
|
||||
|
||||
my @wamr_cmake_baremetal = (
|
||||
'-DWAMR_BUILD_PLATFORM=baremetal',
|
||||
'-DCMAKE_SYSTEM_NAME=Generic',
|
||||
'-DCMAKE_SYSTEM_PROCESSOR=i386',
|
||||
'-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY',
|
||||
);
|
||||
|
||||
my @wamr_cmake_linux = ( '-DWAMR_BUILD_PLATFORM=linux', );
|
||||
|
||||
# Variant defines passed as CMAKE_C_FLAGS
|
||||
my @variant_cflags =
|
||||
( '-Wno-error=implicit-function-declaration', '-O0', '-ggdb3' );
|
||||
push @variant_cflags,
|
||||
$use_mmap_in_text ? '-DWAMR_MMAP_IN_TEXT=1' : '-DWAMR_MMAP_IN_TEXT=0';
|
||||
push @variant_cflags, '-DWASM_MEM_ALLOC_WITH_USAGE=1' if $use_allocator;
|
||||
my $cmake_c_flags = join( ' ', @variant_cflags );
|
||||
|
||||
# Variant options passed as cmake variables
|
||||
my @variant_cmake_flags;
|
||||
push @variant_cmake_flags, '-DWAMR_BUILD_ALLOC_WITH_USAGE=1' if $use_allocator;
|
||||
|
||||
# Defines forwarded to the host compilation so wasm_host.c sees the same
|
||||
# WASM_MEM_ALLOC_WITH_USAGE value as libiwasm.a was built with.
|
||||
my @host_variant_cflags;
|
||||
push @host_variant_cflags, '-DWASM_MEM_ALLOC_WITH_USAGE=1' if $use_allocator;
|
||||
push @host_variant_cflags,
|
||||
$use_global_heap_in_text
|
||||
? '-DWAMR_GLOBAL_HEAP_IN_TEXT=1'
|
||||
: '-DWAMR_GLOBAL_HEAP_IN_TEXT=0';
|
||||
push @host_variant_cflags,
|
||||
$use_runtime_pool_in_text
|
||||
? '-DWAMR_RUNTIME_POOL_IN_TEXT=1'
|
||||
: '-DWAMR_RUNTIME_POOL_IN_TEXT=0';
|
||||
push @host_variant_cflags,
|
||||
$use_linear_pool_in_text
|
||||
? '-DWAMR_LINEAR_POOL_IN_TEXT=1'
|
||||
: '-DWAMR_LINEAR_POOL_IN_TEXT=0';
|
||||
|
||||
# ========================================================================================= #
|
||||
# Compiler / linker flags
|
||||
# ========================================================================================= #
|
||||
|
||||
my @wasi_cflags = (
|
||||
'--target=wasm32', "--sysroot=$wasi_root/share/wasi-sysroot",
|
||||
'-z', 'stack-size=4096',
|
||||
'-O0', '-nostdlib',
|
||||
'-Wl,--no-entry', '-Wl,--export=wasm_module',
|
||||
'-Wl,--no-gc-sections', '-Wl,--initial-memory=65536',
|
||||
'-Wl,--export=__heap_base', '-Wl,--export=__data_end',
|
||||
);
|
||||
|
||||
my @cross_cflags =
|
||||
qw(-O0 -m32 -ffunction-sections -fdata-sections -ffreestanding -fpermissive -ggdb3);
|
||||
my @linux_cflags =
|
||||
qw(-O0 -m32 -ffunction-sections -fdata-sections -fpermissive -ggdb3);
|
||||
my @linux_baremetal_cflags =
|
||||
qw(-O0 -m32 -ffunction-sections -fdata-sections -ffreestanding -ggdb3);
|
||||
|
||||
# libiwasm.a is passed as a direct file path (no -L/-liwasm)
|
||||
my @cross_ldflags_base = (
|
||||
'-Wl,--build-id=none', '-static', '-nostdlib', '-m32',
|
||||
'-lc', '-lgcc', '-lm'
|
||||
);
|
||||
my @linux_ldflags_base = ( '-Wl,--build-id=none', '-m32', '-lm' );
|
||||
my @baremetal_ldflags_base = (
|
||||
'-Wl,--build-id=none', '-static', '-nostdlib', '-m32',
|
||||
'-lc', '-lgcc', '-lm', '--entry',
|
||||
'main'
|
||||
);
|
||||
my @cross_ldflags_nowasm = (
|
||||
'-Wl,--build-id=none', '-static', '-nostdlib', '-m32',
|
||||
'-lc', '-lgcc', '-lm'
|
||||
);
|
||||
my @linux_ldflags_nowasm = ( '-Wl,--build-id=none', '-m32', '-lm' );
|
||||
|
||||
my @wamr_inc_baremetal = (
|
||||
"-I$wamr_root/core/iwasm/include",
|
||||
"-I$wamr_root/core/shared/utils",
|
||||
"-I$wamr_root/core/shared/platform/baremetal",
|
||||
);
|
||||
my @wamr_inc_linux = (
|
||||
"-I$wamr_root/core/iwasm/include",
|
||||
"-I$wamr_root/core/shared/utils",
|
||||
"-I$wamr_root/core/shared/platform/linux",
|
||||
);
|
||||
|
||||
my @cross_wamrcflags = ( '--target=i386', '--cpu=generic', '--opt-level=0' );
|
||||
push @cross_wamrcflags, '--xip' if $use_xip;
|
||||
my @linux_wamrcflags = ( '--target=i386', '--cpu=generic', '--opt-level=0' );
|
||||
|
||||
# ========================================================================================= #
|
||||
# Entry point
|
||||
# ========================================================================================= #
|
||||
|
||||
die "Usage: compile.pl <module> <target> <mode>\n"
|
||||
. " target: fail | linux | linux-baremetal\n"
|
||||
. " mode: aot | interp | c\n"
|
||||
unless @ARGV == 3;
|
||||
|
||||
my ( $module, $target, $mode ) = @ARGV;
|
||||
|
||||
build( $module, $target, $mode );
|
||||
|
||||
# ========================================================================================= #
|
||||
# Build
|
||||
# ========================================================================================= #
|
||||
|
||||
sub build {
|
||||
my ( $module, $target, $mode ) = @_;
|
||||
my $bd = "build-$module";
|
||||
|
||||
rmtree($bd);
|
||||
make_path($bd);
|
||||
copy_auxiliary( $module, $bd );
|
||||
|
||||
if ( $mode eq 'aot' || $mode eq 'interp' ) {
|
||||
build_libiwasm( $module, $bd, $target );
|
||||
compile_wasm_module( $module, $bd );
|
||||
if ( $mode eq 'aot' ) {
|
||||
compile_wasm_aot( $module, $bd, $target );
|
||||
make_aot_array( $module, $bd );
|
||||
}
|
||||
else {
|
||||
make_interp_array( $module, $bd );
|
||||
}
|
||||
prepare_wasm_host( $module, $bd, $mode );
|
||||
compile_wasm_host( $module, $bd, $target );
|
||||
compile_startup( $module, $bd, $target );
|
||||
compile_syscalls( $module, $bd, $target );
|
||||
link_wasm( $module, $bd, $target );
|
||||
}
|
||||
elsif ( $mode eq 'c' ) {
|
||||
compile_c_module( $module, $bd, $target );
|
||||
compile_c_host( $module, $bd, $target );
|
||||
compile_startup( $module, $bd, $target );
|
||||
link_c( $module, $bd, $target );
|
||||
}
|
||||
else {
|
||||
die "Unknown mode '$mode'; expected: aot, interp, c\n";
|
||||
}
|
||||
|
||||
build_iso( $module, $bd );
|
||||
}
|
||||
|
||||
# ========================================================================================= #
|
||||
# Steps
|
||||
# ========================================================================================= #
|
||||
|
||||
sub build_libiwasm {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
my $cmake_bd = "$bd/wamr-build";
|
||||
make_path($cmake_bd);
|
||||
|
||||
my ( $cmake_cc, @sys_flags ) =
|
||||
( $target eq 'linux' )
|
||||
? ( $linux_cc, @wamr_cmake_linux )
|
||||
: ( $cross_cc, @wamr_cmake_baremetal );
|
||||
|
||||
Util::run(
|
||||
'cmake', '-S',
|
||||
$wamr_root, '-B',
|
||||
$cmake_bd, "-DCMAKE_C_COMPILER=$cmake_cc",
|
||||
@wamr_cmake_base, @sys_flags,
|
||||
@variant_cmake_flags, "-DCMAKE_C_FLAGS=$cmake_c_flags",
|
||||
);
|
||||
Util::run( 'cmake', '--build', $cmake_bd );
|
||||
copy( "$cmake_bd/libiwasm.a", "$bd/libiwasm.a" )
|
||||
or die "failed to copy $cmake_bd/libiwasm.a: $!";
|
||||
rmtree($cmake_bd) or die "failed to remove $cmake_bd: $!";
|
||||
}
|
||||
|
||||
sub copy_auxiliary {
|
||||
my ( $module, $bd ) = @_;
|
||||
my @files = (
|
||||
[ 'flake.nix', "$bd/flake.nix" ],
|
||||
[ 'scripts/runner.pl', "$bd/runner.pl" ],
|
||||
[ 'scripts/compile.pl', "$bd/compile.pl" ],
|
||||
[ 'targets/lib.h', "$bd/lib.h" ],
|
||||
[ 'targets/linker.ld', "$bd/linker.ld" ],
|
||||
[ 'targets/startup.s', "$bd/startup.s" ],
|
||||
[ 'targets/syscalls.c', "$bd/syscalls.c" ],
|
||||
[ "targets/wasm-module/$module.cpp", "$bd/wasm-module.cpp" ],
|
||||
);
|
||||
for my $pair (@files) {
|
||||
copy( $pair->[0], $pair->[1] )
|
||||
or die "failed to copy $pair->[0] -> $pair->[1]: $!";
|
||||
}
|
||||
}
|
||||
|
||||
sub compile_wasm_module {
|
||||
my ( $module, $bd ) = @_;
|
||||
Util::run( "$wasi_root/bin/clang", @wasi_cflags,
|
||||
"targets/wasm-module/$module.cpp",
|
||||
'-o', "$bd/wasm_module.wasm" );
|
||||
}
|
||||
|
||||
sub compile_wasm_aot {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
my @flags = ( $target eq 'linux' ) ? @linux_wamrcflags : @cross_wamrcflags;
|
||||
Util::run( 'wamrc', @flags, '-o', "$bd/wasm_module.aot",
|
||||
"$bd/wasm_module.wasm" );
|
||||
}
|
||||
|
||||
sub make_aot_array {
|
||||
my ( $module, $bd ) = @_;
|
||||
open( my $xxd, '-|', 'xxd', '-i', "$bd/wasm_module.aot" )
|
||||
or die "failed to run xxd: $!";
|
||||
my $content = do { local $/; <$xxd> };
|
||||
close($xxd);
|
||||
|
||||
$content =
|
||||
qq{__attribute__((section(".text.wamr_aot"), aligned(4096)))\n}
|
||||
. $content
|
||||
if $use_aot_in_text;
|
||||
|
||||
Util::write_file( "$bd/wasm_aot_array.c", $content );
|
||||
}
|
||||
|
||||
sub make_interp_array {
|
||||
my ( $module, $bd ) = @_;
|
||||
open( my $xxd, '-|', 'xxd', '-i', "$bd/wasm_module.wasm" )
|
||||
or die "Cannot run xxd: $!\n";
|
||||
my $content = do { local $/; <$xxd> };
|
||||
close($xxd);
|
||||
Util::write_file( "$bd/wasm_interp_array.c", $content );
|
||||
}
|
||||
|
||||
sub prepare_wasm_host {
|
||||
my ( $module, $bd, $mode ) = @_;
|
||||
my $template = 'targets/wasm-host/wasm_host.c';
|
||||
|
||||
my $mod_c = ( $module =~ s/-/_/gr );
|
||||
my ( $array_file, $array_sym, $len_sym ) =
|
||||
( $mode eq 'aot' )
|
||||
? (
|
||||
'wasm_aot_array.c',
|
||||
"build_${mod_c}_wasm_module_aot",
|
||||
"build_${mod_c}_wasm_module_aot_len"
|
||||
)
|
||||
: (
|
||||
'wasm_interp_array.c',
|
||||
"build_${mod_c}_wasm_module_wasm",
|
||||
"build_${mod_c}_wasm_module_wasm_len"
|
||||
);
|
||||
|
||||
my $content = Util::read_file($template);
|
||||
$content =~ s/__WASM_ARRAY_FILE__/$array_file/g;
|
||||
$content =~ s/__WASM_ARRAY__/$array_sym/g;
|
||||
$content =~ s/__WASM_ARRAY_LEN__/$len_sym/g;
|
||||
Util::write_file( "$bd/module_host.c", $content );
|
||||
}
|
||||
|
||||
sub compile_wasm_host {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
if ( $target eq 'fail' ) {
|
||||
Util::run(
|
||||
$cross_cc, '-I./targets/wasm-host',
|
||||
@cross_cflags, @host_variant_cflags,
|
||||
@wamr_inc_baremetal, '-DTARGET_FAIL',
|
||||
'-c', "$bd/module_host.c",
|
||||
'-o', "$bd/system.o"
|
||||
);
|
||||
}
|
||||
elsif ( $target eq 'linux' ) {
|
||||
Util::run(
|
||||
$linux_cc, '-I./targets/wasm-host',
|
||||
@linux_cflags, @host_variant_cflags,
|
||||
@wamr_inc_linux, '-DTARGET_LINUX',
|
||||
'-c', "$bd/module_host.c",
|
||||
'-o', "$bd/system.o"
|
||||
);
|
||||
}
|
||||
elsif ( $target eq 'linux-baremetal' ) {
|
||||
Util::run(
|
||||
$cross_cc, '-I./targets/wasm-host',
|
||||
@linux_baremetal_cflags, @host_variant_cflags,
|
||||
@wamr_inc_baremetal, '-DTARGET_LINUX_BAREMETAL',
|
||||
'-c', "$bd/module_host.c",
|
||||
'-o', "$bd/system.o"
|
||||
);
|
||||
}
|
||||
else {
|
||||
die "Unknown target '$target'\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub compile_c_module {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
my ( $cc, @flags ) =
|
||||
( $target eq 'linux' )
|
||||
? ( $linux_cc, @linux_cflags )
|
||||
: ( $cross_cc, @cross_cflags );
|
||||
Util::run( $cc, @flags, '-c', "targets/wasm-module/$module.cpp",
|
||||
'-o', "$bd/c_module.o" );
|
||||
}
|
||||
|
||||
sub compile_c_host {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
my ( $cc, @flags ) =
|
||||
( $target eq 'linux' )
|
||||
? ( $linux_cc, @linux_cflags, '-DTARGET_LINUX' )
|
||||
: ( $cross_cc, @cross_cflags, '-DTARGET_FAIL' );
|
||||
Util::run( $cc, @flags, '-c', 'targets/c-host/c_host.c', '-o',
|
||||
"$bd/c_host.o" );
|
||||
copy( 'targets/c-host/c_host.c', "$bd/module_host.c" );
|
||||
}
|
||||
|
||||
sub compile_startup {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
return unless $target eq 'fail';
|
||||
Util::run( $cross_cc, 'targets/startup.s', '-I./targets/wasm-host',
|
||||
@cross_cflags, '-c', '-o', "$bd/startup.o" );
|
||||
}
|
||||
|
||||
sub compile_syscalls {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
if ( $target eq 'fail' ) {
|
||||
Util::run( $cross_cc, 'targets/syscalls.c',
|
||||
'-I./targets/wasm-host', @cross_cflags,
|
||||
'-c', '-o', "$bd/syscalls.o" );
|
||||
}
|
||||
elsif ( $target eq 'linux-baremetal' ) {
|
||||
Util::run( $cross_cc, 'targets/syscalls.c', @linux_baremetal_cflags,
|
||||
'-c', '-o', "$bd/syscalls.o" );
|
||||
}
|
||||
|
||||
# Linux needs neither startup nor syscall stubs
|
||||
}
|
||||
|
||||
sub link_wasm {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
if ( $target eq 'fail' ) {
|
||||
Util::run(
|
||||
$cross_cc, '-Wl,-T',
|
||||
'targets/linker.ld', "$bd/system.o",
|
||||
"$bd/startup.o", "$bd/syscalls.o",
|
||||
"$bd/libiwasm.a", @cross_ldflags_base,
|
||||
'-o', "$bd/system.elf"
|
||||
);
|
||||
}
|
||||
elsif ( $target eq 'linux' ) {
|
||||
Util::run( $linux_cc, "$bd/system.o", "$bd/libiwasm.a",
|
||||
@linux_ldflags_base, '-o', "$bd/system.elf" );
|
||||
}
|
||||
elsif ( $target eq 'linux-baremetal' ) {
|
||||
Util::run( $cross_cc, "$bd/system.o", "$bd/syscalls.o",
|
||||
"$bd/libiwasm.a", @baremetal_ldflags_base, '-o', "$bd/system.elf" );
|
||||
}
|
||||
else {
|
||||
die "Unknown target '$target'\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub link_c {
|
||||
my ( $module, $bd, $target ) = @_;
|
||||
if ( $target eq 'fail' ) {
|
||||
Util::run(
|
||||
$cross_cc, '-Wl,-T',
|
||||
'targets/linker.ld', "$bd/c_host.o",
|
||||
"$bd/startup.o", "$bd/c_module.o",
|
||||
@cross_ldflags_nowasm, '-o',
|
||||
"$bd/system.elf"
|
||||
);
|
||||
}
|
||||
elsif ( $target eq 'linux' ) {
|
||||
Util::run( $linux_cc, "$bd/c_host.o", "$bd/c_module.o",
|
||||
@linux_ldflags_nowasm, '-o', "$bd/system.elf" );
|
||||
}
|
||||
else {
|
||||
die "C mode is not supported for target '$target'\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub build_iso {
|
||||
my ( $module, $bd ) = @_;
|
||||
make_path("$bd/grub/boot/grub");
|
||||
copy( 'targets/grub.cfg', "$bd/grub/boot/grub/grub.cfg" )
|
||||
or die "failed to copy grub.cfg: $!\n";
|
||||
copy( "$bd/system.elf", "$bd/grub/boot/system.elf" )
|
||||
or die "failed to copy system.elf: $!\n";
|
||||
Util::run( 'grub-mkrescue', '-o', "$bd/system.iso", "$bd/grub" );
|
||||
}
|
||||
49
scripts/deploy.pl
Executable file
49
scripts/deploy.pl
Executable file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
|
||||
use Util;
|
||||
use Mars;
|
||||
use TUI;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_builds_dir = "$local_root/builds";
|
||||
|
||||
my $remote_root = '/home/lab/smchurla/Documents/failnix';
|
||||
my $remote_builds_dir = "$remote_root/builds";
|
||||
my $remote_runner = "$remote_root/scripts/multi_runner.pl";
|
||||
my $remote_log = "$remote_root/multi_runner.log";
|
||||
|
||||
# Upload new experiments
|
||||
my @experiments = grep { /fail/ } Util::find_subdirs($local_builds_dir);
|
||||
my @selected_experiments =
|
||||
TUI::select_from_list( "Select Experiments to Run", 1, @experiments );
|
||||
die "No experiment selected" unless @selected_experiments;
|
||||
Mars::ssh_system( 'mkdir', '-p', $remote_builds_dir );
|
||||
Mars::upload_dir( "$local_builds_dir/$_", "$remote_builds_dir/$_" )
|
||||
for @selected_experiments;
|
||||
|
||||
# Create dbs for new experiments
|
||||
say 'Existing databases:';
|
||||
say " - $_" for Mars::db_list();
|
||||
say 'Creating databases...';
|
||||
Mars::db_create( Mars::db_prefix . "_$_" ) for @selected_experiments;
|
||||
|
||||
# Launch remote runner
|
||||
Mars::ssh_system(
|
||||
join " ",
|
||||
(
|
||||
"nohup sh -c",
|
||||
Util::shell_quote("cd $remote_root && perl $remote_runner"),
|
||||
">" . Util::shell_quote($remote_log),
|
||||
"2>&1 < /dev/null &"
|
||||
)
|
||||
);
|
||||
say "Started remote runner for ", scalar(@experiments), " experiments";
|
||||
718
scripts/explore.pl
Normal file
718
scripts/explore.pl
Normal file
@ -0,0 +1,718 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
|
||||
use Util;
|
||||
use Mars;
|
||||
use TUI;
|
||||
use Text::CSV_XS;
|
||||
use File::Temp qw(tempfile);
|
||||
|
||||
use feature 'say';
|
||||
|
||||
my $local_wamr = '/home/christoph/Notes/TU/MastersThesis/05 WAMR';
|
||||
my $local_newlib = '/home/christoph/Notes/TU/MastersThesis/07 NewLib';
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_archive_dir = "$local_root/injections";
|
||||
|
||||
# Select experiment to open
|
||||
my $selected_experiment = Util::select_experiment(0);
|
||||
|
||||
my $selected_faults_csv =
|
||||
Util::pick_data_file( "$local_archive_dir/$selected_experiment", "faults" );
|
||||
|
||||
my $cui = TUI::init_cui();
|
||||
|
||||
# TODO: Add a TextEditor panel beside the experiment selection for notes.
|
||||
# Store notes in experiment/notes/description.txt
|
||||
# TODO: Add a TextEditor panel below the markers for notes.
|
||||
# Store notes in experiment/notes/benchmark-type-address.txt
|
||||
# TODO: Add a more exhaustive faults query that also retrieves
|
||||
# what fault has been injected. Then add an info popup or
|
||||
# display it in the markers panel
|
||||
# TODO: Add a filter for address ranges
|
||||
# TODO: Add a filter for segments
|
||||
|
||||
# =============================================================================
|
||||
# Data handling
|
||||
# =============================================================================
|
||||
|
||||
my @marker_values;
|
||||
my %marker_labels;
|
||||
my @filtered_marker_values;
|
||||
|
||||
my $assembly_text;
|
||||
|
||||
my $source_file;
|
||||
my $source_line;
|
||||
my $source_text;
|
||||
|
||||
my @benchs = ( "ip", "mem", "regs" );
|
||||
my @markers = (
|
||||
"OK_MARKER", "DETECTED_MARKER",
|
||||
"FAIL_MARKER", "TRAP",
|
||||
"TIMEOUT", "ACCESS_OUTERSPACE",
|
||||
"WRITE_TEXTSEGMENT", "GROUP1_MARKER",
|
||||
);
|
||||
|
||||
# Filter popup state
|
||||
my $popup_focus = "left";
|
||||
|
||||
my @selected_benchs = @benchs;
|
||||
my %index_of_benchs;
|
||||
@index_of_benchs{@benchs} = 0 .. $#benchs;
|
||||
|
||||
my @selected_markers = ("FAIL_MARKER");
|
||||
my %index_of_markers;
|
||||
@index_of_markers{@markers} = 0 .. $#markers;
|
||||
|
||||
my $selected_threshold = 0;
|
||||
|
||||
my @sections;
|
||||
|
||||
sub marker_label {
|
||||
my ($marker) = @_;
|
||||
|
||||
return sprintf(
|
||||
"%4s %8s %5s %17s %12sx %-40s",
|
||||
$marker->{benchmark},
|
||||
$marker->{fault_address},
|
||||
Util::get_section_name( $marker->{fault_address}, @sections ),
|
||||
$marker->{resulttype},
|
||||
Util::format_number_sep( $marker->{faults} ),
|
||||
Util::read_marker_info(
|
||||
$selected_experiment, $marker->{benchmark},
|
||||
$marker->{fault_address}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
sub load_faults_csv {
|
||||
@marker_values = ();
|
||||
%marker_labels = ();
|
||||
|
||||
# Schema: benchmark, resulttype, faults, fault_address
|
||||
my $data = Text::CSV_XS::csv(
|
||||
in => "$local_archive_dir/$selected_experiment/$selected_faults_csv",
|
||||
headers => 'auto'
|
||||
);
|
||||
|
||||
@sections = Util::elf_read_sections(
|
||||
"$local_archive_dir/$selected_experiment/system.elf");
|
||||
|
||||
# Result:
|
||||
# [ { benchmark => "ip", resulttype => "OK_MARKER",
|
||||
# faults => "100", fault_address => "0x100074" },
|
||||
# ... ]
|
||||
@marker_values = @$data;
|
||||
@filtered_marker_values = @marker_values;
|
||||
%marker_labels =
|
||||
map { $_ => marker_label($_); } @marker_values;
|
||||
}
|
||||
|
||||
sub filter_marker_values {
|
||||
|
||||
sub is_allowed {
|
||||
my ($marker) = @_;
|
||||
|
||||
my $bench = $marker->{benchmark};
|
||||
my $type = $marker->{resulttype};
|
||||
my $count = int( $marker->{faults} );
|
||||
|
||||
return ( grep { /^$bench$/ } @selected_benchs
|
||||
and grep { /^$type$/ } @selected_markers
|
||||
and $count > $selected_threshold );
|
||||
}
|
||||
|
||||
@filtered_marker_values = grep { is_allowed($_) } @marker_values;
|
||||
}
|
||||
|
||||
# How much to disassemble around the address / how many lines to show
|
||||
my $region_size = $cui->height() / 2 - 2;
|
||||
my $asm_region_size = $region_size + 120;
|
||||
|
||||
my %assembly_cache;
|
||||
|
||||
sub align_region {
|
||||
my ( $assembly_region, $objdump_address ) = @_;
|
||||
|
||||
my @region;
|
||||
my @lines = split "\n", $assembly_region;
|
||||
my $center;
|
||||
for my $i ( 1 .. $#lines ) {
|
||||
my $line = $lines[ $i - 1 ];
|
||||
chomp $line;
|
||||
|
||||
# Mark the center line
|
||||
if ( grep { /^\s*$objdump_address/ } $line ) {
|
||||
push @region, sprintf( ">> %s", $line );
|
||||
$center = $i;
|
||||
}
|
||||
else {
|
||||
push @region, sprintf( " %s", $line );
|
||||
}
|
||||
}
|
||||
|
||||
if ( defined $center ) {
|
||||
my $offset = $center - $region_size;
|
||||
if ( $offset > 0 ) {
|
||||
|
||||
# Remove lines ($center > $region_size)
|
||||
@region = @region[ $offset .. $#region ];
|
||||
}
|
||||
elsif ( $offset < 0 ) {
|
||||
|
||||
# Add lines
|
||||
for ( 1 .. abs($offset) + 1 ) {
|
||||
unshift @region, "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return join "\n", @region;
|
||||
}
|
||||
|
||||
sub load_assembly_elf {
|
||||
my ($marker) = @_;
|
||||
|
||||
return unless defined $marker;
|
||||
|
||||
my $address = hex( $marker->{fault_address} );
|
||||
|
||||
if ( !exists $assembly_cache{$address} ) {
|
||||
my $file = "$local_archive_dir/$selected_experiment/system.elf";
|
||||
my $start = $address - $asm_region_size;
|
||||
my $end = $address + $asm_region_size;
|
||||
|
||||
my $objdump_address = lc substr( $marker->{fault_address}, 2 );
|
||||
|
||||
my $assembly_region =
|
||||
qx{objdump $file -D -M intel -C --start-address=$start --stop-address=$end}
|
||||
=~ s/.*\n.*\n.*\n.*\n.*\n.*\n//r;
|
||||
|
||||
$assembly_cache{$address} =
|
||||
align_region( $assembly_region, $objdump_address );
|
||||
}
|
||||
|
||||
$assembly_text = $assembly_cache{$address};
|
||||
}
|
||||
|
||||
my %remappings = (
|
||||
"/build/source/core" => "$local_wamr/core",
|
||||
"/build/newlib-.*/newlib" => "$local_newlib/newlib",
|
||||
".*/module_host.c" =>
|
||||
"$local_archive_dir/$selected_experiment/module_host.c",
|
||||
);
|
||||
|
||||
sub remap_source_path {
|
||||
my ($path) = @_;
|
||||
|
||||
foreach my $source ( keys %remappings ) {
|
||||
my $target = $remappings{$source};
|
||||
$path =~ s/$source/$target/;
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
sub read_source_file {
|
||||
my ( $sourcefile, $lineno ) = @_;
|
||||
|
||||
return unless ( -f $sourcefile );
|
||||
|
||||
open( my $fhandle, '<', $sourcefile ) or return;
|
||||
|
||||
my @lines = <$fhandle>;
|
||||
close($fhandle);
|
||||
|
||||
my $start = int($lineno) - $region_size;
|
||||
$start = 1 if $start < 1;
|
||||
my $end = int($lineno) + $region_size;
|
||||
$end = scalar(@lines) if $end > scalar(@lines);
|
||||
|
||||
my @region;
|
||||
for my $i ( $start .. $end ) {
|
||||
my $line = $lines[ $i - 1 ];
|
||||
chomp $line;
|
||||
|
||||
# Mark the center line
|
||||
if ( $i == $lineno ) {
|
||||
push @region, sprintf( ">> %6d | %s", $i, $line );
|
||||
}
|
||||
else {
|
||||
push @region, sprintf( " %6d | %s", $i, $line );
|
||||
}
|
||||
}
|
||||
|
||||
return join( "\n", @region );
|
||||
}
|
||||
|
||||
my %source_cache;
|
||||
my %source_file_cache;
|
||||
my %source_line_cache;
|
||||
|
||||
sub load_source_c {
|
||||
my ($marker) = @_;
|
||||
|
||||
return unless defined $marker;
|
||||
|
||||
my $address = $marker->{fault_address};
|
||||
|
||||
if ( !exists $source_cache{$address} ) {
|
||||
my $elffile = "$local_archive_dir/$selected_experiment/system.elf";
|
||||
my $host_file = "$local_archive_dir/$selected_experiment/module_host.c";
|
||||
my $module_file =
|
||||
"$local_archive_dir/$selected_experiment/wasm-module.cpp";
|
||||
|
||||
# Example:
|
||||
# wasm_interp_call_func_bytecode
|
||||
# /build/source/core/iwasm/interpreter/wasm_interp_classic.c:1685
|
||||
my $location = qx{addr2line -e $elffile -f -C -i $address};
|
||||
my @lines = split( "\n", $location );
|
||||
if ( scalar(@lines) < 2 ) {
|
||||
$source_text = "Addr2Line Error\n";
|
||||
return;
|
||||
}
|
||||
|
||||
my $line = $lines[1]; # Ignore possible further lines
|
||||
my ( $sourcefile, $lineno ) = split ":", $line;
|
||||
($lineno) = $lineno =~ /^(\d+)/;
|
||||
my $remapped = remap_source_path($sourcefile);
|
||||
|
||||
my $source_region = read_source_file( $remapped, $lineno );
|
||||
if ( !defined $source_region or length($source_region) == 0 ) {
|
||||
$source_text = "Failed to Read Source: $location";
|
||||
$source_file = "Unknown";
|
||||
$source_line = "Unknown";
|
||||
return;
|
||||
}
|
||||
|
||||
$source_cache{$address} = $source_region;
|
||||
$source_file_cache{$address} = $remapped;
|
||||
$source_line_cache{$address} = $lineno;
|
||||
}
|
||||
|
||||
$source_text = $source_cache{$address};
|
||||
$source_file = $source_file_cache{$address};
|
||||
$source_line = $source_line_cache{$address};
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# UI Layout
|
||||
# =============================================================================
|
||||
|
||||
my $win = $cui->add( 'explorer', 'Window' );
|
||||
|
||||
my $left = $win->add( 'left', 'Container' ); # , -padbottom => 1,
|
||||
my $middle = $win->add( 'middle', 'Container' ); # , -padbottom => 1,
|
||||
my $right = $win->add( 'right', 'Container' ); # , -padbottom => 1,
|
||||
|
||||
my $markers_panel;
|
||||
my $assembly_panel;
|
||||
my $source_panel;
|
||||
|
||||
my $refresh_panels = sub {
|
||||
load_assembly_elf( $markers_panel->get_active_value() );
|
||||
load_source_c( $markers_panel->get_active_value() );
|
||||
|
||||
$assembly_panel->text($assembly_text);
|
||||
$source_panel->text($source_text);
|
||||
|
||||
$source_panel->title("Source View: $source_file");
|
||||
|
||||
$assembly_panel->draw();
|
||||
$source_panel->draw();
|
||||
};
|
||||
|
||||
$markers_panel = $left->add(
|
||||
'markers_list',
|
||||
'Listbox',
|
||||
-title => "Markers",
|
||||
-border => 1,
|
||||
-values => \@filtered_marker_values,
|
||||
-labels => \%marker_labels,
|
||||
-multi => 0,
|
||||
-radio => 0,
|
||||
-vscrollbar => 'right',
|
||||
-onselchange => $refresh_panels,
|
||||
);
|
||||
|
||||
$assembly_panel = $middle->add(
|
||||
'assembly_viewer',
|
||||
'TextViewer',
|
||||
-title => "Assembly View",
|
||||
-border => 1,
|
||||
-text => $assembly_text,
|
||||
);
|
||||
|
||||
$source_panel = $right->add(
|
||||
'source_viewer',
|
||||
'TextViewer',
|
||||
-title => "Source View",
|
||||
-border => 1,
|
||||
-text => $source_text,
|
||||
);
|
||||
|
||||
$win->add(
|
||||
'titlebar', 'Label',
|
||||
-y => 0,
|
||||
-text => "Experiment: $selected_experiment",
|
||||
);
|
||||
|
||||
$win->add(
|
||||
'info', 'Label',
|
||||
-y => -1,
|
||||
-text =>
|
||||
"Space = toggle, F = filter markers, S = open source, A = open assembly, N = edit notes, R = resize, Q = quit",
|
||||
);
|
||||
|
||||
sub set_geometry {
|
||||
my ( $widget, $x, $y, $w, $h ) = @_;
|
||||
|
||||
$widget->{-x} = $x;
|
||||
$widget->{-y} = $y;
|
||||
$widget->{-width} = $w;
|
||||
$widget->{-height} = $h;
|
||||
|
||||
# $widget->layout();
|
||||
}
|
||||
|
||||
sub layout_resize {
|
||||
my $w = $win->width();
|
||||
my $h = $win->height();
|
||||
|
||||
my $w1 = int( $w * 0.3 );
|
||||
my $w2 = int( $w * 0.3 );
|
||||
my $w3 = int( $w - $w1 - $w2 );
|
||||
|
||||
set_geometry( $left, 0, 1, $w1, $h - 2 );
|
||||
set_geometry( $middle, $w1, 1, $w2, $h - 2 );
|
||||
set_geometry( $right, $w1 + $w2, 1, $w3, $h - 2 );
|
||||
|
||||
$cui->layout();
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Filter Popup
|
||||
# =============================================================================
|
||||
|
||||
sub markers_filter_popup {
|
||||
my $w = 60;
|
||||
my $h = 24;
|
||||
my $h1 = $h - 7; # top listboxes height
|
||||
|
||||
my @bench_values = @benchs;
|
||||
my %bench_labels = map { $_ => $_ } @benchs;
|
||||
|
||||
my @marker_values = @markers;
|
||||
my %marker_labels = map { $_ => $_ } @markers;
|
||||
|
||||
my $popup = $cui->add(
|
||||
'popup', 'Window',
|
||||
-x => int( $cui->width() / 2 - $w / 2 ),
|
||||
-y => int( $cui->height() / 2 - $h / 2 ),
|
||||
-width => $w,
|
||||
-height => $h,
|
||||
-border => 1,
|
||||
-title => "Filter Markers",
|
||||
);
|
||||
|
||||
my $popup_left = $popup->add(
|
||||
'popup_left', 'Container',
|
||||
-x => 0,
|
||||
-y => 1,
|
||||
-width => $w / 2,
|
||||
-height => $h1,
|
||||
);
|
||||
|
||||
my $popup_right = $popup->add(
|
||||
'popup_right', 'Container',
|
||||
-x => $w / 2,
|
||||
-y => 1,
|
||||
-width => $w / 2,
|
||||
-height => $h1,
|
||||
);
|
||||
|
||||
my $popup_bottom = $popup->add(
|
||||
'popup_bottom', 'Container',
|
||||
-x => 0,
|
||||
-y => $h1 + 1,
|
||||
-width => $w,
|
||||
-height => 3,
|
||||
);
|
||||
|
||||
my $benchmark_filter = $popup_left->add(
|
||||
'benchmark_filter',
|
||||
'Listbox',
|
||||
-title => "By Benchmark",
|
||||
-border => 1,
|
||||
-values => \@bench_values,
|
||||
-labels => \%bench_labels,
|
||||
-multi => 1,
|
||||
-radio => 0,
|
||||
);
|
||||
|
||||
my $marker_filter = $popup_right->add(
|
||||
'marker_filter',
|
||||
'Listbox',
|
||||
-title => "By Type",
|
||||
-border => 1,
|
||||
-values => \@marker_values,
|
||||
-labels => \%marker_labels,
|
||||
-multi => 1,
|
||||
-radio => 0,
|
||||
);
|
||||
|
||||
my $threshold = $popup_bottom->add(
|
||||
'threshold', 'TextEntry',
|
||||
-title => "By Count Threshold",
|
||||
-border => 1,
|
||||
-text => $selected_threshold,
|
||||
-pos => length($selected_threshold),
|
||||
-regexp => '/^\d*$/',
|
||||
);
|
||||
|
||||
$popup->add(
|
||||
'popup_info', 'Label',
|
||||
-y => -1,
|
||||
-text => "Space = toggle, F = cycle focus, C = confirm, Q = quit",
|
||||
);
|
||||
|
||||
$benchmark_filter->set_selection( map { $index_of_benchs{$_} }
|
||||
@selected_benchs );
|
||||
$marker_filter->set_selection( map { $index_of_markers{$_} }
|
||||
@selected_markers );
|
||||
|
||||
my $focus = sub {
|
||||
if ( $popup_focus eq "left" ) {
|
||||
$benchmark_filter->focus();
|
||||
}
|
||||
elsif ( $popup_focus eq "right" ) {
|
||||
$marker_filter->focus();
|
||||
}
|
||||
else {
|
||||
$threshold->focus();
|
||||
}
|
||||
};
|
||||
|
||||
$popup->set_binding(
|
||||
sub {
|
||||
@selected_benchs = $benchmark_filter->get();
|
||||
@selected_markers = $marker_filter->get();
|
||||
$selected_threshold = int( $threshold->get() ) or 0;
|
||||
|
||||
filter_marker_values( @selected_benchs, @selected_markers );
|
||||
|
||||
$cui->delete('popup');
|
||||
$cui->layout();
|
||||
},
|
||||
'c',
|
||||
);
|
||||
|
||||
$popup->set_binding(
|
||||
sub {
|
||||
if ( $popup_focus eq "left" ) {
|
||||
$popup_focus = "right";
|
||||
}
|
||||
elsif ( $popup_focus eq "right" ) {
|
||||
$popup_focus = "bottom";
|
||||
}
|
||||
else {
|
||||
$popup_focus = "left";
|
||||
}
|
||||
$focus->();
|
||||
},
|
||||
'f',
|
||||
);
|
||||
|
||||
$popup->set_binding(
|
||||
sub {
|
||||
$cui->delete('popup');
|
||||
$cui->layout();
|
||||
},
|
||||
'q'
|
||||
);
|
||||
|
||||
$cui->layout();
|
||||
$focus->();
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Notes Popup
|
||||
# =============================================================================
|
||||
|
||||
sub edit_notes_popup {
|
||||
my $w = 60;
|
||||
my $h = 24;
|
||||
|
||||
my $marker = $markers_panel->get_active_value();
|
||||
my $marker_text =
|
||||
Util::read_marker_info( $selected_experiment, $marker->{benchmark},
|
||||
$marker->{fault_address} );
|
||||
|
||||
my $popup = $cui->add(
|
||||
'popup', 'Window',
|
||||
-x => int( $cui->width() / 2 - $w / 2 ),
|
||||
-y => int( $cui->height() / 2 - $h / 2 ),
|
||||
-width => $w,
|
||||
-height => $h,
|
||||
-border => 1,
|
||||
-title => "Edit Notes",
|
||||
);
|
||||
|
||||
my $notes = $popup->add(
|
||||
'marker_notes',
|
||||
'TextEditor',
|
||||
-height => $h - 3,
|
||||
-border => 1,
|
||||
-text => $marker_text,
|
||||
-pos => length($marker_text),
|
||||
);
|
||||
|
||||
$popup->add(
|
||||
'popup_info', 'Label',
|
||||
-y => -1,
|
||||
-text => "^S/^C = save, ^Q = quit",
|
||||
);
|
||||
|
||||
$popup->set_binding(
|
||||
sub {
|
||||
my $text = $notes->get();
|
||||
|
||||
if ( length($text) > 0 ) {
|
||||
Util::overwrite_marker_info( $selected_experiment,
|
||||
$marker->{benchmark}, $marker->{fault_address}, $text, );
|
||||
}
|
||||
else {
|
||||
Util::delete_marker_info( $selected_experiment,
|
||||
$marker->{benchmark}, $marker->{fault_address} );
|
||||
}
|
||||
|
||||
$marker_labels{$marker} = marker_label($marker);
|
||||
|
||||
$cui->delete('popup');
|
||||
$cui->layout();
|
||||
$markers_panel->draw();
|
||||
},
|
||||
"\cS",
|
||||
"\cC",
|
||||
);
|
||||
|
||||
$popup->set_binding(
|
||||
sub {
|
||||
$cui->delete('popup');
|
||||
$cui->layout();
|
||||
},
|
||||
"\cQ"
|
||||
);
|
||||
|
||||
$cui->layout();
|
||||
$notes->focus();
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Bindings
|
||||
# =============================================================================
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
markers_filter_popup();
|
||||
},
|
||||
'f',
|
||||
);
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
edit_notes_popup();
|
||||
},
|
||||
'n',
|
||||
);
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
layout_resize();
|
||||
},
|
||||
'r',
|
||||
);
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
system( 'neovide', '--fork', $source_file, '--', "+$source_line" );
|
||||
},
|
||||
's',
|
||||
);
|
||||
|
||||
my $objdump_out;
|
||||
my @objdump_lines;
|
||||
my $temp_file;
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
my $file = "$local_archive_dir/$selected_experiment/system.elf";
|
||||
|
||||
my $marker = $markers_panel->get_active_value();
|
||||
my $objdump_address = lc substr( $marker->{fault_address}, 2 );
|
||||
|
||||
if ( !defined $objdump_out ) {
|
||||
$objdump_out = qx{objdump $file -D -M intel -C --source};
|
||||
$objdump_out =~ s/.*\n.*\n.*\n.*\n.*\n.*\n//;
|
||||
@objdump_lines = split "\n", $objdump_out;
|
||||
|
||||
( my $fhandle, $temp_file ) = tempfile();
|
||||
print $fhandle $objdump_out;
|
||||
close($fhandle);
|
||||
}
|
||||
|
||||
my $temp_line;
|
||||
for my $i ( 1 .. scalar(@objdump_lines) ) {
|
||||
my $line = $objdump_lines[ $i - 1 ];
|
||||
|
||||
if ( grep { /^\s*$objdump_address/ } $line ) {
|
||||
$temp_line = $i;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ( defined $temp_line ) {
|
||||
system( 'neovide', '--fork', $temp_file, '--', "+$temp_line" );
|
||||
}
|
||||
else {
|
||||
system( 'neovide', '--fork', $temp_file );
|
||||
}
|
||||
},
|
||||
'a',
|
||||
);
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
|
||||
},
|
||||
'g',
|
||||
);
|
||||
|
||||
$win->set_binding(
|
||||
sub {
|
||||
$cui->mainloopExit();
|
||||
},
|
||||
'q',
|
||||
);
|
||||
|
||||
# =============================================================================
|
||||
# Main Loop
|
||||
# =============================================================================
|
||||
|
||||
load_faults_csv();
|
||||
filter_marker_values();
|
||||
|
||||
layout_resize();
|
||||
$markers_panel->focus();
|
||||
$refresh_panels->();
|
||||
$cui->mainloop();
|
||||
|
||||
$cui->leave_curses();
|
||||
$cui->delete('explorer');
|
||||
115
scripts/ghidra/ImportMarkersAsBookmarks.java
Normal file
115
scripts/ghidra/ImportMarkersAsBookmarks.java
Normal file
@ -0,0 +1,115 @@
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.BookmarkManager;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
|
||||
public class ImportMarkersAsBookmarks extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
// Can't do this in headless mode
|
||||
// File input = askFile("Select CSV file", "Import");
|
||||
|
||||
String[] args = getScriptArgs();
|
||||
if (args.length < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing CSV file path.\nUsage: ImportMarkersAsBookmarks <markers.csv>");
|
||||
}
|
||||
|
||||
File input = new File(args[0]);
|
||||
if (!input.isFile()) {
|
||||
throw new IllegalArgumentException(
|
||||
"CSV file does not exist or is not a regular file: " + input.getAbsolutePath());
|
||||
}
|
||||
|
||||
println("Importing bookmarks from: " + input.getAbsolutePath());
|
||||
|
||||
// https://ghidra.re/ghidra_docs/api/ghidra/program/model/listing/BookmarkManager.html
|
||||
BookmarkManager bm = currentProgram.getBookmarkManager();
|
||||
|
||||
int imported = 0;
|
||||
int skipped = 0;
|
||||
int lineNo = 0;
|
||||
|
||||
// CSV columns: (benchmark, resulttype, faults, fault_address)
|
||||
// Example: (ip , OK_MARKER , 4311 , 0x10001B )
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(input))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
lineNo++;
|
||||
|
||||
line = line.trim();
|
||||
if (line.isEmpty() || line.startsWith("#") || line.startsWith("benchmark")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure to always use "," delimiter and never quotations
|
||||
String[] parts = line.split(",");
|
||||
if (parts.length != 4) {
|
||||
skipped++;
|
||||
printerr("Line " + lineNo + ": malformed");
|
||||
continue;
|
||||
}
|
||||
|
||||
String benchText = parts[0].trim();
|
||||
String typeText = parts[1].trim();
|
||||
String countText = parts[2].trim();
|
||||
String addrText = parts[3].trim();
|
||||
|
||||
if (benchText.isEmpty()
|
||||
|| typeText.isEmpty()
|
||||
|| countText.isEmpty()
|
||||
|| addrText.isEmpty()) {
|
||||
skipped++;
|
||||
printerr("Line " + lineNo + ": malformed");
|
||||
continue;
|
||||
}
|
||||
|
||||
Address addr = parseAddress(addrText);
|
||||
if (addr == null) {
|
||||
skipped++;
|
||||
printerr("Line " + lineNo + ": invalid address: " + addrText);
|
||||
continue;
|
||||
}
|
||||
|
||||
println(
|
||||
"Adding bookmark at "
|
||||
+ addr
|
||||
+ " with type "
|
||||
+ benchText
|
||||
+ " with category "
|
||||
+ benchText // ip, mem or regs
|
||||
+ " - "
|
||||
+ typeText
|
||||
+ " description "
|
||||
+ countText
|
||||
+ "x");
|
||||
|
||||
// TYPE CATEGORY DESCRIPTION
|
||||
bm.setBookmark(addr, benchText, benchText + " - " + typeText, countText + "x");
|
||||
imported++;
|
||||
}
|
||||
}
|
||||
|
||||
println("Imported " + imported + " bookmarks.");
|
||||
if (skipped > 0) {
|
||||
println("Skipped " + skipped + " lines.");
|
||||
}
|
||||
}
|
||||
|
||||
public Address parseAddress(String text) {
|
||||
text = text.trim();
|
||||
|
||||
if (text.startsWith("0x") || text.startsWith("0X")) {
|
||||
text = text.substring(2);
|
||||
}
|
||||
|
||||
try {
|
||||
return toAddr(text);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
scripts/ghidra/RemapSourcePaths.java
Normal file
36
scripts/ghidra/RemapSourcePaths.java
Normal file
@ -0,0 +1,36 @@
|
||||
import ghidra.program.database.sourcemap.UserDataPathTransformer;
|
||||
import ghidra.program.model.sourcemap.SourcePathTransformer;
|
||||
|
||||
// Remap:
|
||||
// /build/source/core (libiwasm)
|
||||
// /home/christoph/Notes/TU/MastersThesis/FailNix/build-sum2_repl_cored_late/module_host.c
|
||||
public class RemapSourcePaths extends GhidraScript {
|
||||
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
String[] args = getScriptArgs();
|
||||
if (args.length < 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing file paths.\nUsage: RemapSourcePaths <libiwasm> <host>");
|
||||
}
|
||||
|
||||
// https://ghidra.re/ghidra_docs/api/ghidra/program/model/sourcemap/SourcePathTransformer.html
|
||||
SourcePathTransformer tx = UserDataPathTransformer.getPathTransformer(currentProgram);
|
||||
|
||||
String oldIwasmDir = "/build/source/core";
|
||||
String newIwasmDir = args[0];
|
||||
|
||||
tx.addDirectoryTransform(oldIwasmDir, newIwasmDir);
|
||||
println("Added transform:");
|
||||
println(" " + oldIwasmDir + " -> " + newIwasmDir);
|
||||
|
||||
// TODO: What to do here? Need to know the build dir name...
|
||||
String failNix = "/home/christoph/Notes/TU/MastersThesis/FailNix";
|
||||
String oldHostDir = failNix + "/build-.../module_host.c";
|
||||
String newHostDir = args[1];
|
||||
|
||||
tx.addDirectoryTransform(oldHostDir, newHostDir);
|
||||
println("Added transform:");
|
||||
println(" " + oldHostDir + " -> " + newHostDir);
|
||||
}
|
||||
}
|
||||
622
scripts/menu.pl
Normal file
622
scripts/menu.pl
Normal file
@ -0,0 +1,622 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
|
||||
use Util;
|
||||
use Mars;
|
||||
use TUI;
|
||||
use Filters;
|
||||
use Text::CSV_XS;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
# TODO: Much can be extracted into utility functions
|
||||
|
||||
my $local_obsidian = '/home/christoph/Notes/Obsidian/Chriphost';
|
||||
my $local_obsidian_attach = "$local_obsidian/attach";
|
||||
|
||||
my $local_newlib = '/home/christoph/Notes/TU/MastersThesis/07 NewLib';
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_wamr = "$local_root/wamr";
|
||||
my $local_scripts_dir = "$local_root/scripts";
|
||||
my $local_builds_dir = "$local_root/builds";
|
||||
my $local_archive_dir = "$local_root/injections";
|
||||
my $local_charts_dir = "$local_root/scripts/charts";
|
||||
my $local_ghidra_projects = "$local_root/ghidra";
|
||||
my $local_ghidra_scripts = "$local_root/scripts/ghidra";
|
||||
my $local_db_conf = "$local_root/db.conf";
|
||||
|
||||
my $resultbrowser_port = '5000';
|
||||
my $resultbrowser = 'resultbrowser.py';
|
||||
|
||||
my $remote_root = '/home/lab/smchurla/Documents/failnix';
|
||||
my $remote_builds_dir = "$remote_root/builds";
|
||||
|
||||
my $db_host = "127.0.0.1";
|
||||
my $db_port = "3306";
|
||||
my $db_user = "smchurla";
|
||||
|
||||
my %handlers = (
|
||||
'01. Build Experiments' => sub { do qq{$local_scripts_dir/build.pl}; },
|
||||
|
||||
'02. Deploy Experiments (Mars)' =>
|
||||
sub { do qq{$local_scripts_dir/deploy.pl}; },
|
||||
|
||||
'03. Archive Experiments (Downloads from Mars)' => sub {
|
||||
|
||||
# Download ran experiments from mars
|
||||
my @dirs = Mars::find_remote_subdirs($remote_builds_dir);
|
||||
|
||||
my @existing = Util::find_subdirs($local_archive_dir);
|
||||
my @new_dirs;
|
||||
foreach (@dirs) {
|
||||
my $dir = $_ =~ s/:/-/gr;
|
||||
unless ( grep { /$dir/ } @existing ) {
|
||||
push @new_dirs, $_;
|
||||
}
|
||||
}
|
||||
|
||||
my @selected_dirs =
|
||||
TUI::select_from_list( "Select Experiments to Download from Mars",
|
||||
1, @new_dirs );
|
||||
die "No experiment selected" unless @selected_dirs;
|
||||
Mars::download_dir( "$remote_builds_dir/$_",
|
||||
"$local_archive_dir/" . $_ =~ s/:/-/gr )
|
||||
for @selected_dirs;
|
||||
},
|
||||
|
||||
'04. Query Databases (Mars)' => sub {
|
||||
|
||||
# Select databases
|
||||
my @db_names = Mars::db_list();
|
||||
my @selected_dbs =
|
||||
TUI::select_from_list( "Select Databases to Query", 1, @db_names );
|
||||
die "No database selected" unless @selected_dbs;
|
||||
|
||||
# Select queries
|
||||
my @queries =
|
||||
map { s/\.pm//r } Util::find_files("$local_root/scripts/Queries");
|
||||
my @selected_queries =
|
||||
TUI::select_from_list( "Select Queries to Run", 1, @queries );
|
||||
die "No query selected" unless @selected_queries;
|
||||
|
||||
# Select filter configs
|
||||
my @filter_choices = ("None");
|
||||
my %filter_label_name;
|
||||
my @filter_configs;
|
||||
my $configs = Filters::get_configs();
|
||||
foreach my $name ( sort keys %$configs ) {
|
||||
my $label = $configs->{$name}{label};
|
||||
push @filter_choices, $label;
|
||||
$filter_label_name{$label} = $name;
|
||||
}
|
||||
my @selected_filter_labels =
|
||||
TUI::select_from_list( "Select Filters to Apply", 1,
|
||||
@filter_choices );
|
||||
die "No filter selected" unless @selected_filter_labels;
|
||||
@filter_configs = ();
|
||||
foreach my $label (@selected_filter_labels) {
|
||||
if ( $label eq "None" ) {
|
||||
push @filter_configs, '';
|
||||
}
|
||||
else {
|
||||
push @filter_configs, $filter_label_name{$label};
|
||||
}
|
||||
}
|
||||
|
||||
# Run queries on databases
|
||||
foreach my $db (@selected_dbs) {
|
||||
foreach my $query (@selected_queries) {
|
||||
foreach my $config (@filter_configs) {
|
||||
Util::rewrite_file( $local_db_conf, "database=",
|
||||
"database=$db\n" );
|
||||
|
||||
my $config_label = length($config) ? " ($config)" : "";
|
||||
say "Running $query$config_label on $db...";
|
||||
Util::execute_query( $db =~ s/smchurla_//r,
|
||||
$query, $local_db_conf, $local_archive_dir, 0,
|
||||
$config );
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'05. Import Experiments Into Ghidra' => sub {
|
||||
|
||||
my @existing = Util::find_files($local_ghidra_projects);
|
||||
|
||||
# Determine if an experiment was already imported
|
||||
my $project_exists = sub {
|
||||
my ($name) = @_;
|
||||
$name =~ s/:/-/g;
|
||||
|
||||
return grep { /^$name.gpr$/ } @existing;
|
||||
};
|
||||
|
||||
# Import archived experiments into ghidra
|
||||
my @dirs =
|
||||
grep { !$project_exists->($_) }
|
||||
Util::find_subdirs($local_archive_dir);
|
||||
|
||||
my @dirs_with_notes;
|
||||
foreach my $dir (@dirs) {
|
||||
my $info = Util::read_experiment_info($dir);
|
||||
|
||||
push @dirs_with_notes,
|
||||
( defined $info && length($info) > 0 )
|
||||
? sprintf( "%-50s (%s)", $dir, $info )
|
||||
: $dir;
|
||||
}
|
||||
|
||||
my @selected_dirs =
|
||||
TUI::select_from_list( "Select Experiments to Import into Ghidra",
|
||||
1, @dirs_with_notes );
|
||||
|
||||
foreach (@selected_dirs) {
|
||||
my $experiment = $_ =~ s/(.*?)\s+\(.+\)$/$1/r;
|
||||
|
||||
say "Creating Ghidra project for $experiment...";
|
||||
system(
|
||||
'ghidra-analyzeHeadless',
|
||||
|
||||
$local_ghidra_projects, $experiment =~ s/:/-/gr,
|
||||
'-import', "$local_archive_dir/$experiment/system.elf",
|
||||
'-scriptPath', $local_ghidra_scripts,
|
||||
'-postScript', 'DWARFLineInfoSourceMapScript',
|
||||
'-postScript', 'DWARFLineInfoCommentScript',
|
||||
'-postScript', 'ImportMarkersAsBookmarks',
|
||||
"$local_archive_dir/$experiment/faults.csv"
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
'06. Import Experiments Into Obsidian' => sub {
|
||||
|
||||
my @experiments = Util::find_subdirs($local_archive_dir);
|
||||
|
||||
# Filter experiments that already have notes
|
||||
my @new_experiments;
|
||||
my @existing_notes = split "\n", qx{obsidian files};
|
||||
foreach my $experiment (@experiments) {
|
||||
push @new_experiments, $experiment
|
||||
unless ( grep { /zettel\/$experiment/ } @existing_notes );
|
||||
}
|
||||
|
||||
my @selected_experiments =
|
||||
TUI::select_from_list( "Select Experiments to Import into Obsidian",
|
||||
1, @new_experiments );
|
||||
die "No experiment selected" unless @selected_experiments;
|
||||
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
|
||||
# Create note
|
||||
system(
|
||||
'obsidian', 'create',
|
||||
"name=$experiment", 'path=zettel',
|
||||
'template=FailExperiment', 'open',
|
||||
'newtab'
|
||||
);
|
||||
|
||||
# Insert results
|
||||
if ( -f "$local_archive_dir/$experiment/results.txt" ) {
|
||||
open( my $fhandle, '<',
|
||||
"$local_archive_dir/$experiment/results.txt" )
|
||||
or return;
|
||||
my $results = join "", <$fhandle>;
|
||||
close($fhandle);
|
||||
|
||||
say "$local_archive_dir/$experiment/results.txt does not exist";
|
||||
|
||||
system( 'obsidian', 'append', "file=zettel/$experiment",
|
||||
"content=## Results\n\n```\n$results```\n" );
|
||||
}
|
||||
|
||||
# Insert charts
|
||||
system(
|
||||
'obsidian', 'append',
|
||||
"file=zettel/$experiment", "content=## Charts\n\n"
|
||||
);
|
||||
|
||||
my $attach_image = sub {
|
||||
my ($name) = @_;
|
||||
|
||||
system( 'obsidian', 'append', "file=zettel/$experiment",
|
||||
"content=\n"
|
||||
);
|
||||
};
|
||||
$attach_image->("single_result");
|
||||
$attach_image->("scatter");
|
||||
}
|
||||
},
|
||||
|
||||
'10. Explore Experiment Results' =>
|
||||
sub { do qq{$local_scripts_dir/explore.pl}; },
|
||||
|
||||
'11. Compare Experiment Results' => sub {
|
||||
|
||||
my @selected_experiments = Util::select_experiment(1);
|
||||
|
||||
# TODO: Fails silently if not every selected experiment has this datafile
|
||||
my $resultsdata_csv =
|
||||
Util::pick_data_file( "$local_archive_dir/$selected_experiments[0]",
|
||||
"resultsdata" );
|
||||
|
||||
# Read results
|
||||
my %all_results;
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
|
||||
# Schema: benchmark, resulttype, faults
|
||||
my $data = Text::CSV_XS::csv(
|
||||
in => "$local_archive_dir/$experiment/$resultsdata_csv",
|
||||
headers => 'auto'
|
||||
);
|
||||
|
||||
foreach my $row (@$data) {
|
||||
$all_results{$experiment}{ $row->{benchmark} }
|
||||
{ $row->{resulttype} } = $row->{faults};
|
||||
}
|
||||
}
|
||||
|
||||
my @benchs = ( 'ip', 'mem', 'regs' );
|
||||
my @markers = (
|
||||
'OK_MARKER', 'FAIL_MARKER',
|
||||
'DETECTED_MARKER', 'TIMEOUT',
|
||||
'TRAP', 'WRITE_TEXTSEGMENT',
|
||||
'ACCESS_OUTERSPACE', 'GROUP1_MARKER'
|
||||
);
|
||||
|
||||
my $heading = sprintf( "%5s %20s ", "BENCH", "TYPE" );
|
||||
my $subheading = sprintf( "%5s %20s ", "", "" );
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
$heading .= sprintf( "%50s ", $experiment );
|
||||
$subheading .=
|
||||
sprintf( "%50s ", Util::read_experiment_info($experiment) );
|
||||
}
|
||||
|
||||
my @entries = ( $heading, $subheading, "" );
|
||||
foreach my $benchmark (@benchs) {
|
||||
foreach my $marker (@markers) {
|
||||
my $entry = sprintf( "%5s %20s ", $benchmark, $marker );
|
||||
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
if ( exists $all_results{$experiment}{$benchmark}{$marker} )
|
||||
{
|
||||
$entry .= sprintf(
|
||||
"%50s ",
|
||||
Util::format_number_sep(
|
||||
$all_results{$experiment}{$benchmark}{$marker}
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$entry .= sprintf( "%50s ", "" );
|
||||
}
|
||||
}
|
||||
|
||||
push @entries, $entry;
|
||||
}
|
||||
push @entries, "";
|
||||
}
|
||||
|
||||
TUI::select_from_list(
|
||||
"Comparing " . scalar(@selected_experiments) . " Experiments",
|
||||
0, @entries );
|
||||
},
|
||||
|
||||
'12. Open Experiment in BinaryNinja' => sub {
|
||||
my @selected_experiments = Util::select_experiment(1);
|
||||
my @paths =
|
||||
map { "$local_archive_dir/$_/system.elf" } @selected_experiments;
|
||||
|
||||
system( 'binaryninja', @paths );
|
||||
},
|
||||
|
||||
'13. Open Experiment in Binsider' => sub {
|
||||
my $selected_experiment = Util::select_experiment(0);
|
||||
|
||||
system( 'binsider',
|
||||
"$local_archive_dir/$selected_experiment/system.elf" );
|
||||
},
|
||||
|
||||
'14. Open Experiment in Ghidra' => sub {
|
||||
|
||||
my @projects =
|
||||
map { s/\.gpr//r } Util::find_files($local_ghidra_projects);
|
||||
my @selected_projects =
|
||||
TUI::select_from_list( "Select Project to Open in Ghidra",
|
||||
0, @projects );
|
||||
die "No project selected" unless @selected_projects;
|
||||
my $project = $selected_projects[0];
|
||||
system(
|
||||
join " ",
|
||||
(
|
||||
"_JAVA_AWT_WM_NONREPARENTING=1", "ghidra",
|
||||
"$local_ghidra_projects/$project.gpr",
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'15. Run Objdump on Experiment' => sub {
|
||||
my $selected_experiment = Util::select_experiment(0);
|
||||
|
||||
system(
|
||||
"objdump $local_archive_dir/$selected_experiment/system.elf -D -M intel -S | bat --color never"
|
||||
);
|
||||
},
|
||||
|
||||
'16. Run Wasm-Objdump on Experiment' => sub {
|
||||
my $selected_experiment = Util::select_experiment(0);
|
||||
|
||||
system(
|
||||
"wasm-objdump -d $local_archive_dir/$selected_experiment/wasm_module.wasm | bat --color never"
|
||||
);
|
||||
},
|
||||
|
||||
'17. Run Radare2 on Experiment' => sub {
|
||||
my $selected_experiment = Util::select_experiment(0);
|
||||
|
||||
say "Radare help:";
|
||||
say "s <address> - Seek to address";
|
||||
say "pd <n> - Disassemble n instructions";
|
||||
say "pdf - Disassemble current function";
|
||||
say "pdf @ <function> - Disassemble function";
|
||||
say "pdr - Disassemble recursively";
|
||||
say "V - Switch view";
|
||||
say "p - Switch print mode";
|
||||
say "P - Switch layout";
|
||||
system(
|
||||
'radare2', '-AA',
|
||||
'-c', '"-s dbg.os_main"',
|
||||
'-e', 'scr.color=3',
|
||||
'-e', 'scr.scrollbar=0',
|
||||
'-e', 'scr.responsive=true',
|
||||
'-e', 'scr.interactive=true',
|
||||
'-e', 'scr.utf8=true',
|
||||
'-e', 'scr.utf8.curvy=true',
|
||||
'-e', 'asm.syntax=intel',
|
||||
'-e', 'asm.lines=false',
|
||||
'-e', 'asm.xrefs=true',
|
||||
'-e', 'asm.flags=true',
|
||||
'-e', 'asm.comments=true',
|
||||
'-e', 'asm.functions=true',
|
||||
'-e', 'asm.var=true',
|
||||
'-e', 'asm.cmt.right=true',
|
||||
'-e', 'asm.dwarf=true',
|
||||
'-e', 'asm.pseudo=false',
|
||||
'-e', 'asm.describe=false',
|
||||
'-e', 'bin.relocs.apply=true',
|
||||
"$local_archive_dir/$selected_experiment/system.elf",
|
||||
|
||||
);
|
||||
},
|
||||
|
||||
'18. Open Database in ResultBrowser (Mars)' => sub {
|
||||
|
||||
my @db_names = Mars::db_list();
|
||||
my @selected_dbs =
|
||||
TUI::select_from_list( "Select Database for ResultBrowser",
|
||||
0, @db_names );
|
||||
die "No database selected" unless @selected_dbs;
|
||||
my $selected_db = $selected_dbs[0];
|
||||
|
||||
Util::rewrite_file( $local_db_conf, "database=",
|
||||
"database=$selected_db\n" );
|
||||
|
||||
system( $resultbrowser, '-c', $local_db_conf, '--host=0.0.0.0',
|
||||
"--port=$resultbrowser_port" );
|
||||
},
|
||||
|
||||
'19. Open Database in LazySQL (Mars)' => sub {
|
||||
my $experiment =
|
||||
Util::select_experiment(0) =~ s/T(\d\d)-(\d\d)-(\d\d)/T$1:$2:$3/r;
|
||||
my $ssh = Mars::ssh_connect();
|
||||
my $db_password = Mars::read_db_password_file();
|
||||
|
||||
system( 'lazysql', '-read-only',
|
||||
"mariadb://$db_user:$db_password\@$db_host:$db_port/${db_user}_$experiment"
|
||||
);
|
||||
},
|
||||
|
||||
'20. Open TablePlus (Mars)' => sub {
|
||||
system('tableplus');
|
||||
},
|
||||
|
||||
'21. Run Build in GDB' => sub {
|
||||
my @builds = grep { /linux/ } Util::find_subdirs($local_builds_dir);
|
||||
my @selected_builds =
|
||||
TUI::select_from_list( "Select Build to Run in GDB", 0, @builds );
|
||||
die "No build selected" unless @selected_builds;
|
||||
my $selected_build = $selected_builds[0];
|
||||
|
||||
my $build_dir = "$local_builds_dir/$selected_build";
|
||||
my $build_name = $selected_build =~ s/.*?_.*?_(.*?)_.*$/$1/r;
|
||||
|
||||
say "$build_name";
|
||||
|
||||
system(
|
||||
'gdb',
|
||||
'--tui',
|
||||
'-q',
|
||||
"$build_dir/system.elf",
|
||||
'-ex',
|
||||
'set disassembly-flavor intel',
|
||||
'-ex',
|
||||
"set substitute-path 'build-$build_name' '$build_dir'",
|
||||
'-ex',
|
||||
"set substitute-path '/build/source/core' '$local_wamr/core'",
|
||||
'-ex',
|
||||
'break main',
|
||||
'-ex',
|
||||
'break fail_start_trace',
|
||||
'-ex',
|
||||
'break fail_stop_trace',
|
||||
'-ex',
|
||||
'break fail_marker_positive',
|
||||
'-ex',
|
||||
'break fail_marker_detected',
|
||||
'-ex',
|
||||
'break fail_marker_negative',
|
||||
'-ex',
|
||||
'break fail_marker_group1',
|
||||
'-ex',
|
||||
'break os_mmap',
|
||||
'-ex',
|
||||
'break wamr_malloc',
|
||||
'-ex',
|
||||
'break wamr_realloc',
|
||||
'-ex',
|
||||
'break wamr_free',
|
||||
);
|
||||
},
|
||||
|
||||
'30. Plot Results' => sub {
|
||||
|
||||
# Generate R ggplot2 charts
|
||||
my @selected_experiments = Util::select_experiment(1);
|
||||
|
||||
my @charts = map { s/\.r//r } Util::find_files($local_charts_dir);
|
||||
my @selected_charts =
|
||||
TUI::select_from_list( "Select Plots to Generate", 1, @charts );
|
||||
die "No plot selected" unless @selected_charts;
|
||||
|
||||
# Need to know which chart uses which datafile
|
||||
my @faults_charts = grep { /heatmap|scatter|sankey/ } @selected_charts;
|
||||
my @resultsdata_charts =
|
||||
grep { /result$|combined_comparison/ } @selected_charts;
|
||||
|
||||
my $faults_csv;
|
||||
my $resultsdata_csv;
|
||||
if (@faults_charts) {
|
||||
$faults_csv = Util::pick_data_file(
|
||||
"$local_archive_dir/$selected_experiments[0]", "faults" );
|
||||
}
|
||||
if (@resultsdata_charts) {
|
||||
$resultsdata_csv = Util::pick_data_file(
|
||||
"$local_archive_dir/$selected_experiments[0]",
|
||||
"resultsdata" );
|
||||
}
|
||||
|
||||
my @single_charts = grep { /single/ } @selected_charts;
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
foreach my $chart (@single_charts) {
|
||||
say " - Generating plot $chart for $experiment...";
|
||||
my @r_args = (
|
||||
'Rscript',
|
||||
"$local_charts_dir/$chart.r",
|
||||
"$local_archive_dir/$experiment"
|
||||
);
|
||||
push @r_args, $faults_csv
|
||||
if defined $faults_csv && $chart =~ /heatmap|scatter|sankey/;
|
||||
push @r_args, $resultsdata_csv
|
||||
if defined $resultsdata_csv
|
||||
&& $chart =~ /result$|combined_comparison/;
|
||||
system(@r_args);
|
||||
}
|
||||
}
|
||||
|
||||
my @combined_charts = grep { /combined/ } @selected_charts;
|
||||
my $print_experiments = join " ", @selected_experiments;
|
||||
my @path_experiments =
|
||||
map { "$local_archive_dir/$_" } @selected_experiments;
|
||||
foreach my $chart (@combined_charts) {
|
||||
say " - Generating plot $chart for ($print_experiments)...";
|
||||
my @r_args =
|
||||
( 'Rscript', "$local_charts_dir/$chart.r", @path_experiments );
|
||||
push @r_args, $faults_csv
|
||||
if defined $faults_csv && $chart =~ /heatmap|scatter|sankey/;
|
||||
push @r_args, $resultsdata_csv
|
||||
if defined $resultsdata_csv
|
||||
&& $chart =~ /result$|combined_comparison/;
|
||||
system(@r_args);
|
||||
}
|
||||
},
|
||||
|
||||
'95. Delete Builds' => sub {
|
||||
|
||||
# Delete old build files
|
||||
my @builds = Util::find_subdirs($local_builds_dir);
|
||||
my @selected_builds =
|
||||
TUI::select_from_list( "Select Builds to Delete", 1, @builds );
|
||||
die "No builds selected" unless @selected_builds;
|
||||
system( 'rm', '-rf', "$local_builds_dir/$_" ) for @selected_builds;
|
||||
},
|
||||
|
||||
'96. Delete Builds (Mars)' => sub {
|
||||
|
||||
# Delete ran experiments from mars
|
||||
my @builds = Mars::find_remote_subdirs($remote_builds_dir);
|
||||
my @selected_builds =
|
||||
TUI::select_from_list( "Select Builds to Delete from Mars",
|
||||
1, @builds );
|
||||
die "No experiment selected" unless @selected_builds;
|
||||
Mars::ssh_system( 'rm', '-rf', "$remote_builds_dir/$_" )
|
||||
for @selected_builds;
|
||||
},
|
||||
|
||||
'97. Delete Ghidra Projects' => sub {
|
||||
|
||||
# Delete ghidra projects
|
||||
my @projects =
|
||||
map { s/\.gpr//r } Util::find_files($local_ghidra_projects);
|
||||
my @selected_projects =
|
||||
TUI::select_from_list( "Select Ghidra Projects to Delete",
|
||||
1, @projects );
|
||||
die "No project selected" unless @selected_projects;
|
||||
system( 'rm', '-rf', "$local_ghidra_projects/$_.gpr" )
|
||||
for @selected_projects;
|
||||
system( 'rm', '-rf', "$local_ghidra_projects/$_.rep" )
|
||||
for @selected_projects;
|
||||
},
|
||||
|
||||
'98. Delete Archived Experiments' => sub {
|
||||
|
||||
# Delete archived experiments
|
||||
my @selected_experiments = Util::select_experiment(1);
|
||||
|
||||
system( 'rm', '-rf', "$local_archive_dir/$_" )
|
||||
for @selected_experiments;
|
||||
},
|
||||
|
||||
'99. Drop Databases (Mars)' => sub {
|
||||
|
||||
# Drop databases on mars
|
||||
my @dbs = Mars::db_list();
|
||||
my @dbs_with_notes;
|
||||
foreach my $db (@dbs) {
|
||||
my $info =
|
||||
Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr );
|
||||
|
||||
push @dbs_with_notes,
|
||||
( defined $info && length($info) > 0 )
|
||||
? sprintf( "%-60s (%s)", $db, $info )
|
||||
: $db;
|
||||
}
|
||||
|
||||
my @selected_dbs =
|
||||
TUI::select_from_list( "Select Databases to Drop from Mars",
|
||||
1, @dbs_with_notes );
|
||||
die "No database selected" unless @selected_dbs;
|
||||
|
||||
@selected_dbs =
|
||||
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs;
|
||||
|
||||
Mars::db_drop($_) for @selected_dbs;
|
||||
},
|
||||
);
|
||||
|
||||
while (1) {
|
||||
my @submenu =
|
||||
TUI::select_from_list( "FailNix Menu", 0, sort keys %handlers );
|
||||
die "No action selected" unless @submenu;
|
||||
|
||||
say @submenu;
|
||||
|
||||
eval { $handlers{ $submenu[0] }(); }
|
||||
}
|
||||
|
||||
Mars::db_disconnect();
|
||||
28
scripts/multi_runner.pl
Normal file
28
scripts/multi_runner.pl
Normal file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
|
||||
use Util;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
my $remote_root = '/home/lab/smchurla/Documents/failnix';
|
||||
my $remote_builds_dir = "$remote_root/builds";
|
||||
|
||||
# Run experiments
|
||||
my @experiments = Util::find_subdirs($remote_builds_dir);
|
||||
for my $experiment (@experiments) {
|
||||
say "Running experiment: $experiment";
|
||||
my $experiment_runner = "$remote_builds_dir/$experiment/runner.pl";
|
||||
system( "perl", $experiment_runner, $experiment,
|
||||
">", Util::shell_quote("$remote_builds_dir/$experiment/0_runner.log"),
|
||||
"2>&1" ) == 0
|
||||
or warn "runner.pl failed for $experiment: $?";
|
||||
}
|
||||
|
||||
Util::notify("Finished all experiments");
|
||||
304
scripts/runner.pl
Normal file
304
scripts/runner.pl
Normal file
@ -0,0 +1,304 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
|
||||
use FindBin;
|
||||
|
||||
# runner.pl is executed from the build dir
|
||||
use lib "$FindBin::Bin/../../scripts/Modules";
|
||||
use lib "$FindBin::Bin/Modules";
|
||||
|
||||
use Filters;
|
||||
use Util;
|
||||
|
||||
use feature 'say';
|
||||
|
||||
my $remote_root = '/home/lab/smchurla/Documents/failnix';
|
||||
my $remote_db_conf = "$remote_root/db.conf";
|
||||
my $remote_builds_dir = "$remote_root/builds";
|
||||
my $remote_runner = "$remote_root/scripts/runner.pl";
|
||||
|
||||
my $db_user = "smchurla";
|
||||
my $db_prefix = "$db_user";
|
||||
|
||||
my $fail_server_port = '22941';
|
||||
my $resultbrowser_port = '22941';
|
||||
my $fail_bin = "$remote_root/fail/bin";
|
||||
my $fail_share = "$remote_root/fail/share";
|
||||
my $bochs_runner = "$fail_bin/bochs-experiment-runner.py";
|
||||
my $fail_trace = "$fail_bin/fail-x86-tracing";
|
||||
my $fail_dump = "$fail_bin/dump-trace";
|
||||
my $fail_import = "$fail_bin/import-trace";
|
||||
my $fail_prune = "$fail_bin/prune-trace";
|
||||
my $fail_server = "$fail_bin/generic-experiment-server";
|
||||
my $fail_inject = "$fail_bin/generic-experiment-client";
|
||||
my $result_browser = "$fail_bin/resultbrowser.py";
|
||||
|
||||
sub trace {
|
||||
my ($experiment) = @_;
|
||||
|
||||
# Util::notify("Tracing $experiment...");
|
||||
|
||||
my $trace_command = join " ", (
|
||||
"$bochs_runner",
|
||||
"-V $fail_share/vgabios.bin",
|
||||
"-b $fail_share/BIOS-bochs-latest",
|
||||
"-1",
|
||||
"-f $fail_trace",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-i $remote_builds_dir/$experiment/system.iso",
|
||||
"--",
|
||||
"-Wf,--start-symbol=fail_start_trace",
|
||||
"-Wf,--save-symbol=fail_start_trace",
|
||||
"-Wf,--end-symbol=fail_stop_trace",
|
||||
"-Wf,--state-file=$remote_builds_dir/$experiment/state",
|
||||
"-Wf,--trace-file=$remote_builds_dir/$experiment/trace.pb",
|
||||
"-Wf,--elf-file=$remote_builds_dir/$experiment/system.elf",
|
||||
|
||||
# "-Wf,--full-trace",
|
||||
# "-Wf,--check-bounds",
|
||||
">$remote_builds_dir/$experiment/1_trace.log 2>&1"
|
||||
);
|
||||
say "Trace command: $trace_command";
|
||||
|
||||
system($trace_command);
|
||||
}
|
||||
|
||||
sub import_trace {
|
||||
my ($experiment) = @_;
|
||||
|
||||
# Util::notify("Importing $experiment trace...");
|
||||
|
||||
# Benchmark: ip
|
||||
my $import_ip_command = join " ", (
|
||||
"$fail_import",
|
||||
"--database-option-file $remote_db_conf",
|
||||
"-t $remote_builds_dir/$experiment/trace.pb",
|
||||
"-i RegisterImporter",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-v $experiment",
|
||||
"-b ip",
|
||||
"--no-gp", # Don't inject general purpose registers
|
||||
"--ip", # Inject instruction pointer
|
||||
">$remote_builds_dir/$experiment/2_import_ip.log 2>&1"
|
||||
);
|
||||
say "Import IP command: $import_ip_command";
|
||||
system($import_ip_command);
|
||||
|
||||
# Benchmark: mem
|
||||
my $import_mem_command = join " ",
|
||||
(
|
||||
"$fail_import",
|
||||
"--database-option-file $remote_db_conf",
|
||||
"-t $remote_builds_dir/$experiment/trace.pb",
|
||||
"-i MemoryImporter",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-v $experiment",
|
||||
"-b mem",
|
||||
">$remote_builds_dir/$experiment/2_import_mem.log 2>&1"
|
||||
);
|
||||
say "Import MEM command: $import_mem_command";
|
||||
system($import_mem_command);
|
||||
|
||||
# Benchmark: regs
|
||||
my $import_regs_command = join " ", (
|
||||
"$fail_import",
|
||||
"--database-option-file $remote_db_conf",
|
||||
"-t $remote_builds_dir/$experiment/trace.pb",
|
||||
"-i RegisterImporter",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-v $experiment",
|
||||
"-b regs",
|
||||
"--flags", # Inject flags register
|
||||
">$remote_builds_dir/$experiment/2_import_regs.log 2>&1"
|
||||
);
|
||||
say "Import REGS command: $import_regs_command";
|
||||
system($import_regs_command);
|
||||
|
||||
# Import fulltrace for VisualFAIL
|
||||
# system(
|
||||
# join " ",
|
||||
# (
|
||||
# "$fail_import",
|
||||
# "--database-option-file $remote_db_conf",
|
||||
# "-t $remote_builds_dir/$experiment/trace.pb",
|
||||
# "-i FullTraceImporter",
|
||||
# "-e $remote_builds_dir/$experiment/system.elf",
|
||||
# "-v $experiment",
|
||||
# )
|
||||
# );
|
||||
|
||||
# Import disassembly/sources
|
||||
my $import_ip_asm_command = join " ", (
|
||||
"$fail_import",
|
||||
"--database-option-file $remote_db_conf",
|
||||
"-t $remote_builds_dir/$experiment/trace.pb",
|
||||
"-i ElfImporter",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-v $experiment",
|
||||
"-b ip",
|
||||
"--objdump objdump",
|
||||
|
||||
# "--sources",
|
||||
">$remote_builds_dir/$experiment/2_import_ip_asm.log 2>&1"
|
||||
);
|
||||
say "Import IP Asm command: $import_ip_asm_command";
|
||||
system($import_ip_asm_command);
|
||||
|
||||
my $import_mem_asm_command = join " ", (
|
||||
"$fail_import",
|
||||
"--database-option-file $remote_db_conf",
|
||||
"-t $remote_builds_dir/$experiment/trace.pb",
|
||||
"-i ElfImporter",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-v $experiment",
|
||||
"-b mem",
|
||||
"--objdump objdump",
|
||||
|
||||
# "--sources",
|
||||
">$remote_builds_dir/$experiment/2_import_mem_asm.log 2>&1"
|
||||
);
|
||||
say "Import Mem Asm command: $import_mem_asm_command";
|
||||
system($import_mem_asm_command);
|
||||
|
||||
my $import_regs_asm_command = join " ", (
|
||||
"$fail_import",
|
||||
"--database-option-file $remote_db_conf",
|
||||
"-t $remote_builds_dir/$experiment/trace.pb",
|
||||
"-i ElfImporter",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-v $experiment",
|
||||
"-b regs",
|
||||
"--objdump objdump",
|
||||
|
||||
# "--sources",
|
||||
">$remote_builds_dir/$experiment/2_import_regs_asm.log 2>&1"
|
||||
);
|
||||
say "Import Regs Asm command: $import_regs_asm_command";
|
||||
system($import_regs_asm_command);
|
||||
|
||||
my $prune_command = join " ", (
|
||||
"$fail_prune", "--database-option-file $remote_db_conf",
|
||||
"-v $experiment", "-b %%",
|
||||
|
||||
# '-p NoPruner',
|
||||
'-p BasicPruner',
|
||||
"--overwrite", ">$remote_builds_dir/$experiment/2_prune.log 2>&1"
|
||||
);
|
||||
say "Prune command: $prune_command";
|
||||
system($prune_command);
|
||||
}
|
||||
|
||||
sub inject {
|
||||
my ($experiment) = @_;
|
||||
|
||||
my $count = Util::cpu_count();
|
||||
|
||||
Util::notify("Injecting $experiment using $count cores...");
|
||||
|
||||
my $server_command = join " ", (
|
||||
"$fail_server",
|
||||
|
||||
# "--port $fail_server_port",
|
||||
"--database-option-file $remote_db_conf", "-v $experiment",
|
||||
"-b %", "--inject-single-bit",
|
||||
"--inject-registers",
|
||||
">$remote_builds_dir/$experiment/3_server.log 2>&1"
|
||||
);
|
||||
say "Server command: $server_command";
|
||||
|
||||
# Read catch flags written by build.pl into the experiment directory
|
||||
my $runner_flags_file = "$remote_builds_dir/$experiment/runner_flags";
|
||||
my @catch_flags = ();
|
||||
if ( -e $runner_flags_file ) {
|
||||
open( my $rfh, '<', $runner_flags_file )
|
||||
or die "Cannot open $runner_flags_file: $!";
|
||||
@catch_flags = map { chomp; "-Wf,$_" } grep { /\S/ } <$rfh>;
|
||||
close($rfh);
|
||||
}
|
||||
|
||||
my $client_command = join " ", (
|
||||
"nice $bochs_runner",
|
||||
"-V $fail_share/vgabios.bin",
|
||||
"-b $fail_share/BIOS-bochs-latest",
|
||||
"-f $fail_inject",
|
||||
"-e $remote_builds_dir/$experiment/system.elf",
|
||||
"-i $remote_builds_dir/$experiment/system.iso",
|
||||
"-j $count",
|
||||
"--",
|
||||
|
||||
# "-Wf,--server-port=$fail_server_port",
|
||||
"-Wf,--state-dir=$remote_builds_dir/$experiment/state",
|
||||
"-Wf,--trap",
|
||||
|
||||
@catch_flags,
|
||||
|
||||
"-Wf,--timeout=500000",
|
||||
"-Wf,--ok-marker=fail_marker_positive",
|
||||
"-Wf,--fail-marker=fail_marker_negative",
|
||||
"-Wf,--detected-marker=fail_marker_detected",
|
||||
|
||||
# Called in WAMR exception handler (disable for C compilation target!)
|
||||
# "-Wf,--group1-marker=fail_marker_group1",
|
||||
|
||||
">/dev/null 2>&1"
|
||||
|
||||
# ">$remote_builds_dir/$experiment/4_client.log 2>&1"
|
||||
);
|
||||
say "Client command: $client_command";
|
||||
|
||||
say "Forking...";
|
||||
my $pid = fork();
|
||||
die "fork failed: $!" unless defined $pid;
|
||||
|
||||
if ( $pid == 0 ) {
|
||||
|
||||
# child -> server
|
||||
say "Running server in child process...";
|
||||
exec($server_command) == 0 or die "exec server failed: $!";
|
||||
}
|
||||
|
||||
# parent -> client
|
||||
say "Waiting for server...";
|
||||
sleep(10);
|
||||
|
||||
say "Running client with $count cores in parent process";
|
||||
system($client_command) == 0 or die "client failed: $?";
|
||||
|
||||
say "Killing server with pid $pid...";
|
||||
kill 'TERM', $pid;
|
||||
waitpid( $pid, 0 );
|
||||
}
|
||||
|
||||
sub results {
|
||||
my ($experiment) = @_;
|
||||
|
||||
my @queries =
|
||||
map { s/\.pm//gr } Util::find_files("$remote_root/scripts/Queries");
|
||||
my @configs = ( '', Filters::get_default_configs() );
|
||||
|
||||
for my $query (@queries) {
|
||||
for my $config (@configs) {
|
||||
Util::execute_query( $experiment, $query,
|
||||
$remote_db_conf, $remote_builds_dir, 1, $config );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Run single experiment passed as argument
|
||||
my $experiment = $ARGV[0] or die "Usage: runner.pl <experiment>\n";
|
||||
Util::rewrite_file( $remote_db_conf, "database=",
|
||||
"database=${db_prefix}_$experiment\n" );
|
||||
|
||||
say "Killing generic-experiment-server process if it's running...";
|
||||
system( "pkill", "-u", $db_user, "-f", "generic-experiment-server" );
|
||||
sleep(10);
|
||||
|
||||
trace($experiment);
|
||||
import_trace($experiment);
|
||||
inject($experiment);
|
||||
results($experiment);
|
||||
|
||||
Util::notify("Finished experiment $experiment");
|
||||
1
tacle-converter
Submodule
1
tacle-converter
Submodule
Submodule tacle-converter added at ff9c74cae5
20
targets/c-host/c_host.c
Normal file
20
targets/c-host/c_host.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#ifdef TARGET_LINUX
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
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) {}
|
||||
void print(const char *msg) { PRINT("[C] %s", msg); }
|
||||
|
||||
int wasm_module(void);
|
||||
|
||||
MAIN {
|
||||
int retval = wasm_module();
|
||||
PRINT_SUCCESS("wasm_module returned %d.\n", retval);
|
||||
RET(retval);
|
||||
}
|
||||
7
targets/grub.cfg
Normal file
7
targets/grub.cfg
Normal file
@ -0,0 +1,7 @@
|
||||
set timeout=0
|
||||
set default=0
|
||||
|
||||
menuentry "CoRedOS" {
|
||||
multiboot /boot/system.elf
|
||||
boot
|
||||
}
|
||||
79
targets/lib.h
Normal file
79
targets/lib.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef _include_fail_h
|
||||
#define _include_fail_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define INLINE __attribute__((always_inline)) inline
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
|
||||
#define EXPORT(fnct) __attribute__((export_name(fnct)))
|
||||
#define IMPORT(fnct) __attribute__((import_module("env"), import_name(fnct)))
|
||||
|
||||
#if !defined(TARGET_FAIL) && !defined(TARGET_LINUX_BAREMETAL) && \
|
||||
!defined(TARGET_LINUX)
|
||||
// Set to linux while editing to prevent lsp errors
|
||||
#define TARGET_LINUX
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_FAIL
|
||||
#define MAIN void os_main(void)
|
||||
#define PRINT(fmt, ...)
|
||||
#define PRINT_ERROR(fmt, ...)
|
||||
#define PRINT_SUCCESS(fmt, ...)
|
||||
#define HOST_PRINT(msg)
|
||||
#define RET(val) return
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_LINUX_BAREMETAL
|
||||
#define MAIN int main(int argc, char *argv[])
|
||||
#define PRINT(fmt, ...)
|
||||
#define PRINT_ERROR(fmt, ...)
|
||||
#define PRINT_SUCCESS(fmt, ...)
|
||||
#define HOST_PRINT(msg)
|
||||
#define RET(val) return
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_LINUX
|
||||
#define MAIN int main(int argc, char *argv[])
|
||||
#define PRINT(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||
#define PRINT_ERROR(fmt, ...) \
|
||||
fprintf(stderr, "[Error] "); \
|
||||
fprintf(stderr, fmt, ##__VA_ARGS__)
|
||||
#define PRINT_SUCCESS(fmt, ...) \
|
||||
fprintf(stdout, "[Success] "); \
|
||||
fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||
#define HOST_PRINT(msg) print(msg)
|
||||
#define RET(val) return val;
|
||||
#endif
|
||||
|
||||
typedef uint16_t enc_t;
|
||||
typedef uint8_t plain_t;
|
||||
typedef int8_t sign_t;
|
||||
|
||||
#define check(vc, A, B) (((vc - B) % A) == 0)
|
||||
#define encode(v, A, B) ((((plain_t)v) * ((sign_t)A)) + ((sign_t)B))
|
||||
#define decode(vc, A, B) ((vc - B) / A)
|
||||
#define equals(vc1, vc2, B1, B2) ((vc1 - vc2) == (B1 - B2))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Those functions are defined in the host program
|
||||
void NOINLINE IMPORT("fail_start_trace")
|
||||
fail_start_trace(void); // Mark start of injection
|
||||
void NOINLINE IMPORT("fail_stop_trace")
|
||||
fail_stop_trace(void); // Mark end of injection
|
||||
void NOINLINE IMPORT("fail_marker_positive")
|
||||
fail_marker_positive(void); // Everything ok
|
||||
void NOINLINE IMPORT("fail_marker_detected")
|
||||
fail_marker_detected(void); // Everything ok
|
||||
void NOINLINE IMPORT("fail_marker_negative")
|
||||
fail_marker_negative(void); // Invalid code
|
||||
void NOINLINE IMPORT("print") print(const char *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
199
targets/linker.ld
Normal file
199
targets/linker.ld
Normal file
@ -0,0 +1,199 @@
|
||||
/* Kernel entry function */
|
||||
ENTRY(_start)
|
||||
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/DISCARD/ : {
|
||||
*(".text.inlined*")
|
||||
*(.comment)
|
||||
*(.eh_frame)
|
||||
*(.note.gnu.build-id)
|
||||
}
|
||||
|
||||
/* Set kernel start address */
|
||||
. = 0x100000;
|
||||
|
||||
/* Code and readonly data */
|
||||
.text : {
|
||||
/* fill gaps with int3 opcode to detect invalid jumps */
|
||||
FILL(0xcc)
|
||||
|
||||
/* multiboot header */
|
||||
multiboot_header = .;
|
||||
KEEP (*(".rodata.multiboot"))
|
||||
|
||||
/* /\* fixed address for IRQ handlers *\/ */
|
||||
/* . = 0x1000; */
|
||||
|
||||
/* /\* start of interrupt handlers *\/ */
|
||||
/* _stext_irqs = .; */
|
||||
|
||||
/* /\* IRQ Handlers *\/ */
|
||||
/* KEEP (*(".text.irqhandlers*")) /\* ASM *\/ */
|
||||
/* KEEP (*(".text.irq_handler*")) /\* C *\/ */
|
||||
/* *(".text.isrs*") /\* C *\/ */
|
||||
/* *(".text.isr_*") /\* C *\/ */
|
||||
/* KEEP (*(".text.OSEKOS_ISR*")) */
|
||||
/* KEEP (*(".text.idt")) /\* ASM *\/ */
|
||||
|
||||
/* /\* sysenter handler *\/ */
|
||||
/* KEEP (*(".text.sysenter_syscall")) */
|
||||
|
||||
/* _etext_irqs = .; */
|
||||
/* . += 16; /\* padding after data, workaround for import-trace *\/ */
|
||||
|
||||
KEEP (*(".text.startup"))
|
||||
|
||||
/* place before .text, otherwise they'll be caught by the wildcard */
|
||||
|
||||
/* AOT binary array */
|
||||
_wamr_aot_start = .;
|
||||
*(".text.wamr_aot")
|
||||
_wamr_aot_end = .;
|
||||
|
||||
/* The mmap_space memory used by os_mmap in baremetal platform */
|
||||
_wamr_mmap_start = .;
|
||||
*(".text.wamr_mmap")
|
||||
_wamr_mmap_end = .;
|
||||
|
||||
/* The runtime memory pool used by Alloc_With_Usage */
|
||||
_wamr_runtime_pool_start = .;
|
||||
*(".text.wamr_runtime_pool")
|
||||
_wamr_runtime_pool_end = .;
|
||||
|
||||
/* The linear memory pool used by Alloc_With_Usage */
|
||||
_wamr_linear_pool_start = .;
|
||||
*(".text.wamr_linear_pool")
|
||||
_wamr_linear_pool_end = .;
|
||||
|
||||
/* The memory pool used by Alloc_With_Pool */
|
||||
_wamr_global_heap_start = .;
|
||||
*(".text.wamr_global_heap")
|
||||
_wamr_global_heap_end = .;
|
||||
|
||||
/*
|
||||
The libiwasm.a contains the following objects:
|
||||
|
||||
aot_intrinsic.c.obj
|
||||
aot_loader.c.obj
|
||||
aot_reloc_x86_32.c.obj
|
||||
aot_runtime.c.obj
|
||||
bh_assert.c.obj
|
||||
bh_bitmap.c.obj
|
||||
bh_common.c.obj
|
||||
bh_hashmap.c.obj
|
||||
bh_leb128.c.obj
|
||||
bh_list.c.obj
|
||||
bh_log.c.obj
|
||||
bh_queue.c.obj
|
||||
bh_vector.c.obj
|
||||
ems_alloc.c.obj
|
||||
ems_gc.c.obj
|
||||
ems_hmu.c.obj
|
||||
ems_kfc.c.obj
|
||||
invokeNative_ia32.s.obj
|
||||
libc_builtin_wrapper.c.obj
|
||||
mem_alloc.c.obj
|
||||
platform_init.c.obj
|
||||
runtime_timer.c.obj
|
||||
wasm_application.c.obj
|
||||
wasm_blocking_op.c.obj
|
||||
wasm_c_api.c.obj
|
||||
wasm_exec_env.c.obj
|
||||
wasm_interp_classic.c.obj
|
||||
wasm_loader.c.obj
|
||||
wasm_loader_common.c.obj
|
||||
wasm_memory.c.obj
|
||||
wasm_native.c.obj
|
||||
wasm_runtime.c.obj
|
||||
wasm_runtime_common.c.obj
|
||||
wasm_shared_memory.c.obj
|
||||
*/
|
||||
|
||||
/* Put the .text section from aot_runtime.c.obj from libiwasm.a here */
|
||||
_iwasm_aot_runtime_start = .;
|
||||
*aot_runtime.c.obj(.text .text.*)
|
||||
_iwasm_aot_runtime_end = .;
|
||||
|
||||
/* Put the utility library here */
|
||||
_iwasm_bh_start = .;
|
||||
*bh_*.c.obj(.text .text.*)
|
||||
_iwasm_bh_end = .;
|
||||
|
||||
/* Put the allocator here */
|
||||
_iwasm_mem_alloc_start = .;
|
||||
*mem_alloc.c.obj(.text .text.*)
|
||||
_iwasm_mem_alloc_end = .;
|
||||
|
||||
/* Put the baremetal platform here */
|
||||
_iwasm_platform_init_start = .;
|
||||
*platform_init.c.obj(.text .text.*)
|
||||
_iwasm_platform_init_end = .;
|
||||
|
||||
/* Put the exec_env here */
|
||||
_iwasm_exec_env_start = .;
|
||||
*wasm_exec_env.c.obj(.text .text.*)
|
||||
_iwasm_exec_env_end = .;
|
||||
|
||||
/* Put the classic interpreter here */
|
||||
_iwasm_interp_classic_start = .;
|
||||
*wasm_interp_classic.c.obj(.text .text.*)
|
||||
_iwasm_interp_classic_end = .;
|
||||
|
||||
/* Put the wasm memory here */
|
||||
_iwasm_memory_start = .;
|
||||
*wasm_memory.c.obj(.text .text.*)
|
||||
_iwasm_memory_end = .;
|
||||
|
||||
/* Put the wasm native here */
|
||||
_iwasm_native_start = .;
|
||||
*wasm_native.c.obj(.text .text.*)
|
||||
_iwasm_native_end = .;
|
||||
|
||||
/* Put the wasm runtime here */
|
||||
_iwasm_runtime_start = .;
|
||||
*wasm_runtime.c.obj(.text .text.*)
|
||||
*wasm_runtime_common.c.obj(.text .text.*)
|
||||
_iwasm_runtime_end = .;
|
||||
|
||||
_text_start = .;
|
||||
*(".text*")
|
||||
_text_end = .;
|
||||
|
||||
*(".rodata*")
|
||||
}
|
||||
|
||||
/* Data and Stacks */
|
||||
/* NOTE: When including the WAMR mmap region inside .text, it has to be large */
|
||||
/* . = 0x200000; */
|
||||
. = ALIGN(4096);
|
||||
.data : {
|
||||
KEEP (*(".startup_stack"))
|
||||
KEEP (*(".kernel_stack"))
|
||||
*(".data*")
|
||||
}
|
||||
|
||||
/* Uninitialized data */
|
||||
.bss : {
|
||||
_sbss = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
}
|
||||
|
||||
/* Align and mark end of all sections — heap starts here */
|
||||
. = ALIGN(4096);
|
||||
_end = .;
|
||||
|
||||
/* Memory-mapped I/O APIC */
|
||||
_sioapic = 0xFEC00000;
|
||||
ioapic = 0xFEC00000;
|
||||
_eioapic = 0xFEC00FFF;
|
||||
|
||||
/* Memory-mapped Local APIC */
|
||||
_slapic = 0xFEE00000;
|
||||
lapic = 0xFEE00000;
|
||||
_elapic = 0xFEE00FFF;
|
||||
}
|
||||
61
targets/startup.s
Normal file
61
targets/startup.s
Normal file
@ -0,0 +1,61 @@
|
||||
## Bare bone boot.s from wiki.osdev.org
|
||||
|
||||
# multiboot header
|
||||
.section .rodata.multiboot
|
||||
.align 4
|
||||
|
||||
# magic number
|
||||
.long 0x1BADB002
|
||||
|
||||
# flags: align, meminfo
|
||||
.long 0x3
|
||||
|
||||
# checksum: -(magic+flags)
|
||||
.long -(0x1BADB002 + 0x3)
|
||||
|
||||
# the initial kernel stack
|
||||
.section .kernel_stack
|
||||
.global os_stack
|
||||
.size os_stack, 4096
|
||||
|
||||
#.Lstack_bottom:
|
||||
os_stack:
|
||||
.byte 0
|
||||
.skip 65565 # 64 KiB
|
||||
# .skip 16384 # 16 KiB
|
||||
# .skip 4094 # 4 KiB
|
||||
.byte 0
|
||||
.Lstack_top:
|
||||
|
||||
|
||||
# The linker script specifies _start as the entry point to the kernel and the
|
||||
# bootloader will jump to this position once the kernel has been loaded. It
|
||||
# doesn't make sense to return from this function as the bootloader is gone.
|
||||
.section .text.startup
|
||||
.global _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
# Welcome to kernel mode!
|
||||
# To set up a stack, we simply set the esp register to point to the top of
|
||||
# our stack (as it grows downwards).
|
||||
movl $.Lstack_top, %esp
|
||||
# We are now ready to actually execute C code. (see ./startup.cc)
|
||||
call os_main
|
||||
|
||||
# In case the function returns, we'll want to put the computer into an
|
||||
# infinite loop. To do that, we use the clear interrupt ('cli') instruction
|
||||
# to disable interrupts, the halt instruction ('hlt') to stop the CPU until
|
||||
# the next interrupt arrives, and jumping to the halt instruction if it ever
|
||||
# continues execution, just to be safe. We will create a local label rather
|
||||
# than real symbol and jump to there endlessly.
|
||||
cli
|
||||
hlt
|
||||
.Lhang:
|
||||
jmp .Lhang
|
||||
|
||||
# Set the size of the _start symbol to the current location '.' minus its start.
|
||||
# This is useful when debugging or when you implement call tracing.
|
||||
|
||||
# If this is enabled, the linker.ld needs to define a symbol before the .text segment.
|
||||
# Otherwise, there's a gap that prevents FAIL from disassembling the AOT.
|
||||
# .size _start, . - _start
|
||||
35
targets/syscalls.c
Normal file
35
targets/syscalls.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
extern char _end; /* provided by linker script */
|
||||
static char *heap_ptr = &_end;
|
||||
|
||||
void *sbrk(int incr) {
|
||||
char *prev = heap_ptr;
|
||||
heap_ptr += incr;
|
||||
return prev;
|
||||
}
|
||||
|
||||
int write(int fd, const char *buf, int len) { return len; }
|
||||
|
||||
int read(int fd, char *buf, int len) { return 0; }
|
||||
int close(int fd) { return -1; }
|
||||
int fstat(int fd, struct stat *st) {
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
int isatty(int fd) { return 1; }
|
||||
int lseek(int fd, int offset, int whence) { return 0; }
|
||||
void _exit(int status) {
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
void exit(int status) {
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
int kill(int pid, int sig) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
int getpid(void) { return 1; }
|
||||
237
targets/wasm-host/wasm_host.c
Normal file
237
targets/wasm-host/wasm_host.c
Normal file
@ -0,0 +1,237 @@
|
||||
#include "../lib.h"
|
||||
#include "../wasm_export.h"
|
||||
#include "bh_platform.h"
|
||||
|
||||
#include "__WASM_ARRAY_FILE__"
|
||||
#ifdef TARGET_LINUX
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
// FAIL* instrumentation 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 will be called from WASM
|
||||
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();
|
||||
}
|
||||
void host_print(wasm_exec_env_t exec_env, const char *msg) {
|
||||
PRINT("[WASM] %s", msg);
|
||||
}
|
||||
|
||||
#define STACK_SIZE (4 * 1024)
|
||||
#define HEAP_SIZE STACK_SIZE
|
||||
|
||||
#if WASM_MEM_ALLOC_WITH_USAGE
|
||||
|
||||
// Another bump allocator
|
||||
#define WASM_LINEAR_MEMORY_SIZE (64 * 1024) // Need to match --initial-memory?
|
||||
#define RUNTIME_POOL_SIZE (2 * 1024 * 1024)
|
||||
#define LINEAR_POOL_SIZE (WASM_LINEAR_MEMORY_SIZE + 512 * 1024)
|
||||
#define ALIGNMENT 8
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
} BumpPool;
|
||||
|
||||
#if WAMR_RUNTIME_POOL_IN_TEXT
|
||||
__attribute__((section(".text.wamr_runtime_pool"), aligned(4096)))
|
||||
#endif
|
||||
static char runtime_pool_buf[RUNTIME_POOL_SIZE];
|
||||
|
||||
#if WAMR_LINEAR_POOL_IN_TEXT
|
||||
__attribute__((section(".text.wamr_linear_pool"), aligned(4096)))
|
||||
#endif
|
||||
static char linear_pool_buf[LINEAR_POOL_SIZE];
|
||||
|
||||
// mem_alloc_usage_t: 0 = Alloc_For_Runtime, 1 = Alloc_For_LinearMemory
|
||||
static BumpPool pools[] = {
|
||||
{ runtime_pool_buf, RUNTIME_POOL_SIZE, 0 },
|
||||
{ linear_pool_buf, LINEAR_POOL_SIZE, 0 },
|
||||
};
|
||||
|
||||
static size_t align_up(size_t x, size_t a) {
|
||||
return (x + a - 1) & ~(a - 1);
|
||||
}
|
||||
|
||||
static size_t alloc_size(void *ptr) {
|
||||
size_t header_size = align_up(sizeof(size_t), ALIGNMENT);
|
||||
return *(size_t *)((char *)ptr - header_size);
|
||||
}
|
||||
|
||||
static void *bump_alloc(BumpPool *pool, unsigned int size) {
|
||||
size_t header_size = align_up(sizeof(size_t), ALIGNMENT);
|
||||
size_t start = align_up(pool->offset, ALIGNMENT);
|
||||
size_t end = start + header_size + align_up(size, ALIGNMENT);
|
||||
|
||||
if (end > pool->size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*(size_t *)&pool->buf[start] = size;
|
||||
void *ptr = &pool->buf[start + header_size];
|
||||
pool->offset = end;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *wamr_malloc(mem_alloc_usage_t usage, unsigned int size) {
|
||||
PRINT("wamr_malloc: usage=%d size=%u\n", usage, size);
|
||||
return bump_alloc(&pools[usage], size);
|
||||
}
|
||||
|
||||
void *wamr_realloc(mem_alloc_usage_t usage, bool full_size_mmaped, void *ptr,
|
||||
unsigned int new_size) {
|
||||
PRINT("wamr_realloc: usage=%d full_size_mmaped=%d ptr=%p new_size=%u\n",
|
||||
usage, full_size_mmaped, ptr, new_size);
|
||||
|
||||
void *new_addr = bump_alloc(&pools[usage], new_size);
|
||||
if (!new_addr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
size_t old_size = alloc_size(ptr);
|
||||
memcpy(new_addr, ptr, old_size < new_size ? old_size : new_size);
|
||||
}
|
||||
|
||||
return new_addr;
|
||||
}
|
||||
|
||||
void wamr_free(mem_alloc_usage_t usage, void *ptr) {
|
||||
// PRINT("wamr_free: usage=%d ptr=%p\n", usage, ptr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define RUNTIME_POOL_SIZE (4 * STACK_SIZE)
|
||||
|
||||
#if WAMR_GLOBAL_HEAP_IN_TEXT
|
||||
__attribute__((section(".text.wamr_global_heap"), aligned(4096)))
|
||||
#endif
|
||||
static char global_heap_buf[RUNTIME_POOL_SIZE];
|
||||
|
||||
#endif // WASM_MEM_ALLOC_WITH_USAGE
|
||||
|
||||
MAIN {
|
||||
char error_buf[128];
|
||||
|
||||
// Step 1: Initialize WAMR Runtime
|
||||
static RuntimeInitArgs init_args;
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
#if WASM_MEM_ALLOC_WITH_USAGE
|
||||
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;
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
|
||||
init_args.max_thread_num = 1;
|
||||
if (!wasm_runtime_full_init(&init_args)) {
|
||||
PRINT_ERROR("wasm_runtime_full_init failed.\n");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Step 2: Export Native Symbols
|
||||
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},
|
||||
{"print", (void *)host_print, "(*)", NULL},
|
||||
};
|
||||
int count = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
if (!wasm_runtime_register_natives("env", native_symbols, count)) {
|
||||
PRINT_ERROR("wasm_runtime_register_natives failed.\n");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Step 3: Parse and Validate Module
|
||||
wasm_module_t module = wasm_runtime_load(__WASM_ARRAY__, __WASM_ARRAY_LEN__,
|
||||
error_buf, sizeof(error_buf));
|
||||
if (!module) {
|
||||
PRINT_ERROR("wasm_runtime_load failed with \"%s\".\n", error_buf);
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Step 4: Instantiate Module
|
||||
wasm_module_inst_t module_inst = wasm_runtime_instantiate(
|
||||
module, STACK_SIZE, HEAP_SIZE, error_buf, sizeof(error_buf));
|
||||
if (!module_inst) {
|
||||
PRINT_ERROR("wasm_runtime_instantiate failed with \"%s\".\n", error_buf);
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Step 5: Create Execution Environment
|
||||
wasm_exec_env_t exec_env =
|
||||
wasm_runtime_create_exec_env(module_inst, STACK_SIZE);
|
||||
if (!exec_env) {
|
||||
PRINT_ERROR("wasm_runtime_create_exec_env failed.\n");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Step 6: Find and Call Exported Function
|
||||
wasm_function_inst_t func =
|
||||
wasm_runtime_lookup_function(module_inst, "wasm_module");
|
||||
if (!func) {
|
||||
PRINT_ERROR("wasm_runtime_lookup_function failed.\n");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// In case wasm_module accepts arguments, set them here
|
||||
uint32_t args[1];
|
||||
|
||||
if (!wasm_runtime_call_wasm(exec_env, func, 0, args)) {
|
||||
const char *exception = wasm_runtime_get_exception(module_inst);
|
||||
PRINT_ERROR("wasm_runtime_call_wasm failed with \"%s\".\n",
|
||||
exception ? exception : "unknown");
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
PRINT_SUCCESS("wasm function execution finished.\n");
|
||||
|
||||
// In case wasm_module returns a value we can do sth with it
|
||||
uint32_t retval = args[0];
|
||||
|
||||
success_cleanup:
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
wasm_runtime_unload(module);
|
||||
wasm_runtime_destroy();
|
||||
|
||||
RET(0);
|
||||
|
||||
error_cleanup:
|
||||
if (exec_env) {
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
}
|
||||
if (module_inst) {
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
}
|
||||
if (module) {
|
||||
wasm_runtime_unload(module);
|
||||
}
|
||||
wasm_runtime_destroy();
|
||||
|
||||
RET(1);
|
||||
}
|
||||
63
targets/wasm-module/matrix0.cpp
Normal file
63
targets/wasm-module/matrix0.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#define REPLICA_COUNT 1
|
||||
#define MAT_SIZE 3
|
||||
|
||||
static uint32_t X[MAT_SIZE * MAT_SIZE] = {
|
||||
0, 1, 2, //
|
||||
3, 4, 5, //
|
||||
6, 7, 8 //
|
||||
};
|
||||
static uint32_t Y[MAT_SIZE * MAT_SIZE] = {
|
||||
8, 7, 6, //
|
||||
5, 4, 3, //
|
||||
2, 1, 0 //
|
||||
};
|
||||
static uint32_t Calculated[MAT_SIZE * MAT_SIZE] = {0};
|
||||
|
||||
static INLINE uint32_t *idx(uint32_t *matrix, uint8_t x, uint8_t y) {
|
||||
return &matrix[y * MAT_SIZE + x];
|
||||
}
|
||||
|
||||
template <const unsigned int N> static INLINE void matrix(void) {
|
||||
for (uint8_t y = 0; y < MAT_SIZE; ++y) {
|
||||
for (uint8_t x = 0; x < MAT_SIZE; ++x) {
|
||||
for (uint8_t k = 0; k < MAT_SIZE; ++k) {
|
||||
*idx(Calculated, x, y) += (*idx(X, k, y)) * (*idx(Y, x, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int cmp(uint32_t *A, uint32_t *B) {
|
||||
for (uint8_t i = 0; i < MAT_SIZE * MAT_SIZE; ++i) {
|
||||
if (A[i] != B[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
fail_start_trace();
|
||||
|
||||
matrix<0>();
|
||||
|
||||
fail_stop_trace();
|
||||
|
||||
uint32_t Expected[MAT_SIZE * MAT_SIZE] = {
|
||||
9, 6, 3, //
|
||||
54, 42, 30, //
|
||||
99, 78, 57 //
|
||||
};
|
||||
|
||||
if (cmp(Calculated, Expected)) {
|
||||
HOST_PRINT("result correct.\n");
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
HOST_PRINT("result incorrect.\n");
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
36
targets/wasm-module/sum0.cpp
Normal file
36
targets/wasm-module/sum0.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#define REPLICA_COUNT 1
|
||||
|
||||
static plain_t sum_out[REPLICA_COUNT];
|
||||
|
||||
#define X sum_out[0]
|
||||
|
||||
template <const unsigned int N> static INLINE void sum(void) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
sum += 1;
|
||||
}
|
||||
|
||||
sum_out[N] = sum;
|
||||
}
|
||||
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
X = 0;
|
||||
|
||||
fail_start_trace();
|
||||
|
||||
sum<0>();
|
||||
|
||||
fail_stop_trace();
|
||||
|
||||
if (X == 5) {
|
||||
HOST_PRINT("result correct.\n");
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
HOST_PRINT("result incorrect.\n");
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
61
targets/wasm-module/sum1-voter.cpp
Normal file
61
targets/wasm-module/sum1-voter.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#define REPLICA_COUNT 3
|
||||
|
||||
static plain_t vote_res;
|
||||
static plain_t sum_out[REPLICA_COUNT];
|
||||
|
||||
#define XC sum_out[0]
|
||||
#define YC sum_out[1]
|
||||
#define ZC sum_out[2]
|
||||
|
||||
// The prints here can't happen because they're disabled under test ¯\_(ツ)_/¯
|
||||
|
||||
static void naive_vote(void) {
|
||||
if (XC == YC || XC == ZC) {
|
||||
vote_res = XC;
|
||||
} else if (YC == ZC) {
|
||||
vote_res = YC;
|
||||
} else {
|
||||
HOST_PRINT("all replicas differ.\n");
|
||||
fail_marker_detected();
|
||||
}
|
||||
}
|
||||
|
||||
template <const unsigned int N> static INLINE void sum(void) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
sum += 1;
|
||||
}
|
||||
|
||||
sum_out[N] = sum;
|
||||
}
|
||||
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
XC = 0;
|
||||
YC = 0;
|
||||
ZC = 0;
|
||||
|
||||
// "early" starts trace here
|
||||
|
||||
sum<0>();
|
||||
sum<1>();
|
||||
sum<2>();
|
||||
|
||||
// "late" starts trace here
|
||||
fail_start_trace();
|
||||
|
||||
naive_vote();
|
||||
|
||||
fail_stop_trace();
|
||||
|
||||
if (vote_res == 5) {
|
||||
HOST_PRINT("vote success.\n");
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
HOST_PRINT("undetected error.\n");
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
120
targets/wasm-module/sum2-cored.cpp
Normal file
120
targets/wasm-module/sum2-cored.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#define THE_A 110
|
||||
|
||||
// CONSTANT Replica results signatures
|
||||
#define SIG_X 32
|
||||
#define SIG_Y 23
|
||||
#define SIG_Z 67
|
||||
#define SIG_MAX SIG_Z
|
||||
|
||||
// CONSTANT Voter Result Signatures
|
||||
#define SIG_s_XYZ ((SIG_X - SIG_Y) + (SIG_X - SIG_Z))
|
||||
#define SIG_s_XY (SIG_X - SIG_Y)
|
||||
#define SIG_s_YZ (SIG_Y - SIG_Z)
|
||||
#define SIG_s_XZ (SIG_X - SIG_Z)
|
||||
|
||||
#define REPLICA_COUNT 3
|
||||
|
||||
static enc_t cored_res;
|
||||
static enc_t sum_out[REPLICA_COUNT];
|
||||
|
||||
#define XC sum_out[0]
|
||||
#define YC sum_out[1]
|
||||
#define ZC sum_out[2]
|
||||
|
||||
// The prints here can't happen because they're disabled under test ¯\_(ツ)_/¯
|
||||
|
||||
static INLINE enc_t apply(enc_t vc, sign_t bdyn) {
|
||||
if (bdyn > SIG_MAX) {
|
||||
HOST_PRINT("signature overflow.\n");
|
||||
fail_marker_detected();
|
||||
}
|
||||
return vc + bdyn;
|
||||
}
|
||||
|
||||
static sign_t cored_vote(void) {
|
||||
if (equals(XC, YC, SIG_X, SIG_Y)) {
|
||||
if (equals(XC, ZC, SIG_X, SIG_Z)) {
|
||||
cored_res = apply(XC, (XC - YC) + (XC - ZC));
|
||||
return SIG_s_XYZ;
|
||||
} else {
|
||||
cored_res = apply(XC, (XC - YC));
|
||||
return SIG_s_XY;
|
||||
}
|
||||
} else if (equals(YC, ZC, SIG_Y, SIG_Z)) {
|
||||
cored_res = apply(YC, (YC - ZC));
|
||||
return SIG_s_YZ;
|
||||
} else if (equals(XC, ZC, SIG_X, SIG_Z)) {
|
||||
cored_res = apply(XC, (XC - ZC));
|
||||
return SIG_s_XZ;
|
||||
} else {
|
||||
HOST_PRINT("all replicas differ.\n");
|
||||
fail_marker_detected();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <const unsigned int N, const sign_t S> static INLINE void sum(void) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
sum += 1;
|
||||
}
|
||||
|
||||
sum_out[N] = encode(sum, THE_A, S);
|
||||
}
|
||||
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
XC = 0;
|
||||
YC = 0;
|
||||
ZC = 0;
|
||||
|
||||
// "early" starts trace here
|
||||
|
||||
sum<0, SIG_X>();
|
||||
sum<1, SIG_Y>();
|
||||
sum<2, SIG_Z>();
|
||||
|
||||
// "late" starts trace here
|
||||
fail_start_trace();
|
||||
|
||||
sign_t static_sig = cored_vote();
|
||||
|
||||
fail_stop_trace();
|
||||
|
||||
sign_t vote_result_sig;
|
||||
switch (static_sig) {
|
||||
case SIG_s_XYZ:
|
||||
case SIG_s_XY:
|
||||
case SIG_s_XZ:
|
||||
vote_result_sig = SIG_X;
|
||||
break;
|
||||
case SIG_s_YZ:
|
||||
vote_result_sig = SIG_Y;
|
||||
break;
|
||||
default:
|
||||
HOST_PRINT("unknown static_sig.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Inversely apply constant program flow signature.
|
||||
cored_res -= static_sig;
|
||||
|
||||
/* Validate Vote result */
|
||||
if (!check(cored_res, THE_A, vote_result_sig)) {
|
||||
HOST_PRINT("voted result invalid.\n");
|
||||
fail_marker_detected();
|
||||
return 2;
|
||||
}
|
||||
|
||||
plain_t res = decode(cored_res, THE_A, vote_result_sig);
|
||||
if (res == 5) {
|
||||
HOST_PRINT("cored success.\n");
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
HOST_PRINT("undetected error.\n");
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
61
targets/wasm-module/sum3-repl-voter.cpp
Normal file
61
targets/wasm-module/sum3-repl-voter.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#define REPLICA_COUNT 3
|
||||
|
||||
static plain_t vote_res;
|
||||
static plain_t sum_out[REPLICA_COUNT];
|
||||
|
||||
#define XC sum_out[0]
|
||||
#define YC sum_out[1]
|
||||
#define ZC sum_out[2]
|
||||
|
||||
// The prints here can't happen because they're disabled under test ¯\_(ツ)_/¯
|
||||
|
||||
static void naive_vote(void) {
|
||||
if (XC == YC || XC == ZC) {
|
||||
vote_res = XC;
|
||||
} else if (YC == ZC) {
|
||||
vote_res = YC;
|
||||
} else {
|
||||
HOST_PRINT("all replicas differ.\n");
|
||||
fail_marker_detected();
|
||||
}
|
||||
}
|
||||
|
||||
template <const unsigned int N> static INLINE void sum(void) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
sum += 1;
|
||||
}
|
||||
|
||||
sum_out[N] = sum;
|
||||
}
|
||||
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
XC = 0;
|
||||
YC = 0;
|
||||
ZC = 0;
|
||||
|
||||
// "early" starts trace here
|
||||
fail_start_trace();
|
||||
|
||||
sum<0>();
|
||||
sum<1>();
|
||||
sum<2>();
|
||||
|
||||
// "late" starts trace here
|
||||
|
||||
naive_vote();
|
||||
|
||||
fail_stop_trace();
|
||||
|
||||
if (vote_res == 5) {
|
||||
HOST_PRINT("vote success.\n");
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
HOST_PRINT("undetected error.\n");
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
120
targets/wasm-module/sum4-repl-cored.cpp
Normal file
120
targets/wasm-module/sum4-repl-cored.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "../lib.h"
|
||||
|
||||
#define THE_A 110
|
||||
|
||||
// CONSTANT Replica results signatures
|
||||
#define SIG_X 32
|
||||
#define SIG_Y 23
|
||||
#define SIG_Z 67
|
||||
#define SIG_MAX SIG_Z
|
||||
|
||||
// CONSTANT Voter Result Signatures
|
||||
#define SIG_s_XYZ ((SIG_X - SIG_Y) + (SIG_X - SIG_Z))
|
||||
#define SIG_s_XY (SIG_X - SIG_Y)
|
||||
#define SIG_s_YZ (SIG_Y - SIG_Z)
|
||||
#define SIG_s_XZ (SIG_X - SIG_Z)
|
||||
|
||||
#define REPLICA_COUNT 3
|
||||
|
||||
static enc_t cored_res;
|
||||
static enc_t sum_out[REPLICA_COUNT];
|
||||
|
||||
#define XC sum_out[0]
|
||||
#define YC sum_out[1]
|
||||
#define ZC sum_out[2]
|
||||
|
||||
// The prints here can't happen because they're disabled under test ¯\_(ツ)_/¯
|
||||
|
||||
static INLINE enc_t apply(enc_t vc, sign_t bdyn) {
|
||||
if (bdyn > SIG_MAX) {
|
||||
HOST_PRINT("signature overflow.\n");
|
||||
fail_marker_detected();
|
||||
}
|
||||
return vc + bdyn;
|
||||
}
|
||||
|
||||
static sign_t cored_vote(void) {
|
||||
if (equals(XC, YC, SIG_X, SIG_Y)) {
|
||||
if (equals(XC, ZC, SIG_X, SIG_Z)) {
|
||||
cored_res = apply(XC, (XC - YC) + (XC - ZC));
|
||||
return SIG_s_XYZ;
|
||||
} else {
|
||||
cored_res = apply(XC, (XC - YC));
|
||||
return SIG_s_XY;
|
||||
}
|
||||
} else if (equals(YC, ZC, SIG_Y, SIG_Z)) {
|
||||
cored_res = apply(YC, (YC - ZC));
|
||||
return SIG_s_YZ;
|
||||
} else if (equals(XC, ZC, SIG_X, SIG_Z)) {
|
||||
cored_res = apply(XC, (XC - ZC));
|
||||
return SIG_s_XZ;
|
||||
} else {
|
||||
HOST_PRINT("all replicas differ.\n");
|
||||
fail_marker_detected();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <const unsigned int N, const sign_t S> static INLINE void sum(void) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
sum += 1;
|
||||
}
|
||||
|
||||
sum_out[N] = encode(sum, THE_A, S);
|
||||
}
|
||||
|
||||
extern "C" EXPORT("wasm_module") int wasm_module(void) {
|
||||
XC = 0;
|
||||
YC = 0;
|
||||
ZC = 0;
|
||||
|
||||
// "early" starts trace here
|
||||
fail_start_trace();
|
||||
|
||||
sum<0, SIG_X>();
|
||||
sum<1, SIG_Y>();
|
||||
sum<2, SIG_Z>();
|
||||
|
||||
// "late" starts trace here
|
||||
|
||||
sign_t static_sig = cored_vote();
|
||||
|
||||
fail_stop_trace();
|
||||
|
||||
sign_t vote_result_sig;
|
||||
switch (static_sig) {
|
||||
case SIG_s_XYZ:
|
||||
case SIG_s_XY:
|
||||
case SIG_s_XZ:
|
||||
vote_result_sig = SIG_X;
|
||||
break;
|
||||
case SIG_s_YZ:
|
||||
vote_result_sig = SIG_Y;
|
||||
break;
|
||||
default:
|
||||
HOST_PRINT("unknown static_sig.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Inversely apply constant program flow signature.
|
||||
cored_res -= static_sig;
|
||||
|
||||
/* Validate Vote result */
|
||||
if (!check(cored_res, THE_A, vote_result_sig)) {
|
||||
HOST_PRINT("voted result invalid.\n");
|
||||
fail_marker_detected();
|
||||
return 2;
|
||||
}
|
||||
|
||||
plain_t res = decode(cored_res, THE_A, vote_result_sig);
|
||||
if (res == 5) {
|
||||
HOST_PRINT("cored success.\n");
|
||||
fail_marker_positive();
|
||||
return 0;
|
||||
} else {
|
||||
HOST_PRINT("undetected error.\n");
|
||||
fail_marker_negative();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
27
targets/wasm-tacle/app/lift/CMakeLists.txt
Normal file
27
targets/wasm-tacle/app/lift/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
# ~~~
|
||||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
|
||||
# ~~~
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(lift)
|
||||
|
||||
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
|
||||
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
|
||||
|
||||
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
|
||||
|
||||
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
|
||||
set(APP_SOURCE_FILE_PATH
|
||||
"generated/modified_sources/inline/lift.c")
|
||||
else()
|
||||
set(APP_SOURCE_FILE_PATH
|
||||
"generated/modified_sources/default/lift.c"
|
||||
"generated/modified_sources/default/liftlibcontrol.c"
|
||||
"generated/modified_sources/default/liftlibio.c")
|
||||
endif()
|
||||
|
||||
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)
|
||||
|
||||
|
||||
31
targets/wasm-tacle/app/lift/README
Executable file
31
targets/wasm-tacle/app/lift/README
Executable file
@ -0,0 +1,31 @@
|
||||
Lift Controller
|
||||
===============
|
||||
|
||||
This is a port of Martin Schoeberl's Lift Controller [1] to C. The orignal
|
||||
version is an embedded Java program that controls a lift in a factory in Turkey.
|
||||
Benedikt Huber has ported the controller to C and Lucid [3]. It has been used in
|
||||
various research projects, including T-CREST[3] and the F-Shell test generator
|
||||
[4].
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The sensors of the system consist of several buttons, a load sensor (to detect
|
||||
if the lift is positioned at the load), sensors to detect bottom and top
|
||||
position, and an index sensor for the motor. The motor is controlled using two
|
||||
digital outputs, one for its direction and one to turn it off or on.
|
||||
|
||||
The controller itself consists of an initialization routine ctrl_init(), the
|
||||
controller step ctrl_loop(), which should be invoked every 10ms. Outside a test
|
||||
environment, ctrl_get_vals() should be called to read sensors before the
|
||||
controller runs, and ctrl_set_vals() should be called to set actuators after the
|
||||
controller ran.
|
||||
|
||||
The digital IO interface (9 digital inputs, 2 digital outputs and 14 LEDs are
|
||||
used) is realized as global volatile variables (simio_in, simio_out, simio_led),
|
||||
that can be modified and read by test drivers or by the runtime environment.
|
||||
|
||||
[1] http://www.jopdesign.com/doc/jembench.pdf
|
||||
[2] https://github.com/visq/99lifts
|
||||
[3] http://www.t-crest.org
|
||||
[4] http://forsyte.at/software/fshell/
|
||||
46
targets/wasm-tacle/app/lift/changeLog.txt
Executable file
46
targets/wasm-tacle/app/lift/changeLog.txt
Executable file
@ -0,0 +1,46 @@
|
||||
File: duff.c
|
||||
Original provenience: Lift Controller, see README file
|
||||
|
||||
|
||||
2015-12-21:
|
||||
- replaced defines, introduced 4 enums to replace #define statements
|
||||
(enum Direction, Sensor, Motor, Command)
|
||||
- renamed libs to fit general naming scheme: lift_io -> liftio
|
||||
- benchmark consisted of two benchmarks, test_lift and run_lift,
|
||||
only run_lift remains, i.e., test_lift.data.c/h and test_lift.c removed.
|
||||
- Makefile removed, file can now be compiled using 'gcc lift.c'
|
||||
- 'uint16_t' replaced by 'unsigned short int' to get rid of 'stdint.h;
|
||||
- changed LEVEL_POS_LENGTH from 14 to 16 (16 values were initialized).
|
||||
- added an additional global variable 'int checksum'
|
||||
- added function pre-fix 'lift_' to each function
|
||||
- added function int lift_return() returning the checksum and lift_init()
|
||||
- global variable checksum filled in function 'lift_ctrl_set_vals()'
|
||||
and initialized to 0 in 'lift_init()'
|
||||
- Added forward declarations of all functions before the declarations of global
|
||||
variables
|
||||
- in function lift_main, explicit initialization 'int i = 0' added.
|
||||
- Re-ordered functions to fit template-order
|
||||
- Applied code formatting according to the following rules
|
||||
(incomplete, to be discussed; I basically used astyle with the attached
|
||||
options file):
|
||||
- Lines shall not be wider than 80 characters; whenever possible, appropriate
|
||||
line breaks shall be inserted to keep lines below 80 characters
|
||||
- Indentation is done using whitespaces only, no tabs. Code is indented by
|
||||
two whitespaces
|
||||
- Two empty lines are put between any two functions
|
||||
- In non-empty lists or index expressions, opening '(' and '[' are followed by
|
||||
one whitespace, closing ')' and ']' are preceded by one whitespace
|
||||
- In comma- or colon-separated argument lists, one whitespace is put after
|
||||
each comma/colon
|
||||
- Names of functions and global variables all start with a benchmark-specific
|
||||
prefix (here: st_) followed by lowercase letter (e.g., st_square)
|
||||
- For pointer types, one whitespace is put before the '*'
|
||||
- Operators within expressions shall be preceded and followed by one
|
||||
whitespace
|
||||
- Code of then- and else-parts of if-then-else statements shall be put in
|
||||
separate lines, not in the same lines as the if-condition or the keyword
|
||||
"else"
|
||||
- Opening braces '{' denoting the beginning of code for some if-else or loop
|
||||
body shall be put at the end of the same line where the keywords "if",
|
||||
"else", "for", "while" etc. occur
|
||||
- Added general TACLeBench header to beginning of source code
|
||||
BIN
targets/wasm-tacle/app/lift/generated/default/lift.wasm
Executable file
BIN
targets/wasm-tacle/app/lift/generated/default/lift.wasm
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user