fileref: replace assertions by exceptions

read(fileref, ...) and write(fileref, ...), when they notice an error,
currently assert() causing a crash which looks to non-expert users like
an OSv bug. This causes, for example, bug #94, where doing osv::run()
of a directory, instead of an executable, causes such an assertion
failure.

With this patch, these read() and write() will throw an exception
(a struct error) instead of asserting.

This fixes #94, as now the user will see an uncaught exception instead
of buggy-looking assertion failure. In the next patch we'll catch this
exception, so the user won't even see that.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
loader: when can't read elf, fail normally instead of crashing

After the previous patches, when we try to run an executable we cannot
read (e.g., a directory - see issue #94), a "struct error" exception will
be thrown out of osv::run, and nobody will catch it so the user will see
a somewhat-puzzling "uncaught exception" error.

With this patch, we catch the read error exception inside osv::run(), and
when it happens, just return a normal load failure (nullptr). E.g, now
trying to run a directory will result in a normal failure:

   $ scripts/run.py -e /
   OSv v0.07-39-g03feb99
   run_main(): cannot execute /. Powering off.

Fixes #94.

The osv::run() API currently (before this patch, and also after it)
doesn't have any way to say *why* the loading failed - it could have been
that the executable was a directory, that it was not an ELF shared object,
that it was a shared object and didn't have a main - in all cases the
return value is nullptr. In the future this should probably change.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>