Ensure a crashing FDE still generates other FDEs

This commit is contained in:
Théophile Bastian 2019-03-27 16:35:54 +01:00
parent d7c1aaa6b5
commit 719fa27f99
5 changed files with 131 additions and 13 deletions

View file

@ -1,7 +1,9 @@
open Std
let main outfile proj =
let pre_dwarf = Simplest.of_proj proj in
let pre_dwarf = proj
|> Simplest.of_proj
|> Simplest.clean_lost_track_subs in
Format.printf "%a" Frontend.pp_pre_dwarf_readelf pre_dwarf;
let pre_c_dwarf = PreCBinding.convert_pre_c pre_dwarf in
let fd = open_out_bin outfile in

View file

@ -1,6 +1,8 @@
open Simplest
open Std
exception InvalidPreDwarf of string
type pre_c_pre_dwarf_entry = {
location: int64;
cfa_offset: int64;
@ -58,7 +60,9 @@ let convert_pre_c_entry loc entry : pre_c_pre_dwarf_entry =
let offset, offset_reg = (match entry with
| RspOffset off -> off, 7
| RbpOffset off -> off, 6
| CfaLostTrack -> assert false (* Should be filtered out beforehand *)
| CfaLostTrack ->
raise (InvalidPreDwarf
("CfaLostTrack should be filtered out beforehand"))
) in
{
location = loc;
@ -72,22 +76,33 @@ let convert_pre_c_entries entries : pre_c_pre_dwarf_entry array =
(fun loc entry _ -> convert_pre_c_entry loc entry)
entries empty_entry
let convert_pre_c_fde name entry id : pre_c_pre_dwarf_fde =
{
num = AddrMap.cardinal entry.cfa_changes_fde;
initial_location = entry.beg_pos;
end_location = entry.end_pos;
name = name;
entries = convert_pre_c_entries entry.cfa_changes_fde
}
let convert_pre_c_fde name entry : pre_c_pre_dwarf_fde option =
try
Some {
num = AddrMap.cardinal entry.cfa_changes_fde;
initial_location = entry.beg_pos;
end_location = entry.end_pos;
name = name;
entries = convert_pre_c_entries entry.cfa_changes_fde
}
with InvalidPreDwarf reason -> (
Format.eprintf "FAILED subroutine %s: %s@." name reason ;
None
)
module StrMapTool = MapTool(StrMap)
let convert_pre_c (cfa_map: subroutine_cfa_map) : pre_c_pre_dwarf =
(** Converts a `subroutine_cfa_map` to a `pre_c_pre_dwarf` type, in
preparation for C coversion. *)
let num_fde = StrMap.cardinal cfa_map in
let fdes = StrMapTool.fold_map_to_array
convert_pre_c_fde cfa_map empty_fde in
let fdes_list_with_none = StrMap.fold (fun name entry folded ->
(convert_pre_c_fde name entry) :: folded)
cfa_map [] in
let fdes_list = List.fold_left (fun folded elt -> match elt with
| Some x -> x::folded
| None -> folded) [] fdes_list_with_none in
let fdes = Array.of_list fdes_list in
{
num_fde = num_fde ;
fdes = fdes

View file

@ -458,3 +458,13 @@ let of_proj proj : subroutine_cfa_map =
(** Extracts the `cfa_changes` of a project *)
let prog = BStd.Project.program proj in
of_prog prog
let clean_lost_track_subs pre_dwarf : subroutine_cfa_map =
(** Removes the subroutines on which we lost track from [pre_dwarf] *)
let sub_lost_track sub_name (sub: subroutine_cfa_data) =
not @@ AddrMap.exists (fun addr pos -> (match pos with
| RspOffset _ | RbpOffset _ -> false
| CfaLostTrack -> true))
sub.cfa_changes_fde
in
StrMap.filter sub_lost_track pre_dwarf

91
csmith/csmith_test_generated.sh Executable file
View file

@ -0,0 +1,91 @@
#!/bin/bash
USAGE="$0 nb_tests kept_directory"
if [ "$#" -lt 1 ] ; then
>&2 echo -e "Missing argument(s). Usage:\n$USAGE"
exit 1
fi
NB_TESTS=$1
KEPT_DIRECTORY=$2
RUN_TIMEOUT=2
tmpdir="$(mktemp -d)"
error_count=0
function statusline {
echo -ne "\r\e[1m[\e[32m$(printf "%03d/%03d" "$1" "$NB_TESTS")\e[39m] >>>\e[0m $2 "
}
function reporterror {
echo -e "\n\e[1;31m[$(printf "%03d" $1)] Error: \e[0m $2"
}
function mkpath {
echo "$tmpdir/$1"
}
function failed_test {
path=$(mkpath $1)
cp "$path."* "$KEPT_DIRECTORY"
reporterror "$1" "$2"
error_count=$((error_count + 1))
}
function test_empty_dwarf {
path="$2"
statusline $1 "test DWARF emptyness"
if [ -z "$(readelf -wF "$path.eh.bin")" ]; then
return 1
else
return 0
fi
}
function test_run {
path="$2"
statusline $1 "running binaries"
orig="$(timeout $RUN_TIMEOUT "$path.orig.bin")"
orig_status=$?
synth="$(timeout $RUN_TIMEOUT "$path.eh.bin")"
synth_status=$?
if [ "$orig_status" -ne "$synth_status" ] || [ "$orig" != "$synth" ] ; then
return 1
else
return 0
fi
}
mkdir -p "$KEPT_DIRECTORY"
statusline "" ""
for num in $(seq 1 $NB_TESTS); do
## Generation, compilation, synthesis
statusline $num "csmith"
path=$(mkpath $num)
csmith > "$path.c"
statusline $num "compiling"
gcc -O2 -I/usr/include/csmith-2.3.0/ -w "$path.c" -o "$path.orig.bin"
objcopy --remove-section '.eh_frame' --remove-section '.eh_frame_hdr' \
"$path.orig.bin" "$path.bin"
statusline $num "generating dwarf"
../synthesize_dwarf.sh "$path.bin" "$path.eh.bin"
## Testing
if ! test_empty_dwarf "$num" "$path"; then
failed_test "$num" "empty generated DWARF"
elif ! test_run "$num" "$path"; then
failed_test "$num" "different execution behaviour"
fi
done
echo ""
if [ "$error_count" -eq "0" ] ; then
echo -e "\n== ALL TESTS PASSED =="
else
echo -e "\n== FAILED TESTS: $error_count/$NB_TESTS =="
fi
rm -rf "$tmpdir"

View file

@ -35,7 +35,7 @@ function find_ml_dwarf_write {
}
function bap_synth {
bap "$INPUT_FILE" -p dwarfsynth --dwarfsynth-output "$TMP_DIR/marshal" \
bap "$INPUT_FILE" --no-byteweight -p dwarfsynth --dwarfsynth-output "$TMP_DIR/marshal" \
> /dev/null
return $?
}