Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Linking DXE3 with libraries

9 views
Skip to first unread message

Andris Pavenis (andris.pavenis@iki.fi) [via djgpp@delorie.com]

unread,
Jan 28, 2023, 6:02:17 AM1/28/23
to DJGPP List (E-mail)
Thread GXE3 with std::vector has grown bit too long, so I'm beginning a new one

I have not used DXE myself, so my thoughts could be inaccurate


Some general thoughts:

- DXE loader has no way to found symbols of running executable (which requests to load DXE) unless
one tells where they are located

- linking DXE directly with libraries (like libstdcxx.a or libc.a) will cause duplicate copy of
symbols. That is going to cause problems when library have global state. I have seen similar
problems, which have often caused crash of program) for example in Linux, when direct of indirect
dependencies causes 2 different versions of shared library to be loaded:

- there is a wat how to provide symbols of executable (including ones from libraries) when loading DXE:

     - http://www.delorie.com/djgpp/v2faq/faq22_15.html

     - https://www.delorie.com/djgpp/doc/utils/utils_20.html


I tried to run DXE3RES under x86_64 Linux, but is seems that DXE3RES is broken when compiled for
64-bit systems:

[andris@ap ~]$ i686-pc-msdosdjgpp-dxe3res -o tmp.c /usr/i686-pc-msdosdjgpp/lib/libc.a
/usr/i686-pc-msdosdjgpp/lib/libc.a: Exec format error


Questions which should be answered to use DXE3 (I do not have answers myself, but can be easily
tested, I'm not going to test myself):

- are constructors and destructors of global objects executed, when these objects belong to DXE? It
seems from source code, that they could. It is perhaps safer to verify that it actually works


I think one should avoid linking DXE with library directly, but provide symbol list generated by
DXE3RES (or manually) instead. Exception could be if DXE module is only user of library, but
program itself does not use it


Andris

Frank Sapone (emoaddict15@gmail.com) [via djgpp@delorie.com]

unread,
Jan 28, 2023, 6:32:16 AM1/28/23
to dj...@delorie.com
Good Morning Andris,

> - DXE loader has no way to found symbols of running executable (which
> requests to load DXE) unless one tells where they are located
>
Correct, you need a DXE_EXPORT_TABLE with DXE_EXPORT(func/var) to
resolve at run time.  See
https://bitbucket.org/neozeed/q2dos/src/master/dos/dxe.c for an example
if interested.
> - linking DXE directly with libraries (like libstdcxx.a or libc.a)
> will cause duplicate copy of symbols. That is going to cause problems
> when library have global state. I have seen similar problems, which
> have often caused crash of program) for example in Linux, when direct
> of indirect dependencies causes 2 different versions of shared library
> to be loaded:
I'm not quite sure how it works exactly, but with C we just resolve
everything like above, which seems to be the correct way.  With C++
things are trickier and we have to do -lstdcxx -lgcc or we get mangled
names that can't even be exported.
> - are constructors and destructors of global objects executed, when
> these objects belong to DXE? It seems from source code, that they
> could. It is perhaps safer to verify that it actually works
>
I believe so, yes.
>
> I think one should avoid linking DXE with library directly, but
> provide symbol list generated by DXE3RES (or manually) instead.
> Exception could be if DXE module is only user of library, but program
> itself does not use it
>
>
OK, but how do we deal with with the above C++ problem?

I will say that considering it is DOS the likliehood of someone swapping
DXEs around is pretty slim, but I understand why you want to make it
right.  I'd love to contribute code or even something insightful to
these problems but I am not a compiler/compiler tools programmer.  I
also apologize in advance for any dumb or obvious questions I may ask as
a result of this conversation.  I just DXE3GEN like I have been for
years and use the DXE_EXPORT... stuff to resolve at runtime.  This works
quite well for C programs, but C++ requires additional work and it's not
obvious what to do.

Frank

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 28, 2023, 6:39:36 AM1/28/23
to dj...@delorie.com
On 1/28/23, Andris Pavenis (andris....@iki.fi) [via
dj...@delorie.com] <dj...@delorie.com> wrote:
> I have not used DXE myself, so my thoughts could be inaccurate
>
> Some general thoughts:
>
> - DXE loader has no way to found symbols of running executable (which
> requests to load DXE) unless
> one tells where they are located

General issue

> - linking DXE directly with libraries (like libstdcxx.a or libc.a) will
> cause duplicate copy of symbols.

Linking with libc.a can be especially problematic.

However, if you have a dxe written in c++, and especially if your
exe is C-only, linking dxe with libstdc++ is a good thing

As for duplication of symbols: Well that's a known general issue
because djgpp libc is a static library.

> I tried to run DXE3RES under x86_64 Linux, but is seems that DXE3RES is
> broken when compiled for
> 64-bit systems:
>
> [andris@ap ~]$ i686-pc-msdosdjgpp-dxe3res -o tmp.c
> /usr/i686-pc-msdosdjgpp/lib/libc.a
> /usr/i686-pc-msdosdjgpp/lib/libc.a: Exec format error

You should run dxe3res against a dxe module, not an archive,
like: dxe3gen -o tmp.c my.dxe

As for rest of your notes, I will try looking at them later.

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 28, 2023, 7:04:55 AM1/28/23
to dj...@delorie.com
>> I tried to run DXE3RES under x86_64 Linux, but is seems that DXE3RES is
>> broken when compiled for
>> 64-bit systems:
>>
>> [andris@ap ~]$ i686-pc-msdosdjgpp-dxe3res -o tmp.c
>> /usr/i686-pc-msdosdjgpp/lib/libc.a
>> /usr/i686-pc-msdosdjgpp/lib/libc.a: Exec format error
>
> You should run dxe3res against a dxe module, not an archive,
> like: dxe3gen -o tmp.c my.dxe

Fixing my silly typo:
dxe3res -o tmp.c my.dxe

Andris Pavenis (andris.pavenis@iki.fi) [via djgpp@delorie.com]

unread,
Jan 28, 2023, 11:20:26 AM1/28/23
to dj...@delorie.com
On 1/28/23 13:28, Frank Sapone (emoad...@gmail.com) [via dj...@delorie.com] wrote:
> Good Morning Andris,
>
>> - DXE loader has no way to found symbols of running executable (which requests to load DXE)
>> unless one tells where they are located
>>
> Correct, you need a DXE_EXPORT_TABLE with DXE_EXPORT(func/var) to resolve at run time.  See
> https://bitbucket.org/neozeed/q2dos/src/master/dos/dxe.c for an example if interested.
>> - linking DXE directly with libraries (like libstdcxx.a or libc.a) will cause duplicate copy of
>> symbols. That is going to cause problems when library have global state. I have seen similar
>> problems, which have often caused crash of program) for example in Linux, when direct of
>> indirect dependencies causes 2 different versions of shared library to be loaded:
> I'm not quite sure how it works exactly, but with C we just resolve everything like above, which
> seems to be the correct way. With C++ things are trickier and we have to do -lstdcxx -lgcc or we
> get mangled names that can't even be exported.

The following could work (I only tried under Linux, so for native DJGPP and/or other libraries one
should modify script):

[andris@ap dxe]$ cat mk_lib_export_table.sh
#! /bin/sh

i686-pc-msdosdjgpp-nm --extern-only /usr/i686-pc-msdosdjgpp/lib/libstdc++.a |\
awk '/^[0-9A-H]/ && ($2 == "W" || $2 == "T") { print $3 }' | sort | uniq |\
sed -e 's/^_//' >symbols.tmp

(
   echo "#include <sys/dxe.h>"
   echo ""
   awk '{ print "extern void ", $1, "();"}' symbols.tmp
   echo ""
   echo "DXE_EXPORT_TABLE (exported_symbols)"
   awk '{print "  DXE_EXPORT(",$1,")"}' symbols.tmp
   echo "DXE_EXPORT_END"
   echo ""
   echo "int main() { return 0; }"
) | i686-pc-msdosdjgpp-gcc -v -O0 -fno-builtin -x c - -l stdc++


Only added main() to avoid having linker error.

Also linked executable to verify that symbols are extracted correctly.

One can there put code to register generated export table instead.


I only tried gcc-12.2.0.

Output of script is given below

Andris


[andris@ap dxe]$ ./mk_lib_export_table.sh
Using built-in specs.
COLLECT_GCC=i686-pc-msdosdjgpp-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/lto-wrapper
Kohde: i686-pc-msdosdjgpp
Configured with: ../gcc-12.2.0/configure --prefix=/usr --libexecdir=/usr/lib
--target=i686-pc-msdosdjgpp --enable-languages=c,c++,fortran,objc,obj-c++ --enable-shared
--enable-static --enable-th
reads=no --with-system-zlib --with-isl --enable-lto --disable-libgomp --disable-multilib
--enable-checking=release --disable-libstdcxx-pch --enable-libstdcxx-filesystem-ts
--disable-install-libi
berty
Säiemalli: single
Supported LTO compression algorithms: zlib zstd
gcc-versio 12.2.0 (GCC)
COLLECT_GCC_OPTIONS='-v' '-O0' '-fno-builtin' '-mtune=generic' '-march=pentiumpro' '-dumpdir' 'a-'
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/cc1 -quiet -v -remap - -quiet -dumpdir a- -dumpbase -
-mtune=generic -march=pentiumpro -O0 -version -fno-builtin -o /tmp/cchC3Spt.s
GNU C17 (GCC) versio 12.2.0 (i686-pc-msdosdjgpp)
       käännetty GNU C:n versiolla 12.1.1 20220730, GMP version 6.2.1, MPFR version 4.1.0-p13, MPC
version 1.2.1, isl version isl-0.25-GMP

warning: MPFR-otsakeversio 4.1.0-p13 eroaa kirjastoversiosta 4.1.1-p1.
warning: MPC-otsakeversio 1.2.1 eroaa kirjastoversiosta 1.3.1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
jätetään puuttuva hakemisto ”/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/include-fixed” huomiotta
#include "..." -haku alkaa täältä:
#include <...> -haku alkaa täältä:
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/include
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/sys-include
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/include
Hakulistan loppu.
GNU C17 (GCC) versio 12.2.0 (i686-pc-msdosdjgpp)
       käännetty GNU C:n versiolla 12.1.1 20220730, GMP version 6.2.1, MPFR version 4.1.0-p13, MPC
version 1.2.1, isl version isl-0.25-GMP

warning: MPFR-otsakeversio 4.1.0-p13 eroaa kirjastoversiosta 4.1.1-p1.
warning: MPC-otsakeversio 1.2.1 eroaa kirjastoversiosta 1.3.1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 80ce3899c685b09c12b70d8ca8f6fbac
COLLECT_GCC_OPTIONS='-v' '-O0' '-fno-builtin' '-mtune=generic' '-march=pentiumpro' '-dumpdir' 'a-'
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/bin/as -v -o /tmp/ccIgzJio.o
/tmp/cchC3Spt.s
GNU assembler version 2.34 (i686-pc-msdosdjgpp) using BFD version (GNU Binutils) 2.34
COMPILER_PATH=/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/:/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/:/usr/lib/gcc/i686-pc-msdosdjgpp/:/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/:/usr/lib/gcc/i686-pc-msdosd
jgpp/:/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/bin/
LIBRARY_PATH=/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/:/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/lib/

COLLECT_GCC_OPTIONS='-v' '-O0' '-fno-builtin' '-mtune=generic' '-march=pentiumpro' '-dumpdir' 'a.'
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/collect2 -plugin
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/lto-wrapper -plugin-opt=-freso
lution=/tmp/cc8Rf9cH.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/lib/c
rt0.o -L/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0
-L/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/lib /tmp/ccIgzJio.o
-lstdc++ -lgcc -lc -lgcc
COLLECT_GCC_OPTIONS='-v' '-O0' '-fno-builtin' '-mtune=generic' '-march=pentiumpro' '-dumpdir' 'a.'
/usr/lib/gcc/i686-pc-msdosdjgpp/12.2.0/../../../../i686-pc-msdosdjgpp/bin/stubify -v a.out
stubify for djgpp V2.X executables, Copyright (C) 1995-2003 DJ Delorie
stubify: a.out -> a.000 -> a.exe



0 new messages