from what I understand in the programmers guide, CALL-CONVENTION 8 is supposed to be the same as STDCALL. This is WRONG according to the Programmer Guide bit 6 is supposed to be the same as STDCALL
Using the "STDCALL" option on a "CALL" statement is equivalent to using "CALL-CONVENTION 8" (only bit 3 set).
Using the "STATIC" option on a "CALL" statement is equivalent to using "CALL-CONVENTION 64" (only bit 6 set)
==========> conclusion
**The Programmer Guide is misleading "CALL-CONVENTION 64" is really the same as STDCALL "CALL-CONVENTION 8" is really the same as STATIC
Bugs: #673
Discussion: expand source code (COPY and INCLUDE)
Let me try to boil this down.
Bits 3 and 6 are independent, according to the documentation. It would be nice to have a test that does not rely on proprietary code (as DB2 is) that calls a function with 0, 8, 64, and 8+64.
Documentationwise, the table in item 5 could be improved.
Last edit: James K. Lowden 2020-09-09
James,
thanks for replying to this issue. The issue with the documentation is easily resolved.
The the Link and Execution issues are more troubling. So I downloaded the the VS2019 64 bit compiler so that I could test both the MinGW 32 and 64 bit compilers as well as the MS VS2019 32 and 64 bit compilers all against the same source code. DB2 supplies both 32 and 64 bit libraries to use for static linking. I'm using the DB2 Community Edition 11.5.4 which is available from IBM for free download / use.
I used three version of source code all the same except for the calls to the DB2 modules. All of the modules include the SPECIAL-NAMES " CALL-CONVENTION 74 IS DB2API" phrase.
The compile command used was the same for all of the tests except for the LIBRARY names for 64 bit or 32 bit.
32 bit ===> cobc -x delet.cbl checkerr.cbl -fstatic-call -Id:/DB2/SQLLIB/include/cobol_mf -Ld:/DB2/SQLLIB/lib/win32 -ldb2api
64 bit ===> cobc -x delet.cbl checkerr.cbl -fstatic-call -Id:/DB2/SQLLIB/include/cobol_mf -Ld:/DB2/SQLLIB/lib -ldb2api
DELET.CBL uses CALL DB2API "literal"
DELETC.CBL uses CALL STDCALL "literal"
DELETA.CBL uses CALL "literal"
For VS2019 64 bit compiler
All three source codes compiled, linked and executed successfully.
For VS2019 32 bit compiler
All three source codes compiled and linked successfully. The DELET.CBL and DELETC.CBL versions executed successfully and the DELETA.CBL failed with this error "attempt to reference unallocated memory (signal SIGSEGV)".
For the MinGW 64 bit compiler
All three source codes compiled and linked successfully. However all 3 failed to execute successfully and encountered the same error, "attempt to reference unallocated memory (signal SIGSEGV)"
For the MinGW 32 bit compiler
The DELETA.CBL compiled and linked successfully but failed execution with the same error as above. The DELET.CBL and DELETC.CBL versions compiled successfully but failed to link as follows. Note that the MinGW COBOL compiler appears to be appending a "@0" to the end of the statically called DB2 modules. I have no idea why that is happening.p;
F:\DB2TEMP>cobc -x delet.cbl checkerr.cbl -fstatic-call -Id:/DB2/SQLLIB/include/cobol_mf -Ld:/DB2/SQLLIB/lib/win32 -ldb2api
C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x207): undefined reference to
sqlgstrt@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x2de): undefined reference to
sqlgaloc@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x413): undefined reference to
sqlgstlv@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x516): undefined reference to
sqlgcall@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x569): undefined reference to
sqlgstop@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x680): undefined reference to
sqlgstrt@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x757): undefined reference to
sqlgaloc@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x88c): undefined reference to
sqlgstlv@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x9ab): undefined reference to
sqlgstlv@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xaca): undefined reference to
sqlgstlv@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xbcd): undefined reference to
sqlgcall@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xc20): undefined reference to
sqlgstop@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xd4c): undefined reference to
sqlgstrt@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xdd6): undefined reference to
sqlgstls@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xed9): undefined reference to
sqlgcall@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0xf2c): undefined reference to
sqlgstop@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x1068): undefined reference to
sqlgstrt@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x116b): undefined reference to
sqlgcall@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x11be): undefined reference to
sqlgstop@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x12fa): undefined reference to
sqlgstrt@0'C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x13fd): undefined reference to
sqlgcall@0' C:\Users\spcwh2\AppData\Local\Temp\cob10672_0.o:cob10672_0.c:(.text+0x1450): undefined reference to
sqlgstop@0'collect2.exe: error: ld returned 1 exit status
One other request, Chuck. Can you verify something for me?
It's my belief that the C code produced by cobc is invariant with regard to OS or C compiler. That is, the C output from
DELET.CBL
is the same for all configurations you're testing.As you probably know, you can see the .c files with:
Let's just make sure there's only one kind of input to the C compiler for each Cobol program.
Just to be clear, the C files won't be byte-for-byte identical. They contain some "signature" information, such as when they were generated. You will see 5 lines that vary: 3 comments, and two compile-time constants (
COB_MODULE_FORMATTED_DATE
andCOB_MODULE_TIME
).It might be worthwhile to post your
delet.c
, just so I can compare with what I'm seeing.BTW, I'm having the same uphill struggle with DB2 on Linux that I had the first time I tried it several months ago: IBM makes it as hard as possible to install the client-side libraries. Under "installation methods", see There is no installation program for IBM Data Server Driver for ODBC and CLI or for IBM Data Server Driver Package on Linux® and UNIX. You must install the driver manually. It's almost as though they don't want me to....
Hi Chuck,
Your first post described problems in the documentation, which we've addressed (not fixed, but understand) and raised concerns about how various flavors of
CALL
work or don't work. Now we're seeing that the same source code, compiled in different ways, exhibits different failure modes or, in the case of VS2019 64-bit, 100% success. That's a little weird, right? We should expect some runtime failures in every environment, because some of your test programs useCALL
incorrectly for the db2api library.I think I can help, but first I have to be sure I understand exactly what you're doing. I'm sure you've heard it said, to have an intelligent discussion, first define the terms. Let's take a step back to make sure we know what we're saying.
Since
DELET.CBL
has different failure modes, we can focus on just that one file for now.It would be useful to see the output of cobc -v for each invocation. I would like to know which include files and libraries are being brought in at the C level, and what options are being used. I wonder, for example, what knob is being turned to produce a call to
sqlgstrt@0
instead of justsqlgstrt
.Particularly troubling is:
It's very confusing that all 3 programs work correctly using Microsoft's compiler, and none do using MinGW, when we know that some are designed to work and others fail. It takes real compiler magic to make a program succeed that's meant to fail.
I will attempt to replicate your work in Linux as a baseline for comparison.
Hi James, first I did not build any of the compilers, the MinGW versions were downloaded from Arnold Trembley's site. The Microsoft VS2019 versions were downloaded from the site which Simon provided to me [https://ci.appveyor.com/project/GitMensch/gnucobol-3-x-vs]. Second, my background / experience is as a mainframe (Z/OS) COBOL programmer. I did take an introductory C programming class back in 1991 or 1992, but have not used C since then.
I'll open a command prompt and provide the output from "cobc -v" a bit farther down.
Another interesting and related discussion shows that using DYNAMIC calls to the DB2 modules does work with 64 bit Cygwin and MinGW compilers as tested by Laszso Erdos at the bottom of this disscussion thread [https://sourceforge.net/p/gnucobol/discussion/contrib/thread/e6744ecf/?page=1]
the MinGW 64 compiler
D:\GnuCOBOL64\bin>cobc -v
cobc (GnuCOBOL) 3.1-rc1.0
Built Jul 09 2020 07:15:24 Packaged Jul 01 2020 00:39:38 UTC
C version (MinGW) "10.1.0"
loading standard configuration file 'default.conf'
cobc: error: no input files
the MinGW 32 compiler
D:\GnuCOBOL-31rc-NODB>cobc -v
cobc (GnuCOBOL) 3.1-rc1.0
Built Jul 04 2020 18:08:16 Packaged Jul 01 2020 00:39:30 UTC
C version (MinGW) "6.3.0"
loading standard configuration file 'default.conf'
cobc: error: no input files
the VS2019 64 compiler
D:\GnuCOBOL_31_dev_vs_x64>cobc -v
cobc (GnuCOBOL) 3.1-dev.20200726
Built Jul 26 2020 23:43:38 Packaged Jul 26 2020 23:42:59 UTC
C version (Microsoft) 1926
loading standard configuration file 'default.conf'
cobc: error: no input files
the VS2019 32 compiler
D:\GnuCOBOL_31_dev_vs>cobc -v
cobc (GnuCOBOL) 3.1-dev.20200726
Built Jul 26 2020 23:41:41 Packaged Jul 26 2020 23:40:58 UTC
C version (Microsoft) 1926
loading standard configuration file 'default.conf'
cobc: error: no input files
The command line compile is the same other than the name of the included DB2 lib directory. From what I can see no C header files are passed to the compiler other than it's default ones which are part of the compiler implementation.
cobc -x delet.cbl checkerr.cbl -fstatic-call -Id:/DB2/SQLLIB/include/cobol_mf -Ld:/DB2/SQLLIB/lib/win32 -ldb2api
Having worked with DB2 Z/OS for many years I'm somewhat familiar with the concept of building a SQLDA area. From the IBM DB2 LUW manual I found here at this site [https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwi81-iq3N_rAhWUAZ0JHaXXCA8QFjACegQIARAB&url=ftp%3A%2F%2Fpublic.dhe.ibm.com%2Fsoftware%2Fdata%2Fdb2%2Fad%2Fv8%2Fbldg%2Fprepapi.pdf&usg=AOvVaw1ko0awkDRcQmvkIDcbweMQ] Note that this downloads the manual as a PDF.
I suspect SQLGALOC is allocating memory for an SQLDA structure in memory. However in the calls I don't see where a pointer is used to pass the address of that structure to the other modules which are actually building the SQLDA. So my suspicion is that the DB2 modules are putting data on the stack for subsequent calls. This would require that the "CALLEE" module be responsible for cleaning the stack NOT the "CALLER".
Thanks, Chuck. My experience is a mirror image of yours: I spent 1988 in CICS, where we used the "new" version of Cobol at the time, but have otherwise always worked in the vicinity of C.
I have an answer for
@0
from Raymond Chen. It signifies a stdcall function: Function names are decorated by a leading underscore and a trailing @-sign followed by the number of bytes of parameters taken by the function.Thanks for explaining where the compilers came from. Looking at the source code for cobc, I now think the emitted C code does vary based on which compiler was used to build cobc.
I'm sorry I was unclear in my -v request. What I meant was to add -v to the command line when you compile
DELET.CBL
.Now, to some nuts and bolts, in both senses of nuts.
sqlgstrt
, to pick just one function, needsSTDCALL
. This we know from sqlaprep.h:What that function returns and how it is called is declared in the line
which are defined in
sqlsystm.h
:i.e., it returns
int
and is called with, ye olde__stdcall
.So, this is what we know:
_WIN32
is defined. It is for VS; I'm not sure it is for minGW.CALL
._
and trailing@x
, wherex
is supposed to be the number of bytes the function uses to pass its arguments on the stack. At least, that's what Raymond Chen said 16 years ago. That would explain your linker errors about functions ending in@0
, because none of those functions use zero arguments. (Some number greater than zero should follow@
.)Any call you make to db2api should use STDCALL. If you're so inclined, you can set both bits with 72 = 64 + 8, to force static linking; otherwise, linking is deferred until run time.
We can no divide your issue into two parts:
How does that compare to what you're seeing?
Last edit: Simon Sobisch 2021-08-31
James, I tried to send an email to you directly but I suspect that your profile on sourceforge doesn' t allow people to send you emails.
can you contact me at chaat@users.sourceforge.net ?
then it might be easier to send you files / screen shots of WinMerge compares between generated C source code from MinGW and VS2019 compiles
thanks
James, I've learned a bit more about C in the last couple of days. I've run a compile on all 4 compilers using the -S option to generate the Assembler code as well as the C code. I then studied the differences in the C code using Winmerge to compare the C source code files. They are nearly identical but not exactly the same. However when I looked at the Assembler files, particularily for the x86 compilers, the output was quite different. I was concentrating on the calls to the DB2 SQLGSTRT module as well as the others. I found that VS2019 and Gnu GCC produce two different styles of Assembler code. Also using the default compiler options, it looked like the GCC compiler is using the stack differently, putting more data on the stack before the call and then doing clean up of the stack after. According the the Microsoft documentation the STDCALL is that the CALLER is to load the parameters on the stack and the CALLEE is to clean the stack before returning.
I was able to use the following compile options on the MinGW32 compiler to cause it to output Assembler code which looked very similar to the VS2019-32 output.
cobc -S -A "-mpush-args -mno-accumulate-outgoing-args -mno-stack-arg-probe -m32 -mpreferred-stack-boundary=2 -masm=intel" -fstatic-call --save-temps -Id:/DB2/SQLLIB/include/cobol_mf -Ld:/DB2/SQLLIB/lib/win32 -ldb2api delet.cbl checkerr.cbl
Even with this there is one glaring difference in the generated ASSEMBLER code. The VS2019 32 bit compiler generates the STDCALL with name mangling as follows, it prefixes the name with a single underscore character and appends @n, where n is the number of bytes pushed onto the stack. The GCC compiler mangles the name differently, the prefix is the same, but the suffix is @0 rather than the number of bytes pushed onto the stack. Hence the Linker can not find the @0 name in the library.
here are the attached files. The zip files contain the output intermediate files from the different compilers using the -S option to generate the assember source code.
MinGW-32-extra-C-options.zip
MinGW32.zip
MinGW64.zip
vs32.zip
vs64.zip
The txt files contain the output of the -vvv option on the vs32 and MinGW32 with the extra options.
MinGW32-compile-with-vvv.txt
vs32-compile-with-vvv.txt
So at this point I'm stuck as I don't know how to get the GCC compiler to generate the mangled STDCALL function names correctly.
Please let me know if you need any more information to resolve this or if this is an issue that can't be resolved.
This finding is consistent with mine, below. No matter what I do, I can't get the executable to find the function it wants. That could be be because it's looking in the wrong place, or because it's asking for the wrong symbol (an incorrectly decorated name).
Hi Chuck,
I haven't been able to get
delet.cbl
to run using Arnold's compiler, although I'm not sure where the trouble lies.Sticking just with this one program for the moment, I don't understand how to tell cobc or the C compiler to find the db2api functions. These things I do know:
db2api.lib
on the command line, along with a search path for it.For starters, here's the DLL with the "interesting" function:
That
@12
signifies a STDCALL function needing 12 bytes on the stack, but it lacks the leading underscore. Maybe that matters. The symbol is provided as both upper and lower case, and seems to have both stdcall and cdecl versions.I think the C code emitted by cobc is correct. It produces:
There's a lot of inside baseball there.
cob_resolve_cobol
looks up its argument (undecorated, it seems), and stores the function's address in thefuncvoid
member of the left-hand side. The next line invokes that function, and assigns its return code tob_2
.(
cobc
codegen note: I'm not sure the above code is strictly correct. The variablecall_SQLGSTRT
is a union with two members that evaluate to the same address. Strictly speaking, the only safe use of union members is to read the member most recently written to. One should not write to U.a and read from U.b, even if they are at the same address, because the compiler has the "right" to optimize the object code. If it sees the written variable is never read, it might eliminate the write operation, leaving the read with indeterminate data. )So, we know there is a DLL,
db2agapi.dll
on the PATH that providesSQLGSTRT
. We're pretty sure, examining the produced C, thatdelet.exe
calls the function using the STDCALL convention. If we can just get the executable to find its library, we can hope to move on to a runtime error, because I don't have a DB2 server installed. ;-)In Windows, DLLs are described by so-called "import libraries". One names the import library on the command line,. The produced executable later uses the associated DLL, which is found by searching the PATH.
Unlike Linux, on Windows there are no standard utilities to inspect the executable for its dependencies, or to trace (or control) the DLL search at run time. So I'm at a loss at the moment to say what search is being conducted, and why the function isn't found.
To review:
delet.cbl
usesCALL STDCALL "SQLGSTRT"
compiled as:
With environment:
fails as:
Also fails if the import library is explicitly defined.
same error when run:
Update: I wrote a tiny C program that only calls
sqlgstrt
. It fails to link with a noteable message:This is asking for
sqlgstrt@12
, which is good (probably), but complaining about stumbling on a 64-bit DLL. That DLL isn't in its way; there is a 32-bit version (db2app.dll
), and in any case that's not the one it needs, which isdb2agapi.dll
.No luck so far getting my simple program to link with Visual Studio, either.
Solved that particular mystery. The path to the 32-bit import library is
With that path adjusted, my simple static linked C program works: no hits, no runs, no errors.
No luck on the Cobol side, yet, but tomorrow is another day in Tara.
This bug is real, but limited to 32-bit Windows. STDCALL is used only on Windows, and is ignored by 64-bit compilation. Whether or not it will be fixed is undetermined.
The problem is that calls marked STDCALL in Cobol generate an incomplete function prototype in C, causing gcc to generate an incorrectly decorated name that subsequently cannot be resolved, either by the linker (if STATIC) or otherwise at runtime.
Reportedly the Microsoft compiler does not exhibit the same behavior, but that report hasn't been independently verified.
One workaround is to use -include C/header/file.h on the cobc command line. That lets the C header file provide the function prototypes and suppresses their generation by cobc. Inconvenient, but then workarounds usually are. Not brittle, though: if the cobol passes incorrect parameters, the generated C will not conform to the provided prototype, and a C compilation error ensues.
Diff:
As for the C stdcall declaration bug is now in [bugs:#678] lets limit this bug to the PG.
Related
Bugs: #678
I use OpenCobol IDE 4.7.6 to compile the Db2 sample program "cblsql2" under Windowx 10. Before compiling, I generate the proper COBOL source by using Db2 "prep", which I include then as input in the IDE.
I get the same errors as James:
"
C:\Users\pc\AppData\Local\Temp\cob19424_0.o:cob19424_0.c:(.text+0x251): undefined reference to
sqlgstrt' C:\Users\pc\AppData\Local\Temp\cob19424_0.o:cob19424_0.c:(.text+0x3b8): undefined reference to
sqlgaloc'...
"
I use following GCC:
C:\progs\OpenCobolIDE\GnuCOBOL\bin>gcc --version
gcc (GCC) 5.3.0
I (supposed to) include also the proper library path as proposed by James:
C:\Program Files\IBM\SQLLIB\lib\Win32
Is there any solution to solve the problem in the meanwhile? I mean, to use another C compiler etc...?
Regards
Gabor
Not sure why you want to use a different C compiler: why not just add the appropriate library path and library via its configuration options?
Ideally the complete db2prep step would be done by OCIDE, which actually is coded as seen in https://github.com/OpenCobolIDE/OpenCobolIDE/blob/master/doc/source/advanced.rst - but possibly this is disabled on Win32? Again: manually adding the library settings should help.
Gabor,
this is an email that I sent to bug #678, it may be helpful for you. As you can see below I had the most success with the 64 bit version of theVS2019 version of the GNUCOBOL compiler.
I've done some additional testing.
The DB2 precompiler can generate COBOL code for a number of different dialects. I've tested with the following
db2 prep deletx.sqb bindfile target ANSI_COBOL --> this generates the calls as "CALL "sqlg" where sqlg is the DB2 module
db2 prep deletx.sqb bindfile target mfcob --> this generates the calls as "CALL DB2API"sqlg" where sqlg is the DB2 module and DB2API is set to CALL-CONVENTION 74.
for testing purposes I changed the DB2API value to 64 so that I could control static vs dynamic via compile time parameters.
So each version of the compiler has 4 variations mfcob or ANSI_COBOL and static or dynamic calls.
VS2019-64 bit MF static successful
MF dynamic successful
ANSI static successful
ANSI dynamic successful
VS2019-32 bit MF static successful
MF dynamic failed
ANSI static failed
ANSI dynamic failed
MinGW-64 bit MF static failed
MF dynamic successful
ANSI static failed
ANSI dynamic successful
MinGW-32 bitt MF static link error (this is the prototype issue)
MF dynamic failed
ANSI static failed
ANSI dynamic failed
So there is a difference between the MinGW and Visual Studio versions of the GNUCOBOL compiler. The differences only are present when using static calls to the DB2 modules.
That being said, perhaps it's not worth pursuing why these differences exist. So if someone wants to mark this ticket as closed that would be ok with me.
Perhaps the issue with the prototype not including the parameters used in the CALL statement could potentially impact other applications which link to libraries created with MSVC, so that might we worth investigating.
Also the DB2 precompiler has an option to use "TARGET ibmcob". It generates the same output as ANSI_COBOL so no need to test that.
What targets does
db2 prep
supports? How do they differ in code generation?Is this bug for the PG manual now finished ?
If not what exactly is required to go into the manual replace what and where ?
Hello,
sorry for the late answer. I try recently to use the OCIDE as Simon
proposed. It seems to work fine with the preprocessor, but the generated
code has a couple of errors which I must to check.
Am Sa., 15. Mai 2021 um 17:04 Uhr schrieb Vincent (Bryan) Coen vcoen@users.sourceforge.net:
Related
Bugs: #673
My head hurts - So "exactly" what should the manual be saying?
EXACTLY. ---- and make sure you read the manual for CALL.