Open radonnachie opened 4 years ago
@RocketRoss, for now, GHDL cannot be reset/restarted. You need to call the binary multiple times. If you are generating an ELF binary or shared library and loading it dynamically, you need to unload it from memory and load it again. See the following related issues: #1053, #803, #1059.
In VUnit/vunit#568 there is an example that shows how this is handled from Python. Precisely, see dlopen and dlclose in https://github.com/VUnit/vunit/pull/568/files#diff-14ddabc1969914ccb081e8cd8222616d
EDIT
So, for your case:
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//extern int ghdl_main(char argc, char* argv[]);
int main(int argc, char const *argv[])
{
typedef int main_t(int, char**);
for (size_t i = 0; i < 2; i++)
{
void * h = dlopen("path/to/ghdl/generated/binary", RTLD_LAZY);
main_t *ghdl_main = (main_t*)dlsym(h, "ghdl_main");
if (!ghdl_main){
fprintf(stderr, "%s\n", dlerror());
exit(2);
}
printf("ghdl_main return: %d\n", ghdl_main(0, NULL));
dlclose(h);
}
return 0;
}
Note that, as a trick, the ELF binaries generated by ghdl -e
with LLVM can be loaded as shared libraries. This is hackish, but it works (on GNU/Linux). If you want to do it "properly", use --bind
and --list-link
with GCC to generate an *.so
file, instead of ghdl -e
.
@umarcor, Thanks for taking the time to write such an informative response. I'll run through the links etc.
By "path/to/generated/binary" d'you mean the toplevel from ghdl -a ... && ghdl -e ...
?
I suspect that either way this ought to be closed. Unless there is a possibility of adding a reset function to the feature request list. (Excuse me if I'm treating a complex issue as a far simpler one.)
@umarcor, Thanks for taking the time to write such an informative response. I'll run through the links etc.
This is a not-very-used feature of GHDL. It's always a pleasure to share knowledge with other users in this niche! Be aware that some of the content might be interesting for you, as a user of VHPIDIRECT. Not specific about this issue.
By "path/to/generated/binary" d'you mean the toplevel from
ghdl -a ... && ghdl -e ...
?
I mean the (executable) file that you get as the artifact of your design. If you use mcode backend, such artifact does not exist. mcode is an in-memory backend, so you cannot dlopen
it. With LLVM backend, the name of the binary is typically the toplevel. In your example above, ./ent
(shouldn't the entity in your MWE need to be bugtest
so that you get a binary named like that?). However, note that this might change:
entity_arch
, so ent_a
. VUnit uses ghdl --elab-run --no-run
, so it's the same procedure with additional layers.ghdl -a ent.vhd
#ghdl -e -Wl,main.o bugtest
ghdl --bind bugtest
gcc -fPIC -rdynamic -shared wrapper.c -Wl,`ghdl --list-link bugtest` -o name_you_want.so
gcc main.c -o main
Note that:
wrapper.c
can be empty. Use it in case you want to do anything to the args that main
will pass.main
, it will load name_you_want.so
through dlopen
and it will execute the ghdl_main
from there.See https://ghdl.readthedocs.io/en/latest/using/Foreign.html#linking-ghdl-to-ada-c
Further notes:
I suspect that either way this ought to be closed.
I think it is ok to keep it open. AFAIK, there is no specific issue to request the feature of "being able to reset GHDL in-memory". I believe that this alone might be faster to be implemented than other features mentioned in #1053, such as run_until
.
Unless there is a possibility of adding a reset function to the feature request list.
The meaning of ghdl_restart
in the quoted text in #1053 is the same as this request of yours.
(Excuse me if I'm treating a complex issue as a far simpler one.)
According to Tristan, this is not complex. However, I tried and I could not do it. Maybe you are luckier :D. Anyway, I understand that this is a low priority issue for now. Synthesis and supporting VHDL 2008 features are more demanded features!
Ah of course, I'd understand pushing support for VHDL 2008 over this. I think that features of this sort will create really powerful tools in the simulation on top of GHDL.
(shouldn't the entity in your MWE need to be bugtest so that you get a binary named like that?) Yup, I was cutting corners on the form! Well spotted.
Do you mind helping a bit further: I'm trying to set up the mentioned shared library and PIE.
Let me share my context: I built ghdl-llvm with --default-pic in anticipation for this sort of work. So far it hasn't been useful: apt-get install ghdl-llvm has worked everytime. I dont know when to use the -Wl,-pie compilation flag though.... On that, my compilation understanding seems to be slipping: I came up with:
ghdl-gcc -a BugTest.vhd &&
ghdl-gcc --bind bugtest &&
gcc main.c -Wl,`ghdl-gcc --list-link bugtest` &&
./a.out &&
rm *.o work-obj93.cf a.out
for your
ghdl-gcc -a bugtest.vhd ghdl-gcc --bind bugtest gcc -fPIC -rdynamic -shared wrapper.c -Wl,
ghdl-gcc --list-link bugtest
-o name_you_want.so gcc main.c -o main
Yours fails with:
/usr/bin/ld: /usr/lib/ghdl/gcc/vhdl/libgrt.a(grt-cbinding.o): relocation R_X86_64_PC32 against symbol `stdout@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
What do you suspect needs recompilation with the '-fPIC' flag? GLIBC? GHDL-gcc? This sort of thing escapes me.
According to Tristan, this is not complex. However, I tried and I could not do it. Maybe you are luckier :D.
Life goals right there. I'll keep working towards it :+1:
EDIT Clean up markup.
I think that features of this sort will create really powerful tools in the simulation on top of GHDL.
I do believe so. Apart from dbhi.github.io and VUnit/cosim, see the screencasts in VUnit/vunit#568. That's a simulation GUI written in Vue, with a Flask backend that loads a GHDL simulation dynamically. It allows to build "custom virtual boards and interactive testbenches". Of course, it is just a fancy proof of concept for now.
Let me share my context: I built ghdl-llvm with --default-pic in anticipation for this sort of work.
Precisely, images in dbhi/docker use GHDL with LLVM backend and --default-pic
.
So far it hasn't been useful: apt-get install ghdl-llvm has worked everytime. I dont know when to use the -Wl,-pie compilation flag though.... On that, my compilation understanding seems to be slipping
TBH, I am neither sure about when are -fPIC
, -PIE
and/or -rdynamic
required. For GCC, I put all three and then remove them one by one.
I do know that GHDL tried to detect --default-pic
from the system. If the system GCC and libs were compiled with fPIC/PIE, it did compile all the libs with it. When GHDL is configured with --default-pic
explicitly, it is supposed to use it implicitly when executing any -a
, -e
or -r
command. Hence, you do never need to provide these arguments (fPIC/PIE) to ghdl, as long as you use a recent version of GHDL and you configure it properly.
/usr/bin/ld: /usr/lib/ghdl/gcc/vhdl/libgrt.a(grt-cbinding.o): relocation R_X86_64_PC32 against symbol `stdout@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
What do you suspect needs recompilation with the '-fPIC' flag? GLIBC? GHDL-gcc? This sort of thing escapes me.
It seems that the version of GHDL that you have does NOT use fPIC by default. When it was built, libgrt.a
was compiled without it. Hence, it fails to link it with a wrapper.o
or main.o
which is position independent. I would say that the ./a.out
that you get is not PIE. That is, you can execute it in the CLI but you cannot load it dynamically. Moreover, if you add -shared
to your gcc call, it should fail.
Hence, you do need a version of GHDL that was built with --default-pie
, so that libgrt.a
and all the std
and ieee
libs are PIE. If you don't want to build GHDL yourself, any of the docker/podman images in the following repos should work for you: ghdl/ghdl, ghdl/vunit or aptman/dbhi.
Also, sooner or later, this conversation will be interesting/useful for you: #800
Life goals right there. I'll keep working towards it 👍
I pointed you to some sources in the other issue, so that you can have a glance at them.
I've gotten further but am still struggling to dlopen() dlclose() the symbol of ghdl_main.
I just get cannot dynamically load position-independent executable
on trying to open the output from -e or --list-link. The posts I have read are a little hazy on when you can/not dlopen() a Position independent executable.
Any further pointers @umarcor? When I have got this down, it'll be noted in the examples (#1059 comment
As a foot note on the build process, my attempts were:
#gcc
ghdl-gcc -a BugTest.vhd &&
ghdl-gcc --bind bugtest &&
gcc wrapper.c -fPIC -rdynamic -Wl,`ghdl-gcc --list-link bugtest` -o bugtest.so
gcc -o main main.c -ldl &&
./main
#llvm
#/etc/ghdl-llvm-non-PIC-compiled/bin/ghdl -a BugTest.vhd &&
#/etc/ghdl-llvm-non-PIC-compiled/bin/ghdl -e bugtest
#gcc -o main main.c -ldl &&
#./main
#llvm --bind
#gcc
#/etc/ghdl-llvm-non-PIC-compiled/bin/ghdl -a BugTest.vhd &&
#/etc/ghdl-llvm-non-PIC-compiled/bin/ghdl --bind bugtest &&
#gcc wrapper.c -fPIC -rdynamic -Wl,`/etc/ghdl-llvm-non-PIC-compiled/bin/ghdl --list-link bugtest` -o bugtest.so
#gcc -o main main.c -ldl &&
#./main
@RocketRoss you are generating an executable ELF binary, not an ELF shared library. Naming it *.so
won't change that; I believe you need to add -shared
as an argument to GCC. Sometimes, an executable ELF can be dynamically loaded, but the proper way is for it to be a shared lib. Actually, that's the main reason to use GCC explicitly, instead of ghdl -e
.
Grand, I used ghdl-llvm (one compiled with -fPIC) and the -shared
flag, following the #gcc process - it produced a .so (shared object this time) which was happily gobbled by dlopen().... only to find no symbol for ghdl_main... further thoughts? I have this C code (copied yours, but now you dont have to scroll for it):
typedef int main_t(int, char**);
void * h = dlopen("./bugtest.so", RTLD_LAZY);
printf("dlerror() after dlopen: '%s'\n", dlerror());
main_t *ghdl_main = (main_t*)dlsym(h, "ghdl_main");
if (!ghdl_main){
fprintf(stderr, "%s\n", dlerror());
exit(2);
}
printf("ghdl_main return: %d\n", ghdl_main(0, NULL));
dlclose(h);
By default, GHDL uses grt.ver
to limit which symbols are exposed:
ANY {
global:
vpi_chk_error;
vpi_control;
vpi_free_object;
vpi_get;
vpi_get_str;
vpi_get_time;
vpi_get_value;
vpi_get_vlog_info;
vpi_handle;
vpi_handle_by_index;
vpi_handle_by_name;
vpi_iterate;
vpi_mcd_close;
vpi_mcd_name;
vpi_mcd_open;
vpi_put_value;
vpi_register_cb;
vpi_register_systf;
vpi_remove_cb;
vpi_scan;
vpi_vprintf;
vpi_printf;
local:
*;
};
As you see, ghdl_main is not in the list. You need to either avoid the version script (so that all symbols are visible) or you need to provide a custom one. See #800, referenced above. See also the hint in https://ghdl.readthedocs.io/en/latest/using/CommandReference.html#list-link-list-link. For example, this one is used in VUnit/cosim: https://github.com/VUnit/cosim/blob/master/cosim/vhpidirect/c/grt.ver.
Note that, when using VHPIDIRECT, you don't need any of those vpi*
functions to be exposed. That's why VUnit/cosim just ignores them.
Sorry, you had actually given me all the resources to get to where I am now from the get go. I think I got a little lost on the way (losing the -shared flag, and not seeing the relevance of #800).
I have tried to be more thorough this time. But again I am stuck. (I am explaining my understanding too in case there is an error there)
The --version-script flag is meant for elaboration. But in order to generate a shared object (not an executable) of the ghdl simulation, we replace ghdl -e
with ghdl --bind
, then we create a manual compilation of the SO with a gcc -shared -fPIC
call that uses the ghdl --list-link
. (The -Wl,ghdl --list-link...
feeds extra linking options to the linker invoked by gcc [right?]j).
As the --list-link
is the second half of the -e
step, I added the --version-script
option to it. I have copied the VUnit grt.ver, and point to it.
I do use a ghdl-llvm that was compiled with --default-pic. It is necessary, as stated a few times already.
Compilation happens, without errors. But at run time dlsym() still doesn't find ghdl_main.
I dont use the empty wrapper.c file in the SO gcc compilation, it doesnt make a difference if I do.. I dont compile main with the SO, it doesnt make a difference if I do. I do compile main with -ldl for the dl*() functions. I use the same ghdl in every related call, so there is no mixing of grt.ver/backend stuff.
I wondered if this has to do with the custom grt.ver being exposed as VHPIDIRECT, and me needing to change the symbol I search for.
objdump -d ghdl.so | grep "<ghdl_main>"
from #640. I tried on a number of objects nothing is found to match.... But there was a different build process in that issue.e~bugtest.o
object is for...I am struggling to apply all of the comments and solutions across the threads that mention this because of the very different compilation processes.
I even sat for a while working out where one would use ghdl -e -Wl,-shared
in this, as per #800 comment.. I feel like it doesn't fit in to this process, even though it seems to have come up while @umarcor was dealing with my comments.
The code again:
entity BugTest is
end entity BugTest;
architecture RTL of BugTest is
begin
process
begin
report "Toplevel";
wait;
end process;
end architecture RTL;
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
typedef int main_t(int, char**);
for (size_t i = 0; i < 3; i++)
{
void * h = dlopen("./ghdl.so", RTLD_LAZY);
printf("dlerror() after dlopen: '%s'\n", dlerror());
main_t *ghdl_main = (main_t*)dlsym(h, "ghdl_main");
if (!ghdl_main){
fprintf(stderr, "%s\n", dlerror());
exit(2);
}
printf("ghdl_main return: %d\n", ghdl_main(0, NULL));
dlclose(h);
}
return 0;
}
/etc/ghdl-llvm-PIC-compiled/bin/ghdl -a BugTest.vhd
/etc/ghdl-llvm-PIC-compiled/bin/ghdl --bind bugtest
gcc -fPIC -rdynamic -shared -Wl,`/etc/ghdl-llvm-PIC-compiled/bin/ghdl --list-link -Wl,-Wl,--version-script=/etc/ghdl-llvm-PIC-compiled/grt.ver bugtest` -o ghdl.so
gcc main.c -ldl -o main &&
./main
If the ghdl_main symbol is missing, maybe you should force it to be added by linking with -Wl,-u,ghdl_main (or maybe -Wl,-Wl,-u,ghdl_main)
Sorry, you had actually given me all the resources to get to where I am now from the get go. I think I got a little lost on the way (losing the -shared flag, and not seeing the relevance of #800).
It's ok. As you are seeing, almost all the details are directly or indirectly documented already; hence, potentially you already have all the resources that you might need. However, the content is not friendly to new users; it is rather meant as a reference/cheatsheet for those who already know the big picture. That's the gap we are trying to narrow!
I have tried to be more thorough this time. But again I am stuck. (I am explaining my understanding too in case there is an error there)
All your explanations seem ok. It feels to me that the issues you are facing now are not strictly related to GHDL. Let's step back a bit. I uploaded https://github.com/umarcor/ghdl-cosim/tree/master/dlopen. Can you execute run.sh
? I tried it in a docker container (aptman/dbhi:bionic
) and the output is the following:
root@d7c2c81c52f6:/src/dlopen# ./run.sh
Build corea.so
Build coreb.so
Build main
Test
> Hello, I'm your host: 29
> Hello, I'm core A
> Hello, I'm core B
As you can see, it just builds two dummy ghdl_main
functions in separate shared libs. Then, both of them are dynamically loaded at the same time in the main application, and both are executed (one after the other).
ghdl_main
is visible, and 2) whether we can load the same symbol name from different shared libs and use them at the same time.If the symbol is still not found, try adding -g
and/or -rdynamic
when building corea.so
and coreb.so
. Actually, it'd be useful if you added them to corea.so
only, so you can tell the difference.
Honestly, I am not sure about the rules to make symbols visible. Depending on the platform/board, sometimes symbols are visible by default, sometimes you need additional flags, sometimes there is no way... Precisely, I found the example above to fail on boards with older versions of GCC (4? 5?). Unfortunately, I did not find how to make it work consistently accross a wide variety of platforms. That's why, if possible, I try to use Docker (even on SBCs).
Precisely, dbhi/binhook is an attempt to gather different techniques for hijacking/replacing a given function in a pre-built binary/library. That's out of scope for us, because we do have access to the sources of the binary/library that we want to load/execute. However, it is related in the sense that all those techniques do need to somehow (elegant or ugly) find the symbol in order to have it replaced. As a matter of fact, I've been working on combining such function replacement techniques with GHDL and VUnit (see https://dbhi.github.io/pdf/FPGA2020_poster.pdf).
- I try the
objdump -d ghdl.so | grep "<ghdl_main>"
from #640. I tried on a number of objects nothing is found to match.... But there was a different build process in that issue.
This is relevant. You need to be able to see the symbol anyhow (objdump, readelf, nm, etc.). For example:
root@d7c2c81c52f6:/src/dlopen# objdump -d corea.so
corea.so: file format elf64-x86-64
Disassembly of section .init:
00000000000004e8 <_init>:
4e8: 48 83 ec 08 sub $0x8,%rsp
4ec: 48 8b 05 f5 0a 20 00 mov 0x200af5(%rip),%rax # 200fe8 <__gmon_start__>
4f3: 48 85 c0 test %rax,%rax
4f6: 74 02 je 4fa <_init+0x12>
4f8: ff d0 callq *%rax
4fa: 48 83 c4 08 add $0x8,%rsp
4fe: c3 retq
Disassembly of section .plt:
0000000000000500 <.plt>:
500: ff 35 02 0b 20 00 pushq 0x200b02(%rip) # 201008 <_GLOBAL_OFFSET_TABLE_+0x8>
506: ff 25 04 0b 20 00 jmpq *0x200b04(%rip) # 201010 <_GLOBAL_OFFSET_TABLE_+0x10> 50c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000000510 <puts@plt>:
510: ff 25 02 0b 20 00 jmpq *0x200b02(%rip) # 201018 <puts@GLIBC_2.2.5>
516: 68 00 00 00 00 pushq $0x0
51b: e9 e0 ff ff ff jmpq 500 <.plt>
Disassembly of section .plt.got:
0000000000000520 <__cxa_finalize@plt>:
520: ff 25 d2 0a 20 00 jmpq *0x200ad2(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 526: 66 90 xchg %ax,%ax
Disassembly of section .text:
0000000000000530 <deregister_tm_clones>:
530: 48 8d 3d f1 0a 20 00 lea 0x200af1(%rip),%rdi # 201028 <_edata>
537: 55 push %rbp
538: 48 8d 05 e9 0a 20 00 lea 0x200ae9(%rip),%rax # 201028 <_edata>
53f: 48 39 f8 cmp %rdi,%rax
542: 48 89 e5 mov %rsp,%rbp
545: 74 19 je 560 <deregister_tm_clones+0x30>
547: 48 8b 05 92 0a 20 00 mov 0x200a92(%rip),%rax # 200fe0 <_ITM_deregisterTMCloneTable>
54e: 48 85 c0 test %rax,%rax
551: 74 0d je 560 <deregister_tm_clones+0x30>
553: 5d pop %rbp
554: ff e0 jmpq *%rax
556: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
55d: 00 00 00
560: 5d pop %rbp
561: c3 retq
562: 0f 1f 40 00 nopl 0x0(%rax)
566: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
56d: 00 00 00
0000000000000570 <register_tm_clones>:
570: 48 8d 3d b1 0a 20 00 lea 0x200ab1(%rip),%rdi # 201028 <_edata>
577: 48 8d 35 aa 0a 20 00 lea 0x200aaa(%rip),%rsi # 201028 <_edata>
57e: 55 push %rbp
57f: 48 29 fe sub %rdi,%rsi
582: 48 89 e5 mov %rsp,%rbp
585: 48 c1 fe 03 sar $0x3,%rsi
589: 48 89 f0 mov %rsi,%rax
58c: 48 c1 e8 3f shr $0x3f,%rax
590: 48 01 c6 add %rax,%rsi
593: 48 d1 fe sar %rsi
596: 74 18 je 5b0 <register_tm_clones+0x40>
598: 48 8b 05 51 0a 20 00 mov 0x200a51(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable>
59f: 48 85 c0 test %rax,%rax
5a2: 74 0c je 5b0 <register_tm_clones+0x40>
5a4: 5d pop %rbp
5a5: ff e0 jmpq *%rax
5a7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
5ae: 00 00
5b0: 5d pop %rbp
5b1: c3 retq
5b2: 0f 1f 40 00 nopl 0x0(%rax)
5b6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
5bd: 00 00 00
00000000000005c0 <__do_global_dtors_aux>:
5c0: 80 3d 61 0a 20 00 00 cmpb $0x0,0x200a61(%rip) # 201028 <_edata>
5c7: 75 2f jne 5f8 <__do_global_dtors_aux+0x38>
5c9: 48 83 3d 27 0a 20 00 cmpq $0x0,0x200a27(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
5d0: 00
5d1: 55 push %rbp
5d2: 48 89 e5 mov %rsp,%rbp
5d5: 74 0c je 5e3 <__do_global_dtors_aux+0x23>
5d7: 48 8b 3d 42 0a 20 00 mov 0x200a42(%rip),%rdi # 201020 <__dso_handle>
5de: e8 3d ff ff ff callq 520 <__cxa_finalize@plt>
5e3: e8 48 ff ff ff callq 530 <deregister_tm_clones>
5e8: c6 05 39 0a 20 00 01 movb $0x1,0x200a39(%rip) # 201028 <_edata>
5ef: 5d pop %rbp
5f0: c3 retq
5f1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
5f8: f3 c3 repz retq
5fa: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000000600 <frame_dummy>:
600: 55 push %rbp
601: 48 89 e5 mov %rsp,%rbp
604: 5d pop %rbp
605: e9 66 ff ff ff jmpq 570 <register_tm_clones>
000000000000060a <ghld_main>:
60a: 55 push %rbp
60b: 48 89 e5 mov %rsp,%rbp
60e: 48 83 ec 10 sub $0x10,%rsp
612: 89 7d fc mov %edi,-0x4(%rbp)
615: 48 89 75 f0 mov %rsi,-0x10(%rbp)
619: 48 8d 3d 15 00 00 00 lea 0x15(%rip),%rdi # 635 <_fini+0x9>
620: e8 eb fe ff ff callq 510 <puts@plt>
625: b8 00 00 00 00 mov $0x0,%eax
62a: c9 leaveq
62b: c3 retq
Disassembly of section .fini:
000000000000062c <_fini>:
62c: 48 83 ec 08 sub $0x8,%rsp
630: 48 83 c4 08 add $0x8,%rsp
634: c3 retq
- I dont know what the
e~bugtest.o
object is for...
I believe this is why you need to call ghdl --bind
. See #781.
I am struggling to apply all of the comments and solutions across the threads that mention this because of the very different compilation processes.
This might be, partially, my fault. As commented in https://github.com/ghdl/ghdl/issues/800#issuecomment-610602607, I thought that using GCC, --bind
and --list-link
was compulsory in order to generate a shared library. But it seems not to be true. Hence, I should start testing and using ghdl -e
only (as it feel much easier).
I even sat for a while working out where one would use
ghdl -e -Wl,-shared
in this, as per #800 comment.. I feel like it doesn't fit in to this process, even though it seems to have come up while @umarcor was dealing with my comments.
It does. Instead of:
ghdl-gcc --bind bugtest &&
gcc wrapper.c -fPIC -shared -Wl,`ghdl-gcc --list-link bugtest` -Wl,--version-script=file.ver -o bugtest.so
the following should work:
gcc -c -fPIC wrapper.c &&
ghdl -e -Wl,wrapper.o -Wl,-shared -Wl,-Wl,--version-script=file.ver -o bugtest.so bugtest
However, I did not test it yet.
-Wl,-Wl,-u,ghdl_main
^^ has helped where -Wl,-Wl,--version-script=/etc/ghdl-llvm-PIC/grt.ver
could not
In each following code block, the first line works, the others (all beginning with a #) do not:
/etc/ghdl-llvm-PIC/bin/ghdl -e -Wl,-shared -Wl,-Wl,-u,ghdl_main -o ghdl.so bugtest
#/etc/ghdl-llvm-PIC/bin/ghdl -e -Wl,-shared -Wl,-Wl,--version-script=cust.ver -o ghdl.so bugtest
gcc -fPIC -shared -Wl,`/etc/ghdl-llvm-PIC/bin/ghdl --list-link -Wl,-Wl,-u,ghdl_main bugtest` -o ghdl.so
#gcc -fPIC -shared -Wl,`/etc/ghdl-llvm-PIC/bin/ghdl --list-link bugtest` -Wl,--version-script=cust.ver -o ghdl.so
#gcc -fPIC -shared -Wl,`/etc/ghdl-llvm-PIC/bin/ghdl --list-link -Wl,-Wl,--version-script=cust.ver bugtest` -o ghdl.so
So I am having issues with using the --version-script
The version script is required to support vpi, but by default symbols are exported when building a shared library.
So I think you need the -u ghdl_main
. You may add the version script (or not), but that's not required.
I suppose if you add the version script you must also export ghdl_main.
The version script is required to support vpi, but by default symbols are exported when building a shared library.
I'm not sure about this. I believe that GHDL uses grt.ver
by default, even if VPI is not being used. Hence, all symbols except the ones defined in grt.ver
are hidden. That's why:
https://github.com/ghdl/ghdl/issues/640#issuecomment-486433605
I think it would still be useful to have a
--no-version-script
as an option to--list-link
.
Now, I'd add that it would be useful to have it as an argument to ghdl -e
too.
In fact, this was the motivation for #801. Since the default version script cannot be removed (without using sed
to parse the output of --list-link
), it was made compatible with additional version scripts. Theoretically, that allows users to provide a list of symbols, apart from the defaults made visible by grt.ver
. That's how I've been using it.
So I think you need the
-u ghdl_main
. You may add the version script (or not), but that's not required.
In order to expose ghdl_main
only, this is correct. However, for exposing multiple symbols (such as the ones in ghdl.h
) it is cumbersome to provide all of them in the CLI. That's why I think that @RocketRoss should try to guess how to use a custom version script.
I suppose if you add the version script you must also export ghdl_main.
Indeed. All the custom version scripts I use do include ghdl_main
, at least.
@RocketRoss, did you try the dlopen
example? What's the output of objdump -d corea.so
?
@umarcor Your dlopen
worked out of the box, it helped confirm my understanding of what is going on. Thanks for it.
I suppose if you add the version script you must also export ghdl_main.
I believe I am trying to export ghdl_main with the custom.ver file (as I said I borrowed it from VUnit: first 4 lines:
VHPIDIRECT {
global:
main;
ghdl_main;
...
local:
*;
};
Now, I'd add that it would be useful to have it as an argument to ghdl -e too.
Now it seems as though the --version-script option hasn't actually made its way to my ghdl?? But it had been merged in #801.
I think it would still be useful to have a --no-version-script as an option to --list-link.
It didn't work in my Mistook --no-version-script for --version-script.--list-link
either. So how come some are using it and I am not.
GHDL 1.0-dev (v0.37.0-178-gbe59edef) [Dunoon edition] Compiled with GNAT Version: 8.3.0 llvm code generator
@umarcor Your
dlopen
worked out of the box, it helped confirm my understanding of what is going on. Thanks for it.
Good! That means that we need to guess what's happening with GHDL, but the system tools are ok.
Now, I'd add that it would be useful to have it as an argument to ghdl -e too.
Now it seems as though the --version-script option hasn't actually made its way to my ghdl?? But it had been merged in #801.
This is interesting... what's the content of your default grt.ver
file? You can get the path from --list-link
.
I think it would still be useful to have a --no-version-script as an option to --list-link.
It didn't work in my
--list-link
either. So how come some are using it and I am not. Will edit with my ghdl version details again.
This might be a misunderstanding. --no-version-script
was never implemented, neither for --list-link
nor for -e
. I'm actually requesting/asking Tristan whether he'd consider to add this feature.
Anyway, we should be able to fix your issue regardless of that option being supported.
In fact, I did not ignore umarcor/ghdl#1, but I did not reply yet because I'm working on https://github.com/umarcor/ghdl-cosim/tree/todo. See https://umarcor.github.io/ghdl-cosim/. That's a refactorisation/extension of https://ghdl.readthedocs.io/en/latest/using/Foreign.html. The interesting difference is that several examples are included:
quickstart/random,
quickstart/math,
quickstart/customc,
linking/*,
wrapping/basic,
wrapping/time,
accarray/*,
demo,
shlib/dlopen,
shlib/ghdl
It is basically a remix of the references in https://github.com/eine/hwd-ide/tree/develop/examples/VHPI and the multiple tests that you did during this last week. However, it is not ready yet. Please, let me finish adding (specially, setting up the CI for shlib/ghdl, which is the example that corresponds to your current issue) and tidying it up. I will let you know when it's ready, since I'd like to rebase umarcor/ghdl#1 on top of it, instead of the fork of this repo. Actually, example accarray
is a placeholder for your "C access" example.
It gets interesting! Because (luckily) I hadn't cleaned up some experiments:
This is interesting... what's the content of your default grt.ver file?
The default grt.ver file actually had ghdl_main;
listed under global. I had put it there in exasperation a while back. Having removed it, the executable compilation lines above no longer work. These:
/etc/ghdl-llvm-PIC/bin/ghdl -e -Wl,-shared -Wl,-Wl,-u,ghdl_main -o ghdl.so bugtest
#or
gcc -fPIC -shared -Wl,`/etc/ghdl-llvm-PIC/bin/ghdl --list-link -Wl,-Wl,-u,ghdl_main bugtest` -o ghdl.so
The objdump of the SO does contain the <ghdl_main>
definition though. But still such a symbol is not found by dlsym().
Of course then, adding -Wl,-Wl,--version-script=custom.ver
in with the -Wl,-Wl,-u,ghdl_main
gets the -e
and gcc
generated SOs to work.
So now the question is, why do I have to provide a custom.ver file and -u
expose the function. I do think this is what Tristan meant though, that I have to do both.
In fact, I did not ignore umarcor#1, but I did not reply yet because I'm working
I like the sound of it. Will be glad to help once you're ready for it. I'll double check the hwd-ide examples out in the meanwhile.
I have just added the '-shared' option. It removes the version script. I have just quickly tested it, so maybe it has to be tuned. In particular, we may need to also add the -u ghdl_main option.
Confirming that I got the -shared
elaboration flag to generate a SO file with the toplevel entity's name. Still needed to expose ghdl_main.
/etc/ghdl-llvm-PIC/bin/ghdl -a Bugtest.vhd &&
/etc/ghdl-llvm-PIC/bin/ghdl -e -shared -Wl,-Wl,-u,ghdl_main Bugtest &&
gcc main.c -ldl -o main&&
./main
Starting to look neater and neater. Thanks @tgingold.
I'll just reference #640 to link this comment to that issue.
@RocketRoss, I think that the first version of https://umarcor.github.io/ghdl-cosim/index.html is almost ready. Would you mind having a look?
Example shared/shghdl is what we've been talking about in this issue. This is the log of the execution: https://github.com/umarcor/ghdl-cosim/runs/578738118?check_suite_focus=true#step:4:11.
I used ghdl -e -Wl,-Wl,--version-script=../../vhpidirect.ver -o tb.so tb
only for now. However, when the initial version is upstreamed, I'd like to work on three PRs:
-shared
and -Wl,-Wl,-u,ghdl_main
, according to these last comments.@umarcor I'm reading through it. I'll rebuild the older --version-script
enabled version and double check that example my side :)
anything else in particular you'd like me to check?
@umarcor I'm reading through it. I'll rebuild the older
--version-script
enabled version and double check that example my side :)
Good!
anything else in particular you'd like me to check?
Just a quick readthrough to ensure that there is nothing clearly badly formatted or which should not be there. Note that all the content except the examples is basically copied from the current Foreign.rst
, split and extended. Hence, most of the content should already be familiar. Cross-references to sections in the main docs should work transparently.
Examples 'Demo' and 'Access to array' are placeholders only. Not to be published at first.
Yup cross references are lining up, and I like the split. Reads nicely.
Do you mind if I nitpick over little things (not grammar, just extra explicit sentences/hints)? I'm reading it as if I were as naive as I was when I first started?
ensure that there is nothing clearly badly formatted
I can also save the little changes for later (I'll note them). Your preference?
Sure. I'll be disconnected for some hours now and, otherwise, I have other tasks I can do. Hence, you can open a PR with those little details and changes and I'll avoid doing text modifications meanwhile.
Note that I added many comments to places in the main docs such as https://ghdl.readthedocs.io/en/latest/using/CommandReference.html#list-link-list-link or https://ghdl.readthedocs.io/en/latest/using/Simulation.html#cmdoption-ghdl-ggeneric. Also, for each section in the cosim docs, info is split between the section and the examples that correspond to that section (e.g. "Wrapping a simulation (ghdl_main)" and "Examples/Wrapping").
Instead of writing changes straighaway, better note them and ensure that they are not already written somewhere else. If in doubt, I can tell you. Of course, suggestions to move content are also welcome.
@RocketRoss, since ghdl/ghdl-cosim is ready now, let's talk about tests regarding -Wl,-Wl,-u,ghdl_main
, -shared
and -Wl,-Wl,--version-script=
in ghdl/ghdl-cosim#2. We will keep this issue open for supporting restart in GRT. Does it sound good to you?
Description With a custom main(), the second call of ghdl_main(0, NULL) aborts the program.
Expected behaviour I expect to be able to resimulate. (Ultimately I want to pass in a different (argc, argv)/top-level generic the subsequent times - but I am not getting positive results passing in argc, argv in the first place. So that will be a second query.)
How to reproduce? Tell us how to reproduce this issue. Please provide a Minimal Working Example (MWE). With sample code it's easier to reproduce the bug and it's much faster to fix it. For example:
Context $ ghdl --version GHDL 0.36-dev (Ubuntu 0.35+git20181129+dfsg-4ubuntu1) [Dunoon edition] Compiled with GNAT Version: 8.3.0 llvm code generator
Additional context Just get the following in the terminal: