sim/erc32: fix gdb with simulator build
authorAndrew Burgess <aburgess@redhat.com>
Sun, 4 Sep 2022 16:49:11 +0000 (17:49 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Sun, 4 Sep 2022 17:02:15 +0000 (18:02 +0100)
In commit:

  commit 7b01c1cc1d111ba0afa51e60fa9842d3b971e2d1
  Date:   Mon Apr 4 22:38:04 2022 +0100

      sim: fixes for libopcodes styled disassembler

changes were made to the simulator source to handle the new libopcodes
disassembler styling API.

Unfortunately, these changes broke building GDB with the erc32 (sparc)
simulator, like this:

  ../src/configure --target=sparc-linux
  make all-gdb
  ....
  /usr/bin/ld: ../sim/erc32/libsim.a(interf.o): in function `sim_open':
  /tmp/build/sim/../../src/sim/erc32/interf.c:247: undefined reference to `fprintf_styled'
  collect2: error: ld returned 1 exit status

The problem is that in commit 7b01c1cc1d11 the fprintf_styled function
was added into sis.c.  This file is only used when building the 'run'
binary, that is, the standalone simulator, and is not included in the
libsim.a library.

Now, the obvious fix would be to move fprintf_styled into libsim.a,
however, that turns out to be tricky.

The erc32 simulator currently has two copies of the function run_sim,
one in sis.c, and one in interf.c, both of these copies are global.

Currently, the 'run' binary links fine, though I suspect this might be
pure luck.  When I tried moving fprintf_styled into interf.c, I ran
into multiple-definition (of run_sim) errors.  I suspect that by
requiring the linker to pull in fprintf_styled from libsim.a I was
changing the order in which symbols were loaded, and the linker was
now seeing both copies of run_sim, while currently we only see one
copy.

The ideal solution of course, would be to merge the two similar, but
slightly different copies of run_sim, and just use the one copy.  Then
we could safely move fprintf_styled into interf.c too, and all would
be good.

But I don't have time right now to start debugging the erc32
simulator, so I wanted a solution that fixes the build without
introducing multiple definition errors.

The easiest solution I think is to just have two copies of
fprintf_styled, one in sis.c, and one in interf.c.  Unlike run_sim,
these two copies are both static, so we will not run into multiple
definition issues with this function.  The functions themselves are
not very big, so it's not a huge amount of duplicate code.

I am very aware that this is not an ideal solution, and I would
welcome anyone who wants to take on fixing the run_sim problem
properly, and then cleanup the fprintf_styled duplication.

sim/erc32/interf.c
sim/erc32/sis.c
sim/erc32/sis.h

index 78dec6f4b9bcb0b82e76d48c08b25a209a5eeb7b..f433b9d55ac3c86090777a2e6cfbbf18aa1de6ab 100644 (file)
@@ -156,6 +156,21 @@ run_sim(struct pstate *sregs, uint64_t icount, int dis)
     return TIME_OUT;
 }
 
+static int
+fprintf_styled (void *stream, enum disassembler_style style,
+               const char *fmt, ...)
+{
+  int ret;
+  FILE *out = (FILE *) stream;
+  va_list args;
+
+  va_start (args, fmt);
+  ret = vfprintf (out, fmt, args);
+  va_end (args);
+
+  return ret;
+}
+
 SIM_DESC
 sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback,
          struct bfd *abfd, char * const *argv)
index 12eb21f15a74177f8521dfdbedb9632f7d959e92..1d3ea139c23af37559c85ee653a292b0aee322a9 100644 (file)
@@ -138,7 +138,7 @@ run_sim(struct pstate *sregs, uint64_t icount, int dis)
     return TIME_OUT;
 }
 
-int
+static int
 fprintf_styled (void *stream, enum disassembler_style style,
                const char *fmt, ...)
 {
index 3a27667040264ee79537dc74ff249057811eb23f..71033137f2c6d88e13eb266d98641a166019a036 100644 (file)
@@ -204,8 +204,6 @@ extern void init_regs (struct pstate *sregs);
 /* interf.c */
 extern int     run_sim (struct pstate *sregs,
                         uint64_t icount, int dis);
-extern int      fprintf_styled (void *stream, enum disassembler_style style,
-                               const char *fmt, ...) ATTRIBUTE_PRINTF (3, 4);
 
 /* float.c */
 extern int     get_accex (void);