Re: [Qemu-devel] [PATCH v5 12/23] RISC-V HTIF Console

2018-02-09 Thread Richard Henderson
On 02/09/2018 01:08 AM, Michael Clark wrote:
> https://github.com/michaeljclark/riscv-qemu/commit/17272f5c66adf8532f196d660d2a593c2178ac95
> 
>  hw/core/loader.c     |   18 --
>  include/hw/elf_ops.h |   28 
>  include/hw/loader.h  |   17 -
>  3 files changed, 48 insertions(+), 15 deletions(-)


Much better, thanks.  Please fix the formatting though
(braces around if blocks).


r~



Re: [Qemu-devel] [PATCH v5 12/23] RISC-V HTIF Console

2018-02-09 Thread Michael Clark
https://github.com/michaeljclark/riscv-qemu/commit/17272f5c66adf8532f196d660d2a593c2178ac95

 hw/core/loader.c |   18 --
 include/hw/elf_ops.h |   28 
 include/hw/loader.h  |   17 -
 3 files changed, 48 insertions(+), 15 deletions(-)


On Fri, Feb 9, 2018 at 9:09 PM, Michael Clark  wrote:

>
>
> On Fri, Feb 9, 2018 at 8:33 PM, Michael Clark  wrote:
>
>>
>>
>> On Fri, Feb 9, 2018 at 5:35 AM, Richard Henderson <
>> richard.hender...@linaro.org> wrote:
>>
>>> On 02/07/2018 05:28 PM, Michael Clark wrote:
>>> > +++ b/hw/riscv/riscv_elf.c
>>> > @@ -0,0 +1,244 @@
>>> > +/*
>>> > + * elf.c - A simple package for manipulating symbol tables in elf
>>> binaries.
>>> > + *
>>> > + * Taken from
>>> > + * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f
>>> 03/www/
>>> > + * ftrace/elf.c
>>> > + *
>>> > + */
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +#include 
>>> > +
>>> > +#include "hw/riscv/riscv_elf.h"
>>> > +
>>> > +/*
>>> > + * elf_open - Map a binary into the address space and extract the
>>> > + * locations of the static and dynamic symbol tables and their string
>>> > + * tables. Return this information in a Elf object file handle that
>>> will
>>> > + * be passed to all of the other elf functions.
>>> > + */
>>> > +Elf_obj64 *elf_open64(const char *filename)
>>> > +{
>>> > +int i, fd;
>>> > +struct stat sbuf;
>>> > +Elf_obj64 *ep;
>>> > +Elf64_Shdr *shdr;
>>> > +
>>> > +ep = g_new(Elf_obj64, 1);
>>> > +
>>> > +/* Do some consistency checks on the binary */
>>> > +fd = open(filename, O_RDONLY);
>>> > +if (fd == -1) {
>>> > +fprintf(stderr, "Can't open \"%s\": %s\n", filename,
>>> strerror(errno));
>>> > +exit(1);
>>> > +}
>>> > +if (fstat(fd, ) == -1) {
>>> > +fprintf(stderr, "Can't stat \"%s\": %s\n", filename,
>>> strerror(errno));
>>> > +exit(1);
>>> > +}
>>> > +if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
>>> > +fprintf(stderr, "\"%s\" is not an ELF binary object\n",
>>> filename);
>>> > +exit(1);
>>> > +}
>>> > +
>>> > +/* It looks OK, so map the Elf binary into our address space */
>>> > +ep->mlen = sbuf.st_size;
>>> > +ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
>>> > +if (ep->maddr == (void *)-1) {
>>> > +fprintf(stderr, "Can't mmap \"%s\": %s\n", filename,
>>> strerror(errno));
>>> > +exit(1);
>>> > +}
>>> > +close(fd);
>>> > +
>>> > +/* The Elf binary begins with the Elf header */
>>> > +ep->ehdr = ep->maddr;
>>> > +
>>> > +/* check we have a 64-bit little-endian RISC-V ELF object */
>>> > +if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
>>> > +ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
>>> > +ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
>>> > +ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
>>> > +ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
>>> > +ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
>>> > +ep->ehdr->e_machine != EM_RISCV)
>>> > +{
>>> > +fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n",
>>> filename);
>>> > +exit(1);
>>> > +}
>>> > +
>>> > +/*
>>> > + * Find the static and dynamic symbol tables and their string
>>> > + * tables in the the mapped binary. The sh_link field in symbol
>>> > + * table section headers gives the section index of the string
>>> > + * table for that symbol table.
>>> > + */
>>> > +shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);
>>>
>>> This duplicates, badly, existing code within include/hw/elf_ops.h.
>>>
>>> In particular, this fails to bswap these fields.  As such, this code
>>> will only
>>> work on little-endian hosts.
>>>
>>
>> There is enough information in the structures held in the syminfo table
>> used by the disassembler however elf_ops.h currently throws away all
>> symbols that are not STT_FUNC, and we are after STT_OBJECT symbols. We
>> would need to add an option to load_elf to load the entire symbol table.
>> Also, it runs qsort on the table by address, so we'd need to do a linear
>> scan for the HTIF symbols by name. There are only two symbols we need:
>> 'fromhost' and 'tohost'.
>>
>> /* We are only interested in function symbols.
>>Throw everything else away.  */
>> if (syms[i].st_shndx == SHN_UNDEF ||
>> syms[i].st_shndx >= SHN_LORESERVE ||
>> ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
>> nsyms--;
>> if (i < nsyms) {
>> syms[i] = syms[nsyms];
>> }
>> continue;
>> }
>>
>> It would be really nice if HTIF just specified registers in device-tree;
>> alas it doesn't; and there is still quite a bit of code that depend on
>> using 

Re: [Qemu-devel] [PATCH v5 12/23] RISC-V HTIF Console

2018-02-09 Thread Michael Clark
On Fri, Feb 9, 2018 at 8:33 PM, Michael Clark  wrote:

>
>
> On Fri, Feb 9, 2018 at 5:35 AM, Richard Henderson <
> richard.hender...@linaro.org> wrote:
>
>> On 02/07/2018 05:28 PM, Michael Clark wrote:
>> > +++ b/hw/riscv/riscv_elf.c
>> > @@ -0,0 +1,244 @@
>> > +/*
>> > + * elf.c - A simple package for manipulating symbol tables in elf
>> binaries.
>> > + *
>> > + * Taken from
>> > + * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f03/www/
>> > + * ftrace/elf.c
>> > + *
>> > + */
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +#include 
>> > +
>> > +#include "hw/riscv/riscv_elf.h"
>> > +
>> > +/*
>> > + * elf_open - Map a binary into the address space and extract the
>> > + * locations of the static and dynamic symbol tables and their string
>> > + * tables. Return this information in a Elf object file handle that
>> will
>> > + * be passed to all of the other elf functions.
>> > + */
>> > +Elf_obj64 *elf_open64(const char *filename)
>> > +{
>> > +int i, fd;
>> > +struct stat sbuf;
>> > +Elf_obj64 *ep;
>> > +Elf64_Shdr *shdr;
>> > +
>> > +ep = g_new(Elf_obj64, 1);
>> > +
>> > +/* Do some consistency checks on the binary */
>> > +fd = open(filename, O_RDONLY);
>> > +if (fd == -1) {
>> > +fprintf(stderr, "Can't open \"%s\": %s\n", filename,
>> strerror(errno));
>> > +exit(1);
>> > +}
>> > +if (fstat(fd, ) == -1) {
>> > +fprintf(stderr, "Can't stat \"%s\": %s\n", filename,
>> strerror(errno));
>> > +exit(1);
>> > +}
>> > +if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
>> > +fprintf(stderr, "\"%s\" is not an ELF binary object\n",
>> filename);
>> > +exit(1);
>> > +}
>> > +
>> > +/* It looks OK, so map the Elf binary into our address space */
>> > +ep->mlen = sbuf.st_size;
>> > +ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
>> > +if (ep->maddr == (void *)-1) {
>> > +fprintf(stderr, "Can't mmap \"%s\": %s\n", filename,
>> strerror(errno));
>> > +exit(1);
>> > +}
>> > +close(fd);
>> > +
>> > +/* The Elf binary begins with the Elf header */
>> > +ep->ehdr = ep->maddr;
>> > +
>> > +/* check we have a 64-bit little-endian RISC-V ELF object */
>> > +if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
>> > +ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
>> > +ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
>> > +ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
>> > +ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
>> > +ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
>> > +ep->ehdr->e_machine != EM_RISCV)
>> > +{
>> > +fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n",
>> filename);
>> > +exit(1);
>> > +}
>> > +
>> > +/*
>> > + * Find the static and dynamic symbol tables and their string
>> > + * tables in the the mapped binary. The sh_link field in symbol
>> > + * table section headers gives the section index of the string
>> > + * table for that symbol table.
>> > + */
>> > +shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);
>>
>> This duplicates, badly, existing code within include/hw/elf_ops.h.
>>
>> In particular, this fails to bswap these fields.  As such, this code will
>> only
>> work on little-endian hosts.
>>
>
> There is enough information in the structures held in the syminfo table
> used by the disassembler however elf_ops.h currently throws away all
> symbols that are not STT_FUNC, and we are after STT_OBJECT symbols. We
> would need to add an option to load_elf to load the entire symbol table.
> Also, it runs qsort on the table by address, so we'd need to do a linear
> scan for the HTIF symbols by name. There are only two symbols we need:
> 'fromhost' and 'tohost'.
>
> /* We are only interested in function symbols.
>Throw everything else away.  */
> if (syms[i].st_shndx == SHN_UNDEF ||
> syms[i].st_shndx >= SHN_LORESERVE ||
> ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
> nsyms--;
> if (i < nsyms) {
> syms[i] = syms[nsyms];
> }
> continue;
> }
>
> It would be really nice if HTIF just specified registers in device-tree;
> alas it doesn't; and there is still quite a bit of code that depend on
> using these magic HTIF 'fromhost' and 'tohost' symbols. riscv-tests for one
> uses the HTIF mechanism and spike the official ISA simulator uses HTIF for
> IO.
>

Luckily elf_ops.h load_elf32 and load_elf64 are wrapped by load_elf, and
several load_elf_* variants.

We need the symbol name, type, address and size to find and validate the
HTIF symbols. The current thought is to pass a callback function pointer to
a new load_elf_sym variant, where the new function pointer, in the common
case, won't be called by 

Re: [Qemu-devel] [PATCH v5 12/23] RISC-V HTIF Console

2018-02-08 Thread Michael Clark
On Fri, Feb 9, 2018 at 5:35 AM, Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 02/07/2018 05:28 PM, Michael Clark wrote:
> > +++ b/hw/riscv/riscv_elf.c
> > @@ -0,0 +1,244 @@
> > +/*
> > + * elf.c - A simple package for manipulating symbol tables in elf
> binaries.
> > + *
> > + * Taken from
> > + * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f03/www/
> > + * ftrace/elf.c
> > + *
> > + */
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "hw/riscv/riscv_elf.h"
> > +
> > +/*
> > + * elf_open - Map a binary into the address space and extract the
> > + * locations of the static and dynamic symbol tables and their string
> > + * tables. Return this information in a Elf object file handle that will
> > + * be passed to all of the other elf functions.
> > + */
> > +Elf_obj64 *elf_open64(const char *filename)
> > +{
> > +int i, fd;
> > +struct stat sbuf;
> > +Elf_obj64 *ep;
> > +Elf64_Shdr *shdr;
> > +
> > +ep = g_new(Elf_obj64, 1);
> > +
> > +/* Do some consistency checks on the binary */
> > +fd = open(filename, O_RDONLY);
> > +if (fd == -1) {
> > +fprintf(stderr, "Can't open \"%s\": %s\n", filename,
> strerror(errno));
> > +exit(1);
> > +}
> > +if (fstat(fd, ) == -1) {
> > +fprintf(stderr, "Can't stat \"%s\": %s\n", filename,
> strerror(errno));
> > +exit(1);
> > +}
> > +if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
> > +fprintf(stderr, "\"%s\" is not an ELF binary object\n",
> filename);
> > +exit(1);
> > +}
> > +
> > +/* It looks OK, so map the Elf binary into our address space */
> > +ep->mlen = sbuf.st_size;
> > +ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
> > +if (ep->maddr == (void *)-1) {
> > +fprintf(stderr, "Can't mmap \"%s\": %s\n", filename,
> strerror(errno));
> > +exit(1);
> > +}
> > +close(fd);
> > +
> > +/* The Elf binary begins with the Elf header */
> > +ep->ehdr = ep->maddr;
> > +
> > +/* check we have a 64-bit little-endian RISC-V ELF object */
> > +if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
> > +ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
> > +ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
> > +ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
> > +ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
> > +ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
> > +ep->ehdr->e_machine != EM_RISCV)
> > +{
> > +fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n",
> filename);
> > +exit(1);
> > +}
> > +
> > +/*
> > + * Find the static and dynamic symbol tables and their string
> > + * tables in the the mapped binary. The sh_link field in symbol
> > + * table section headers gives the section index of the string
> > + * table for that symbol table.
> > + */
> > +shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);
>
> This duplicates, badly, existing code within include/hw/elf_ops.h.
>
> In particular, this fails to bswap these fields.  As such, this code will
> only
> work on little-endian hosts.
>

There is enough information in the structures held in the syminfo table
used by the disassembler however elf_ops.h currently throws away all
symbols that are not STT_FUNC, and we are after STT_OBJECT symbols. We
would need to add an option to load_elf to load the entire symbol table.
Also, it runs qsort on the table by address, so we'd need to do a linear
scan for the HTIF symbols by name. There are only two symbols we need:
'fromhost' and 'tohost'.

/* We are only interested in function symbols.
   Throw everything else away.  */
if (syms[i].st_shndx == SHN_UNDEF ||
syms[i].st_shndx >= SHN_LORESERVE ||
ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
nsyms--;
if (i < nsyms) {
syms[i] = syms[nsyms];
}
continue;
}

It would be really nice if HTIF just specified registers in device-tree;
alas it doesn't; and there is still quite a bit of code that depend on
using these magic HTIF 'fromhost' and 'tohost' symbols. riscv-tests for one
uses the HTIF mechanism and spike the official ISA simulator uses HTIF for
IO.


Re: [Qemu-devel] [PATCH v5 12/23] RISC-V HTIF Console

2018-02-08 Thread Richard Henderson
On 02/07/2018 05:28 PM, Michael Clark wrote:
> +++ b/hw/riscv/riscv_elf.c
> @@ -0,0 +1,244 @@
> +/*
> + * elf.c - A simple package for manipulating symbol tables in elf binaries.
> + *
> + * Taken from
> + * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f03/www/
> + * ftrace/elf.c
> + *
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "hw/riscv/riscv_elf.h"
> +
> +/*
> + * elf_open - Map a binary into the address space and extract the
> + * locations of the static and dynamic symbol tables and their string
> + * tables. Return this information in a Elf object file handle that will
> + * be passed to all of the other elf functions.
> + */
> +Elf_obj64 *elf_open64(const char *filename)
> +{
> +int i, fd;
> +struct stat sbuf;
> +Elf_obj64 *ep;
> +Elf64_Shdr *shdr;
> +
> +ep = g_new(Elf_obj64, 1);
> +
> +/* Do some consistency checks on the binary */
> +fd = open(filename, O_RDONLY);
> +if (fd == -1) {
> +fprintf(stderr, "Can't open \"%s\": %s\n", filename, 
> strerror(errno));
> +exit(1);
> +}
> +if (fstat(fd, ) == -1) {
> +fprintf(stderr, "Can't stat \"%s\": %s\n", filename, 
> strerror(errno));
> +exit(1);
> +}
> +if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
> +fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
> +exit(1);
> +}
> +
> +/* It looks OK, so map the Elf binary into our address space */
> +ep->mlen = sbuf.st_size;
> +ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
> +if (ep->maddr == (void *)-1) {
> +fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, 
> strerror(errno));
> +exit(1);
> +}
> +close(fd);
> +
> +/* The Elf binary begins with the Elf header */
> +ep->ehdr = ep->maddr;
> +
> +/* check we have a 64-bit little-endian RISC-V ELF object */
> +if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
> +ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
> +ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
> +ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
> +ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
> +ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
> +ep->ehdr->e_machine != EM_RISCV)
> +{
> +fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n", 
> filename);
> +exit(1);
> +}
> +
> +/*
> + * Find the static and dynamic symbol tables and their string
> + * tables in the the mapped binary. The sh_link field in symbol
> + * table section headers gives the section index of the string
> + * table for that symbol table.
> + */
> +shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);

This duplicates, badly, existing code within include/hw/elf_ops.h.

In particular, this fails to bswap these fields.  As such, this code will only
work on little-endian hosts.


r~



[Qemu-devel] [PATCH v5 12/23] RISC-V HTIF Console

2018-02-07 Thread Michael Clark
HTIF (Host Target Interface) provides console emulation for QEMU. HTIF
allows identical copies of BBL (Berkeley Boot Loader) and linux to run
on both Spike and QEMU. BBL provides HTIF console access via the
SBI (Supervisor Binary Interface) and the linux kernel SBI console.

The HTIF interface reads the ELF kernel and locates the 'tohost' and
'fromhost' symbols which it uses for guest to host console MMIO.

The HTIT chardev implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_elf.c  | 244 +++
 hw/riscv/riscv_htif.c | 373 ++
 include/hw/riscv/riscv_elf.h  |  69 
 include/hw/riscv/riscv_htif.h |  62 +++
 4 files changed, 748 insertions(+)
 create mode 100644 hw/riscv/riscv_elf.c
 create mode 100644 hw/riscv/riscv_htif.c
 create mode 100644 include/hw/riscv/riscv_elf.h
 create mode 100644 include/hw/riscv/riscv_htif.h

diff --git a/hw/riscv/riscv_elf.c b/hw/riscv/riscv_elf.c
new file mode 100644
index 000..355a5a1
--- /dev/null
+++ b/hw/riscv/riscv_elf.c
@@ -0,0 +1,244 @@
+/*
+ * elf.c - A simple package for manipulating symbol tables in elf binaries.
+ *
+ * Taken from
+ * https://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15213-f03/www/
+ * ftrace/elf.c
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "hw/riscv/riscv_elf.h"
+
+/*
+ * elf_open - Map a binary into the address space and extract the
+ * locations of the static and dynamic symbol tables and their string
+ * tables. Return this information in a Elf object file handle that will
+ * be passed to all of the other elf functions.
+ */
+Elf_obj64 *elf_open64(const char *filename)
+{
+int i, fd;
+struct stat sbuf;
+Elf_obj64 *ep;
+Elf64_Shdr *shdr;
+
+ep = g_new(Elf_obj64, 1);
+
+/* Do some consistency checks on the binary */
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (fstat(fd, ) == -1) {
+fprintf(stderr, "Can't stat \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (sbuf.st_size < sizeof(Elf64_Ehdr)) {
+fprintf(stderr, "\"%s\" is not an ELF binary object\n", filename);
+exit(1);
+}
+
+/* It looks OK, so map the Elf binary into our address space */
+ep->mlen = sbuf.st_size;
+ep->maddr = mmap(NULL, ep->mlen, PROT_READ, MAP_SHARED, fd, 0);
+if (ep->maddr == (void *)-1) {
+fprintf(stderr, "Can't mmap \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+close(fd);
+
+/* The Elf binary begins with the Elf header */
+ep->ehdr = ep->maddr;
+
+/* check we have a 64-bit little-endian RISC-V ELF object */
+if (ep->ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
+ep->ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
+ep->ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
+ep->ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
+ep->ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+ep->ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
+ep->ehdr->e_machine != EM_RISCV)
+{
+fprintf(stderr, "\"%s\" is not a 64-bit RISC-V ELF object\n", 
filename);
+exit(1);
+}
+
+/*
+ * Find the static and dynamic symbol tables and their string
+ * tables in the the mapped binary. The sh_link field in symbol
+ * table section headers gives the section index of the string
+ * table for that symbol table.
+ */
+shdr = (Elf64_Shdr *)(ep->maddr + ep->ehdr->e_shoff);
+for (i = 0; i < ep->ehdr->e_shnum; i++) {
+if (shdr[i].sh_type == SHT_SYMTAB) {   /* Static symbol table */
+ep->symtab = (Elf64_Sym *)(ep->maddr + shdr[i].sh_offset);
+ep->symtab_end = (Elf64_Sym *)((char *)ep->symtab +
+ shdr[i].sh_size);
+ep->strtab = (char *)(ep->maddr + shdr[shdr[i].sh_link].sh_offset);
+}
+if (shdr[i].sh_type == SHT_DYNSYM) {   /* Dynamic symbol table */
+ep->dsymtab = (Elf64_Sym *)(ep->maddr + shdr[i].sh_offset);
+ep->dsymtab_end = (Elf64_Sym *)((char *)ep->dsymtab +
+  shdr[i].sh_size);
+ep->dstrtab = (char *)(ep->maddr + 
shdr[shdr[i].sh_link].sh_offset);
+}
+}
+return ep;
+}
+
+Elf_obj32 *elf_open32(const char *filename)
+{
+int i, fd;
+struct stat sbuf;
+Elf_obj32 *ep;
+Elf32_Shdr *shdr;
+
+ep = g_new(Elf_obj32, 1);
+
+/* Do some consistency checks on the binary */
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+fprintf(stderr, "Can't open \"%s\": %s\n", filename, strerror(errno));
+exit(1);
+}
+if (fstat(fd, ) == -1) {
+fprintf(stderr, "Can't stat \"%s\": %s\n", filename,