LDP/LDP/howto/docbook/GCC-HOWTO.sgml

2538 lines
77 KiB
Plaintext

<!DOCTYPE Article PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!--
TODO:
1) pointer to Assembly-HOWTO in appropriate place
2) cover shared library building on glibc 2.1, mention libtool, point
to glibc-howto
-->
<Article>
<ArtHeader>
<Title>The Linux GCC HOWTO</Title>
<AUTHOR>
<!-- be nice to find out the rest of the allowable content for this element -->
<FirstName>Daniel</FirstName>
<Surname>Barlow</Surname>
<Affiliation><OrgName>Linux Documentation Project</OrgName></Affiliation>
</AUTHOR>
<Address><Email>daniel.barlow@linux.org</Email></Address>
<Edition>2.0</Edition>
<PubDate>May 1999</PubDate>
<Abstract>
<Para>
This document covers how to set up the GNU C compiler and development
libraries under Linux, and gives an overview of compiling, linking,
running and debugging programs under it. Most of the material in it
has been taken from Mitch D'Souza's GCC-FAQ or the ELF-HOWTO - it
replaces both documents.
</Para>
<Para>
This is the first version to be written in DocBook instead of the old
Linuxdoc format, and may contain markup errors. Please let me know if
you find anything worng.
</Para>
<Para>
As can be determined from the long times between updates of this
document, I don't actually have the time or inclination to maintain it
much. If you have, can, and want to, drop me some email describing
what you'd do with it and why you think you'd be good at it.
</Para>
</Abstract>
</ArtHeader>
<Sect1>
<Title>Preliminaries</Title>
<Sect2>
<Title>ELF vs. a.out, libc 5 vs 6</Title>
<Para>
Three years ago when this document was first created, I opened this
section by saying "Linux development is in a state of flux right now"
and going on to describe how ELF was replacing the older a.out binary format.
</Para>
<Para>
It still is in a state of flux. It always will be. Though that
particular change is long since past, development of the Linux kernel
and the surrounding system continues to happen, and things change for
developers as a result. So it's a good idea to know upfront what kind
of system you have in front of you.
</Para>
<Para>
The possible candidates, in order of age, are
<ItemizedList>
<ListItem><Para>libc 4, a.out: very old systems</Para></ListItem>
<ListItem><Para>libc 5, ELF: Red Hat 4.2, Debian 2.0</Para></ListItem>
<ListItem><Para>libc 6 (a.k.a glibc 2), ELF:
Red Hat 5 - 5.2, Debian 2.1 </Para></ListItem>
<ListItem><Para>libc 6.1,(a.k.a glibc 2.1) ELF: Red Hat 6 </Para></ListItem>
</ItemizedList>
How to tell? The simplest approach is to pick a binary that you
consider is typical (e.g. <filename>/bin/ls</filename> and run
<command>ldd</command> on it. One of the listed libraries should be
libc - check its version number.
<screen>
<prompt>$</prompt> <userinput>ldd /bin/ls</userinput>
libc.so.6 => /lib/libc.so.6 (0x4000e000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
</screen>
<para>This document was created on a <ulink
url="http://www.debian.org">Debian</ulink> 2.1 system, so no surprise
there. </para>
<para> It's entirely possible that the system you're using may have a
mix of different versions on it. What you probably want to know in
that case is the version that its C development environment is set up
for, so you're best off compiling "hello world" and running
<command>ldd</command> on the output thus created. Note that for
historical reasons, <command>gcc</command> defaults to an output file
called <filename>a.out</filename> even on ELF systems, so don't assume
anything from that.
</para>
</Sect2>
<Sect2 id="index.3">
<Title>Administrata </Title>
<Para>
The copyright information and like legalese can be found at the
<Emphasis>end</Emphasis> of this document, together with the statutory
warnings about asking dumb questions on Usenet, revealing your
ignorance of the C language by reporting bugs which aren't, and
picking your nose while chewing gum.
</Para>
</Sect2>
<Sect2>
<Title>Typography</Title>
<Para>
If you're reading this in Postscipt, dvi, or html format, you get to
see a little more font variation than people with the plain text
version. In particular, filenames, commands, command output and
source code excerpts are set in some form of <Literal
remap="tt">typewriter</Literal> font, whereas `variables' and random
things that need emphasizing are <Emphasis>emphasized</Emphasis>.
</Para>
<Para>
You also get a usable index. In dvi or postscript, the numbers in the
index are section numbers. In HTML they're just sequentially assigned
numbers that you can click on. In the plain text version, they really
are just numbers. Get an upgrade!
</Para>
<Para>
The Bourne (rather than C) shell syntax is used in examples. C shell
users will want to use
<Screen>
<Prompt>%</Prompt> setenv FOO bar
</Screen>
where I have written
<Screen>
<Prompt>$</Prompt> FOO=bar; export FOO
</Screen>
</Para>
<Para>
If the prompt shown is <Literal remap="tt">&num;</Literal> rather than <Literal remap="tt">&dollar;</Literal>, the command shown
will probably only work as root. Of course, I accept no
responsibility for anything that happens to your system as a result of
trying these examples. Have a nice day <Literal remap="tt">:-)</Literal>
</Para>
</Sect2>
</Sect1>
<Sect1>
<Title>Where to get things</Title>
<Para>In the three years since the first `HOWTO' version of this,
useful Linux distributions have become prevalent. So, where once I'd
have spent pages listing FTP sites and hours updating (failing to
update) version numbers and directory names, now I will simply say -
your distribution maintainer should be taking care of this for you.
If you don't have, say, gcc installed, find the RPM or the deb
packages that contain it, and install it. If that isn't an option
because you don't have a friendly distribution, you've almost
certainly been using Linux long enough that you don't need me to tell
you where to find things anyway.
<Sect2>
<Title>This document</Title>
<Para> You're reading it. You probably have it already.</Para>
<para>This document is one of the Linux HOWTO series, so is probably
already installed somewhere in <filename>/usr/doc</filename> if you're
reading this on a linux box. Failing that, from all Linux HOWTO
repositories (try <ULink URL="http://metalab.unc.edu/LDP/HOWTO/"
>Metalab</ULink>) and (possibly in a slightly newer version) at my
personal web site <ULink URL="http://www.telent.net/linux/linux/gcc-howto/"
>www.telent.net</ULink >.
</Para>
</Sect2>
<Sect2 id="index.4">
<Title>Other documentation
</Title>
<Para>
The official documentation for gcc is in the source distribution
(see below) as texinfo files, and as <Literal remap="tt">.info</Literal> files. If you have a fast
network connection, a cdrom, or a reasonable amount of patience, you
can just untar it and copy the relevant bits into <Literal remap="tt">/usr/info</Literal>. If not,
you may find them at <ULink
URL="ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"
>tsx-11</ULink
>, but
not necessarily always the latest version.
</Para>
<Para>
<Anchor id="index.5">
</Para>
<Para>
There are two source of documentation for libc. GNU libc comes
with info files which describe Linux libc fairly accurately except for
stdio. Also, the <ULink
URL="ftp://sunsite.unc.edu/pub/Linux/docs/"
>manpages</ULink
> archive are written for
Linux and describe a lot of system calls (section 2) and libc
functions (section 3).
</Para>
</Sect2>
<Sect2 id="index.6">
<Title>GCC </Title>
<Para>
There are two answers.
</Para>
<Para>
(a) The official Linux GCC distribution can always be found in binary
(ready-compiled) form at <ULink
URL="ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"
>&#65533;</ULink
>. At the time of
writing, 2.7.2 (<Literal remap="tt">gcc-2.7.2.bin.tar.gz</Literal>) is the latest version.
</Para>
<Para>
(b) The latest source distribution of GCC from the Free Software
Foundation can be had from <ULink
URL="ftp://prep.ai.mit.edu/pub/gnu/"
>GNU archives</ULink
>. This is not necessarily always
the same version as above, though it is just now. The Linux GCC
maintainer(s) have made it easy for you to compile the latest version
available yourself --- the <Literal remap="tt">configure</Literal> script should set it all up
for you. Check <ULink
URL="ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"
>tsx-11</ULink
> as well, for patches
which you may want to apply.
</Para>
<Para>
To compile anything non-trivial (and quite a few trivial things also)
you will also need the
</Para>
</Sect2>
<Sect2 id="index.7">
<Title>C library and header files
</Title>
<Para>
What you want here depends on (i) whether your system is ELF or
a.out, and (ii) which you want it to be. If you're upgrading from
libc 4 to libc 5, you are recommended to look at the ELF-HOWTO from
approximately the same place as you found this document.
</Para>
<Para>
These are available from <ULink
URL="ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"
>tsx-11</ULink
> as above:
</Para>
<Para>
<VariableList>
<VarListEntry>
<Term><Literal remap="tt">libc-5.2.18.bin.tar.gz</Literal></Term>
<ListItem>
<Para>
--- ELF shared library images, static
libraries and include files for the C and maths libraries.
</Para>
</VarListEntry>
<VarListEntry>
<Term><Literal remap="tt">libc-5.2.18.tar.gz</Literal></Term>
<ListItem>
<Para>
--- Source for the above. You will also
need the <Literal remap="tt">.bin.</Literal> package for the header files. If you are
deliberating whether to compile the C library yourself or use the
binaries, the right answer in nearly all cases is to use the binaries.
You will however need to roll your own if you want NYS or shadow
password support.
</Para>
</VarListEntry>
<VarListEntry>
<Term><Literal remap="tt">libc-4.7.5.bin.tar.gz</Literal></Term>
<ListItem>
<Para>
--- a.out shared library images and static
libraries for version 4.7.5 of the C library and friends. This is
designed to coexist with the libc 5 package above, but is only really
necessary if you wish to keep using/developing a.out format programs.
</Para>
</VarListEntry>
</VariableList>
</Para>
</Sect2>
<Sect2 id="index.8">
<Title>Associated tools (as, ld, ar, strings etc)
</Title>
<Para>
From <ULink
URL="ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"
>tsx-11</ULink
>, just like everything
else so far. The current version is <Literal remap="tt">binutils-2.6.0.2.bin.tar.gz</Literal>.
</Para>
<Para>
Note that the binutils are only available in ELF, the current libc
version is in ELF and the a.out libc is happiest when used in
conjunction with an ELF libc. C library development is moving
emphatically ELFwards, and unless you have really good reasons for
needing a.out things you're encouraged to follow suit.
</Para>
</Sect2>
</Sect1>
<Sect1>
<Title>GCC installation and setup</Title>
<Sect2 id="index.12">
<Title>GCC versions
</Title>
<Para>
You can find out what GCC version you're running by typing <Literal remap="tt">gcc
-v</Literal> at the shell prompt. This is also a fairly reliable way to
find out whether you are set up for ELF or a.out. On my system it does
</Para>
<Para>
<Screen>
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs
gcc version 2.7.2
</Screen>
</Para>
<Para>
The key things to note here are
<ItemizedList>
<ListItem>
<Para>
<Literal remap="tt">i486</Literal>. This indicates that the gcc you are using was built
for a 486 processor --- you might have 386 or 586 instead. All of
these chips can run code compiled for each of the others; the
difference is that the 486 code has added padding in some places so
runs faster on a 486. This has no detrimental performance effect on a
386, but does make the binaries slightly larger.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">box</Literal>. This is <Emphasis>not</Emphasis> at all important, and may say
something else (such as <Literal remap="tt">slackware</Literal> or <Literal remap="tt">debian</Literal>) or nothing at
all (so that the complete directory name is <Literal remap="tt">i486-linux</Literal>). If you
build your own gcc, you can set this at build time for cosmetic
effect. Just like I did <Literal remap="tt">:-)</Literal>
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">linux</Literal>. This may instead say <Literal remap="tt">linuxelf</Literal> or
<Literal remap="tt">linuxaout</Literal>, and, confusingly, the meaning of each varies according
to the version that you are using.
<ItemizedList>
<ListItem>
<Para>
<Literal remap="tt">linux</Literal> means ELF if the version is 2.7.0 or newer, a.out
otherwise.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">linuxaout</Literal> means a.out. It was introduced as a target
when the definition of <Literal remap="tt">linux</Literal> was changed from a.out to ELF, so
you won't see any <Literal remap="tt">linuxaout</Literal> gcc older than 2.7.0.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">linuxelf</Literal> is obsolete. It is generally a version of gcc
2.6.3 set to produce ELF executables. Note that gcc 2.6.3 has known
bugs when producing code for ELF --- an upgrade is advisable.
</Para>
</ListItem>
</ItemizedList>
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">2.7.2</Literal> is the version number.
</Para>
</ListItem>
</ItemizedList>
</Para>
<Para>
So, in summary, I have gcc 2.7.2 producing ELF code. Quelle surprise.
</Para>
</Sect2>
<Sect2>
<Title>Where did it go?</Title>
<Para>
If you installed gcc without watching, or if you got it as part of
a distribution, you may like to find out where it lives in the
filesystem. The key bits are
</Para>
<Para>
<ItemizedList>
<ListItem>
<Para>
<Literal remap="tt">/usr/lib/gcc-lib/</Literal><Emphasis>target</Emphasis><Literal remap="tt">/</Literal><Emphasis>version</Emphasis><Literal remap="tt">/</Literal> (and
subdirectories) is where most of the compiler lives. This includes
the executable programs that do actual compiling, and some
version-specific libraries and include files.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">/usr/bin/gcc</Literal> is the compiler driver --- the bit that you
can actually run from the command line. This can be used with
multiple versions of gcc provided that you have multiple compiler
directories (as above) installed. To find out the default version it
will use, type <Literal remap="tt">gcc -v</Literal>. To force it to another version, type
<Literal remap="tt">gcc -V </Literal><Emphasis>version</Emphasis>. For example
<Screen>
# gcc -v
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs
gcc version 2.7.2
# gcc -V 2.6.3 -v
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.6.3/specs
gcc driver version 2.7.2 executing gcc version 2.6.3
</Screen>
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">/usr/</Literal><Emphasis>target</Emphasis><Literal remap="tt">/(bin&verbar;lib&verbar;include)/</Literal>. If you have
multiple targets installed (for example, a.out and elf, or a
cross-compiler of some sort, the libraries, binutils (<Literal remap="tt">as</Literal>, <Literal remap="tt">ld</Literal>
and so on) and header files for the non-native target(s) can be found
here. Even if you only have one kind of gcc installed you might find
anyway that various bits for it are kept here. If not, they're in
<Literal remap="tt">/usr/(bin&verbar;lib&verbar;include)</Literal>.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">/lib/</Literal>,<Literal remap="tt">/usr/lib</Literal> and others are library directories for
the native system. You will also need <Literal remap="tt">/lib/cpp</Literal> for many
applications (X makes quite a lot of use of it) --- either copy it
from <Literal remap="tt">/usr/lib/gcc-lib/</Literal><Emphasis>target</Emphasis><Literal remap="tt">/</Literal><Emphasis>version</Emphasis><Literal remap="tt">/</Literal> or
make a symlink pointing there.
</Para>
</ListItem>
</ItemizedList>
</Para>
</Sect2>
<Sect2 id="index.17">
<Title>Where are the header files?
</Title>
<Para>
Apart from whatever you install yourself under
<Literal remap="tt">/usr/local/include</Literal>, there are three main sources of header
files in Linux:
</Para>
<Para>
<ItemizedList>
<ListItem>
<Para>
Most of <Literal remap="tt">/usr/include/</Literal> and its subdirectories are
supplied with the libc binary package from H J Lu. I say `most'
because you may also have files from other sources (<Literal remap="tt">curses</Literal> and
<Literal remap="tt">dbm</Literal> libraries, for example) in here, especially if you are using
the newest libc distribution (which doesn't come with curses or dbm,
unlike the older ones).
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">/usr/include/linux</Literal> and <Literal remap="tt">/usr/include/asm</Literal> (for
the files <Literal remap="tt">&lt;linux/*.h&gt;</Literal> and <Literal remap="tt">&lt;asm/*.h&gt;</Literal>)
should be symbolic links to the directories
<Literal remap="tt">linux/include/linux</Literal> and <Literal remap="tt">linux/include/asm</Literal> in the
kernel source distribution. You need to install these if you plan to
do <Emphasis>any</Emphasis> non-trivial development; they are not just there for
compiling the kernel.
You might find also that you need to do <Literal remap="tt">make config</Literal> in the
kernel directory after unpacking the sources. Many files depend on
<Literal remap="tt">&lt;linux/autoconf.h&gt;</Literal> which otherwise may not exist, and in
some kernel versions <Literal remap="tt">asm</Literal> is a symbolic link itself and only
created at <Literal remap="tt">make config</Literal> time.
So, if you unpack your kernel sources under <Literal remap="tt">/usr/src/linux</Literal>, that's
<Screen>
$ cd /usr/src/linux
$ su
# make config
[answer the questions. Unless you're going to go on and build the kernel
it doesn't matter _too_ much what you say]
# cd /usr/include
# ln -s ../src/linux/include/linux .
# ln -s ../src/linux/include/asm .
</Screen>
</Para>
</ListItem>
<ListItem>
<Para>
Files such as <Literal remap="tt">&lt;float.h&gt;</Literal>, <Literal remap="tt">&lt;limits.h&gt;</Literal>,
<Literal remap="tt">&lt;varargs.h&gt;</Literal>, <Literal remap="tt">&lt;stdarg.h&gt;</Literal> and
<Literal remap="tt">&lt;stddef.h&gt;</Literal> vary according to the compiler version, so are
found in <Literal remap="tt">/usr/lib/gcc-lib/i486-box-linux/2.7.2/include/</Literal> and
places of that ilk.
</Para>
</ListItem>
</ItemizedList>
</Para>
</Sect2>
<Sect2>
<Title>Building cross compilers</Title>
<Sect3>
<Title>Linux as the target platform</Title>
<Para>
Assuming you have obtained the source code to gcc, usually you can
just follow the instructions given in the INSTALL file for GCC. A
<Literal remap="tt">configure --target=i486-linux --host=XXX</Literal> on platform <Literal remap="tt">XXX</Literal>
followed by a <Literal remap="tt">make</Literal> should do the trick. Note that you will need
the Linux includes, the kernel includes, and also to build the cross
assembler and cross linker from the sources in <ULink
URL="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/"
>&#65533;</ULink
>.
</Para>
</Sect3>
<Sect3>
<Title>Linux as the source platform, MSDOS as the target</Title>
<Para>
Ugh. Apparently this is somewhat possible by using the "emx"
package or the "go" extender. Please look at <ULink
URL="ftp://sunsite.unc.edu/pub/Linux/devel/msdos"
>&#65533;</ULink
>.
</Para>
<Para>
I have not tested this and cannot vouch for its abilities.
</Para>
</Sect3>
</Sect2>
</Sect1>
<Sect1>
<Title>Porting and Compiling</Title>
<Sect2 id="index.25">
<Title>Automatically defined symbols
</Title>
<Para>
You can find out what symbols your version of gcc defines
automatically by running it with the <Literal remap="tt">-v</Literal> switch. For example,
mine does:
</Para>
<Para>
<Screen>
$ echo 'main(){printf("hello world\n");}' | gcc -E -v -
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs
gcc version 2.7.2
/usr/lib/gcc-lib/i486-box-linux/2.7.2/cpp -lang-c -v -undef
-D__GNUC__=2 -D__GNUC_MINOR__=7 -D__ELF__ -Dunix -Di386 -Dlinux
-D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__i386
-D__linux -Asystem(unix) -Asystem(posix) -Acpu(i386)
-Amachine(i386) -D__i486__ -
</Screen>
</Para>
<Para>
If you are writing code that uses Linux-specific features, it is a
good idea to enclose the nonportable bits in
</Para>
<Para>
<Screen>
#ifdef __linux__
/* ... funky stuff ... */
#endif /* linux */
</Screen>
</Para>
<Para>
Use <Literal remap="tt">&lowbar;&lowbar;linux&lowbar;&lowbar;</Literal> for this purpose, <Emphasis>not</Emphasis> <Literal remap="tt">linux</Literal>.
Although the latter is defined, it is not POSIX compliant.
</Para>
</Sect2>
<Sect2>
<Title>Compiler invocation</Title>
<Para>
The documentation for compiler switches is the gcc info page (in
Emacs, use <Literal remap="tt">C-h i</Literal> then select the `gcc' option). Your distributor
may not have packed this with your system, or you may have an old
version; the best thing to do in this case is to download the gcc
source archive from <ULink
URL="ftp://prep.ai.mit.edu/pub/gnu"
>&#65533;</ULink
> or one
of its mirrors, and copy them out of it.
</Para>
<Para>
The gcc manual page (<Literal remap="tt">gcc.1</Literal>) is, generally speaking, out of date.
It will warn you of this when you try to look at it.
</Para>
<Sect3 id="index.26">
<Title>Compiler flags
</Title>
<Para>
gcc can be made to optimize its output code by adding
<Literal remap="tt">-O</Literal><Emphasis>n</Emphasis> to its command line, where <Emphasis>n</Emphasis> is an optional small
integer. Meaningful values of <Emphasis>n</Emphasis>, and their exact effect, vary
according to the exact version, but typically it ranges from 0 (no
optimization) to 2 (lots) or 3 (lots and lots).
</Para>
<Para>
Internally, gcc translates these to a series of <Literal remap="tt">-f</Literal> and <Literal remap="tt">-m</Literal>
options. You can see exactly which <Literal remap="tt">-O</Literal> levels map to which
options by running gcc with the <Literal remap="tt">-v</Literal> flag and the (undocumented)
<Literal remap="tt">-Q</Literal> flag. For example, for <Literal remap="tt">-O2</Literal>, mine says
</Para>
<Para>
<Screen>
enabled: -fdefer-pop -fcse-follow-jumps -fcse-skip-blocks
-fexpensive-optimizations
-fthread-jumps -fpeephole -fforce-mem -ffunction-cse -finline
-fcaller-saves -fpcc-struct-return -frerun-cse-after-loop
-fcommon -fgnu-linker -m80387 -mhard-float -mno-soft-float
-mno-386 -m486 -mieee-fp -mfp-ret-in-387
</Screen>
</Para>
<Para>
Using an optimization level higher than your compiler supports
(e.g. <Literal remap="tt">-O6</Literal>) will have exactly the same effect as using the highest
level that it <Emphasis>does</Emphasis> support. Distributing code which is set to
compile this way is a poor idea though --- if further optimisations
are incorporated into future versions, you (or your users) may find
that they break your code.
</Para>
<Para>
<Anchor id="index.28">
Users of gcc 2.7.0 thru 2.7.2 should note that there is a bug in
<Literal remap="tt">-O2</Literal> on these. Specifically, strength reduction doesn't work. A
patch can be had to fix this if you feel like recompiling gcc,
otherwise make sure that you always compile with <Literal remap="tt">-fno-strength-reduce</Literal>
</Para>
<Sect4>
<Title>Processor-specific</Title>
<Para>
There are other <Literal remap="tt">-m</Literal> flags which aren't turned on by any variety of
<Literal remap="tt">-O</Literal> but are nevertheless useful. Chief among these are <Literal remap="tt">-m386</Literal>
and <Literal remap="tt">-m486</Literal>, which tell gcc to favour the 386 or 486 respectively.
Code compiled with one of these will still work on the other; 486 code
is bigger, but otherwise not slower on the 386.
</Para>
<Para>
There is currently no <Literal remap="tt">-mpentium</Literal> or <Literal remap="tt">-m586</Literal>. Linus suggests
using <Literal remap="tt">-m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2</Literal>,
to get 486 code optimisations but without the big gaps for alignment
(which the pentium doesn't need). Michael Meissner (of Cygnus) says
</Para>
<Para>
<QUOTE
>My hunch is that <Literal remap="tt">-mno-strength-reduce</Literal> also results in faster code on
the x86 (note, I'm not talking about the strength reduction bug, which
is another issue). This is because the x86 is rather register starved
(and GCC's method of grouping registers into spill registers vs. other
registers doesn't help either). Strength reduction typically results
in using additional registers to replace multiplications with
addition. I also suspect <Literal remap="tt">-fcaller-saves</Literal> may also be a loss.</QUOTE
>
<QUOTE
>Another hunch is that <Literal remap="tt">-fomit-frame-pointer</Literal> might or might not be a
win. On the one hand, it can mean that another register is available
for allocation. On the other hand, the way the x86 encodes its
instruction set, means that stack relative addresses take more space
instead of frame relative addresses, which means slightly less Icache
availble to the program. Also, <Literal remap="tt">-fomit-frame-pointer</Literal>, means that the
compiler has to constantly adjust the stack pointer after calls, while
with a frame, it can let the stack accumulate for a few calls.</QUOTE
>
</Para>
<Para>
The final word on this subject is from Linus again:
</Para>
<Para>
<QUOTE
>Note that if you want to get optimal performance, don't believe me:
test. There are lots of gcc compiler switches, and it may be that a
particular set gives the best optimizations for you. </QUOTE
>
</Para>
</Sect4>
</Sect3>
<Sect3 id="index.29">
<Title><Literal remap="tt">Internal compiler error: cc1 got fatal signal 11</Literal>
</Title>
<Para>
Signal 11 is SIGSEGV, or `segmentation violation'. Usually it
means that the program got its pointers confused and tried to write to
memory it didn't own. So, it could be a gcc bug.
</Para>
<Para>
gcc is however, a well tested and reliable piece of software, for
the most part. It also uses a large number of complex data
structures, and an awful lot of pointers. In short, it's the pickiest
RAM tester commonly available. If you <Emphasis>can't duplicate the bug</Emphasis>
--- if it doesn't stop in the same place when you restart the
compilation --- it's almost certainly a problem with your hardware
(CPU, memory, motherboard or cache). <Emphasis remap="bf">Don't</Emphasis> claim it as a bug
because your computer passes the power-on checks or runs Windows ok or
whatever; these `tests' are commonly and rightly held to be worthless.
And don't claim it's a bug because a kernel compile always stops
during `<Literal remap="tt">make zImage</Literal>' --- of course it will! `<Literal remap="tt">make zImage</Literal>'
is probably compiling over 200 files; we're looking for a slightly
<Emphasis>smaller</Emphasis> place than that.
</Para>
<Para>
If you can duplicate the bug, and (better) can produce a short
program that exhibits it, you can submit it as a bug report to the
FSF, or to the linux-gcc mailing list. See the gcc documentation for
details of exactly what information they need.
</Para>
</Sect3>
</Sect2>
<Sect2>
<Title>Portability</Title>
<Para>
It has been said that, these days, if something hasn't been ported
to Linux then it is not worth having :-)
</Para>
<Para>
Seriously though, in general only minor changes are needed to the
sources to get over Linux's 100&percnt; POSIX compliance. It is also
worthwhile passing back any changes to authors of the code such that
in the future only `make' need be called to provide a working
executable.
</Para>
<Sect3>
<Title>BSDisms (including <Literal remap="tt">bsd&lowbar;ioctl</Literal>, <Literal remap="tt">daemon</Literal> and <Literal remap="tt">&lt;sgtty.h&gt;</Literal>)</Title>
<Para>
You can compile your program with <Literal remap="tt">-I/usr/include/bsd</Literal> and link
it with <Literal remap="tt">-lbsd</Literal> (i.e. add <Literal remap="tt">-I/usr/include/bsd</Literal> to <Literal remap="tt">CFLAGS</Literal>
and <Literal remap="tt">-lbsd</Literal> to the <Literal remap="tt">LDFLAGS</Literal> line in your Makefile). There is
<Emphasis>no</Emphasis> need to add <Literal remap="tt">-D&lowbar;&lowbar;USE&lowbar;BSD&lowbar;SIGNAL</Literal> any more if you want BSD
type signal behavior, as you get this automatically when you have
<Literal remap="tt">-I/usr/include/bsd</Literal> and include <Literal remap="tt">&lt;signal.h&gt;</Literal>.
</Para>
</Sect3>
<Sect3 id="index.34">
<Title>`Missing' signals (<Literal remap="tt">SIGBUS</Literal>, <Literal remap="tt">SIGEMT</Literal>, <Literal remap="tt">SIGIOT</Literal>, <Literal remap="tt">SIGTRAP</Literal>, <Literal remap="tt">SIGSYS</Literal> etc)
</Title>
<Para>
Linux is POSIX compliant. These are not POSIX-defined signals ---
ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
</Para>
<Para>
<QUOTE
>``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS were omitted
from POSIX.1 because their behavior is implementation dependent and
could not be adequately categorized. Conforming implementations may
deliver these signals, but must document the circumstances under which
they are delivered and note any restrictions concerning their
delivery.''</QUOTE
>
</Para>
<Para>
The cheap and cheesy way to fix this is to redefine these signals
to <Literal remap="tt">SIGUNUSED</Literal>. The <Emphasis>correct</Emphasis> way is to bracket the code that
handles them with appropriate <Literal remap="tt">&num;ifdef</Literal>s:
</Para>
<Para>
<Screen>
#ifdef SIGSYS
/* ... non-posix SIGSYS code here .... */
#endif
</Screen>
</Para>
</Sect3>
<Sect3 id="index.39">
<Title>K &amp; R Code
</Title>
<Para>
GCC is an ANSI compiler; much existing code is not ANSI. There's
really not much that can be done about this, except to add
<Literal remap="tt">-traditional</Literal> to the compiler flags. There is a certain amount of
finer-grained control over which varieties of brain damage to emulate;
consult the gcc info page.
</Para>
<Para>
Note that <Literal remap="tt">-traditional</Literal> has effects beyond just changing the
language that gcc accepts. For example, it turns on
<Literal remap="tt">-fwritable-strings</Literal>, which moves string constants into data space
(from text space, where they cannot be written to). This increases
the memory footprint of the program.
</Para>
</Sect3>
<Sect3 id="index.40">
<Title>Preprocessor symbols conflict with prototypes in the code
</Title>
<Para>
One of the most frequent problems is that some common functions
are defined as macros in Linux's header files and the preprocessor
will refuse to parse similar prototype definitions in the code. Common
ones are <Literal remap="tt">atoi()</Literal> and <Literal remap="tt">atol()</Literal>.
</Para>
</Sect3>
<Sect3 id="index.42">
<Title><Literal remap="tt">sprintf()</Literal>
</Title>
<Para>
Something to be aware of, especially when porting from SunOS, is
that <Literal remap="tt">sprintf(string, fmt, ...)</Literal> returns a pointer to <Literal remap="tt">string</Literal>
on many unices, whereas Linux (following ANSI) returns the number of
characters which were put into the string.
</Para>
</Sect3>
<Sect3 id="index.43">
<Title><Literal remap="tt">fcntl</Literal> and friends. Where are the definitions of
<Literal remap="tt">FD&lowbar;*</Literal> stuff ?
</Title>
<Para>
In <Literal remap="tt">&lt;sys/time.h&gt;</Literal>. If you are using <Literal remap="tt">fcntl</Literal> you
probably want to include <Literal remap="tt">&lt;unistd.h&gt;</Literal> too, for the actual
prototype.
</Para>
<Para>
Generally speaking, the manual page for a function lists the necessary
<Literal remap="tt">&num;include</Literal>s in its SYNOPSIS section.
</Para>
</Sect3>
<Sect3 id="index.50">
<Title>The <Literal remap="tt">select()</Literal> timeout. Programs start busy-waiting.
</Title>
<Para>
The BSD manual page for select(2) used to say
<QUOTE
>select() should probably return the time remaining from the original
timeout, if any, by modifying the time value in place. This may be
implemented in future versions of the system. Thus, it is unwise to
assume that the timeout pointer will be unmodified by the select()
call.</QUOTE
>
</Para>
<Para>
Some versions of Linux do perform this modification. Some don't. It
is incredibly unwise to assume one behaviour or the other.
</Para>
<Para>
To fix, put the timeout value into that structure every time you call
<Literal remap="tt">select()</Literal>. Change code like
<Screen>
struct timeval timeout;
timeout.tv_sec = 1; timeout.tv_usec = 0;
while (some_condition)
select(n,readfds,writefds,exceptfds,&amp;timeout);
</Screen>
to, say,
<Screen>
struct timeval timeout;
while (some_condition) {
timeout.tv_sec = 1; timeout.tv_usec = 0;
select(n,readfds,writefds,exceptfds,&amp;timeout);
}
</Screen>
</Para>
<Para>
Some versions of Mosaic were at one time notable for this problem.
The speed of the spinning globe animation was inversely related to the
speed that the data was coming in from the network at!
</Para>
</Sect3>
<Sect3 id="index.51">
<Title>Interrupted system calls.
</Title>
<Sect4>
<Title>Symptom:</Title>
<Para>
When a program is stopped using Ctrl-Z and then restarted - or in
other situations that generate signals: Ctrl-C interruption,
termination of a child process etc. - it complains about "interrupted
system call" or "write: unknown error" or things like that.
</Para>
</Sect4>
<Sect4>
<Title>Problem:</Title>
<Para>
POSIX systems check for signals a bit more often than some older
unices. Linux may execute signal handlers ---
</Para>
<Para>
<ItemizedList>
<ListItem>
<Para>
asynchronously (at a timer tick)
</Para>
</ListItem>
<ListItem>
<Para>
on return from any system call
</Para>
</ListItem>
<ListItem>
<Para>
during the execution of the following system calls:
<Literal remap="tt">select()</Literal>, <Literal remap="tt">pause()</Literal>, <Literal remap="tt">connect()</Literal>,
<Literal remap="tt">accept()</Literal>, <Literal remap="tt">read()</Literal> on terminals, sockets, pipes or
files in <Literal remap="tt">/proc</Literal>, <Literal remap="tt">write()</Literal> on terminals, sockets, pipes or
the line printer, <Literal remap="tt">open()</Literal> on FIFOs, PTYs or serial lines,
<Literal remap="tt">ioctl()</Literal> on terminals, <Literal remap="tt">fcntl()</Literal> with command
<Literal remap="tt">F&lowbar;SETLKW</Literal>, <Literal remap="tt">wait4()</Literal>, <Literal remap="tt">syslog()</Literal>, any TCP or NFS
operations.
</Para>
</ListItem>
</ItemizedList>
</Para>
<Para>
For other operating systems you may have to include the system calls
<Literal remap="tt">creat()</Literal>, <Literal remap="tt">close()</Literal>, <Literal remap="tt">getmsg()</Literal>, <Literal remap="tt">putmsg()</Literal>,
<Literal remap="tt">msgrcv()</Literal>, <Literal remap="tt">msgsnd()</Literal>, <Literal remap="tt">recv()</Literal>, <Literal remap="tt">send()</Literal>,
<Literal remap="tt">wait()</Literal>, <Literal remap="tt">waitpid()</Literal>, <Literal remap="tt">wait3()</Literal>, <Literal remap="tt">tcdrain()</Literal>,
<Literal remap="tt">sigpause()</Literal>, <Literal remap="tt">semop()</Literal> to this list.
</Para>
<Para>
If a signal (that the program has installed a handler for) occurs
during a system call, the handler is called. When the handler returns
(to the system call) it detects that it was interrupted, and
immediately returns with -1 and <Literal remap="tt">errno = EINTR</Literal>. The program is
not expecting that to happen, so bottles out.
</Para>
<Para>
You may choose between two fixes.
</Para>
<Para>
(1) For every signal handler that you install, add <Literal remap="tt">SA&lowbar;RESTART</Literal> to the
sigaction flags. For example, change
</Para>
<Para>
<Screen>
signal (sig_nr, my_signal_handler);
</Screen>
to
<Screen>
signal (sig_nr, my_signal_handler);
{ struct sigaction sa;
sigaction (sig_nr, (struct sigaction *)0, &amp;sa);
#ifdef SA_RESTART
sa.sa_flags |= SA_RESTART;
#endif
#ifdef SA_INTERRUPT
sa.sa_flags &amp;= ~ SA_INTERRUPT;
#endif
sigaction (sig_nr, &amp;sa, (struct sigaction *)0);
}
</Screen>
</Para>
<Para>
Note that while this applies to most system calls, you must still
check for <Literal remap="tt">EINTR</Literal> yourself on <Literal remap="tt">read()</Literal>, <Literal remap="tt">write()</Literal>,
<Literal remap="tt">ioctl()</Literal>, <Literal remap="tt">select()</Literal>, <Literal remap="tt">pause()</Literal> and <Literal remap="tt">connect()</Literal>. See
below.
</Para>
<Para>
(2) Check for <Literal remap="tt">EINTR</Literal> explicitly, yourself:
</Para>
<Para>
Here are two examples for <Literal remap="tt">read()</Literal> and <Literal remap="tt">ioctl()</Literal>,
</Para>
<Para>
Original piece of code using <Literal remap="tt">read()</Literal>
</Para>
<Para>
<Screen>
int result;
while (len &#62; 0) {
result = read(fd,buffer,len);
if (result &#60; 0) break;
buffer += result; len -= result;
}
</Screen>
becomes
</Para>
<Para>
<Screen>
int result;
while (len &#62; 0) {
result = read(fd,buffer,len);
if (result &#60; 0) { if (errno != EINTR) break; }
else { buffer += result; len -= result; }
}
</Screen>
and a piece of code using <Literal remap="tt">ioctl()</Literal>
</Para>
<Para>
<Screen>
int result;
result = ioctl(fd,cmd,addr);
</Screen>
becomes
<Screen>
int result;
do { result = ioctl(fd,cmd,addr); }
while ((result == -1) &#38;&#38; (errno == EINTR));
</Screen>
</Para>
<Para>
Note that in some versions of BSD Unix the default behaviour is to
restart system calls. To get system calls interrupted you have to use
the <Literal remap="tt">SV&lowbar;INTERRUPT</Literal> or <Literal remap="tt">SA&lowbar;INTERRUPT</Literal> flag.
</Para>
</Sect4>
</Sect3>
<Sect3 id="index.53">
<Title>Writable strings (program seg faults randomly)
</Title>
<Para>
GCC has an optimistic view of its users, believing that they
intend string constants to be exactly that --- constant. Thus, it
stores them in the text (code) area of the program, where they can be
paged in and out from the program's disk image (instead of taking up
swapspace), and any attempt to rewrite them will cause a segmentation
fault. This is a feature!
</Para>
<Para>
It may cause a problem for old programs that, for example, call
<Literal remap="tt">mktemp()</Literal> with a string constant as argument. <Literal remap="tt">mktemp()</Literal>
attempts to rewrite its argument in place.
</Para>
<Para>
To fix, either (a) compile with <Literal remap="tt">-fwritable-strings</Literal>, to get gcc to
put constants in data space, or (b) rewrite the offending parts to
allocate a non-constant string and strcpy the data into it before
calling.
</Para>
</Sect3>
<Sect3 id="index.57">
<Title>Why does the <Literal remap="tt">execl()</Literal> call fail?
</Title>
<Para>
Because you're calling it wrong. The first argument to <Literal remap="tt">execl</Literal>
is the program that you want to run. The second and subsequent
arguments become the <Literal remap="tt">argv</Literal> array of the program you're calling.
Remember: <Literal remap="tt">argv[0]</Literal> is traditionally set even when a program is run
with `no' arguments. So, you should be writing
</Para>
<Para>
<Screen>
execl("/bin/ls","ls",NULL);
</Screen>
not just
<Screen>
execl("/bin/ls", NULL);
</Screen>
</Para>
<Para>
Executing the program with no arguments at all is construed as an
invitation to print out its dynamic library dependencies, at least
using a.out. ELF does things differently.
</Para>
<Para>
(If you want this library information, there are simpler interfaces;
see the section on dynamic loading, or the manual page for <Literal remap="tt">ldd</Literal>).
</Para>
</Sect3>
</Sect2>
</Sect1>
<Sect1>
<Title>Debugging and Profiling</Title>
<Sect2 id="index.58">
<Title>Preventative maintenance (lint)
</Title>
<Para>
There is no widely-used lint for Linux, as most people are
satisfied with the warnings that gcc can generate.
Probably the most useful is the <Literal remap="tt">-Wall</Literal> switch --- this stands for
`Warnings, all' but probably has more mnemonic value if thought of as
the thing you bang your head against.
</Para>
<Para>
There is a public domain lint available from <ULink
URL="ftp://larch.lcs.mit.edu/pub/Larch/lclint"
>&#65533;</ULink
>. I don't know how
good it is.
</Para>
</Sect2>
<Sect2 id="index.59">
<Title>Debugging
</Title>
<Sect3 id="index.60">
<Title>How do I get debugging information into a program ?
</Title>
<Para>
You need to compile and link all its bits with the <Literal remap="tt">-g</Literal> switch,
and without the <Literal remap="tt">-fomit-frame-pointer</Literal> switch. Actually, you don't
need to recompile all of it, just the bits you're interested in debugging.
</Para>
<Para>
On a.out configurations the shared libraries are compiled with
<Literal remap="tt">-fomit-frame-pointer</Literal>, which gdb won't get on with. Giving the
<Literal remap="tt">-g</Literal> option when you link should imply static linking; this is why.
</Para>
<Para>
If the linker fails with a message about not finding libg.a, you
don't have <Literal remap="tt">/usr/lib/libg.a</Literal>, which is the special
debugging-enabled C library. It may be supplied in the libc binary
package, or (in newer C library versions) you may need to get the libc
source code and build it yourself. You don't actually <Emphasis>need</Emphasis> it
though; you can get enough information for most purposes simply by
symlinking it to <Literal remap="tt">/usr/lib/libc.a</Literal>
</Para>
<Sect4 id="index.63">
<Title>How do I get it out again?
</Title>
<Para>
A lot of GNU software comes set up to compile and link with
<Literal remap="tt">-g</Literal>, causing it to make very big (and often static) executables.
This is not really such a hot idea.
</Para>
<Para>
If the program has an autoconf generated <Literal remap="tt">configure</Literal> script,
you can usually turn off debugging information by doing
<Literal remap="tt">./configure CFLAGS=</Literal> or <Literal remap="tt">./configure CFLAGS=-O2</Literal>. Otherwise,
check the Makefile. Of course, if you're using ELF, the program is
dynamically linked regardless of the <Literal remap="tt">-g</Literal> setting, so you can just
<Literal remap="tt">strip</Literal> it.
</Para>
</Sect4>
</Sect3>
<Sect3 id="index.64">
<Title>Available software
</Title>
<Para>
Most people use <Emphasis remap="bf">gdb</Emphasis>, which you can get in source form from
<ULink
URL="ftp://prep.ai.mit.edu/pub/gnu"
>GNU archive sites</ULink
>, or
as a binary from <ULink
URL="ftp://tsx-11.mit.edu/pub/linux/packages/GCC"
>tsx-11</ULink
> or
sunsite. <Emphasis remap="bf">xxgdb</Emphasis> is an X debugger based on this (i.e. you need gdb
installed first). The source may be found at <ULink
URL="ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz"
>&#65533;</ULink
>
</Para>
<Para>
Also, the <Emphasis remap="bf">UPS</Emphasis> debugger has been ported by Rick Sladkey. It runs
under X as well, but unlike xxgdb, it is not merely an X front end for
a text based debugger. It has quite a number of nice features, and if
you spend any time debugging stuff, you probably should check it
out. The Linux precompiled version and patches for the stock UPS
sources can be found in <ULink
URL="ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/"
>&#65533;</ULink
>, and the
original source at <ULink
URL="ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z"
>&#65533;</ULink
>.
</Para>
<Para>
Another tool you might find useful for debugging is `<Emphasis remap="bf">strace</Emphasis>', which
displays the system calls that a process makes. It has a multiplicity
of other uses too, including figuring out what pathnames were compiled
into binaries that you don't have the source for, exacerbating race
conditions in programs that you suspect contain them, and generally
learning how things work. The latest version of strace (currently
3.0.8) can be found at <ULink
URL="ftp://ftp.std.com/pub/jrs/"
>&#65533;</ULink
>.
</Para>
</Sect3>
<Sect3>
<Title>Background (daemon) programs</Title>
<Para>
Daemon programs typically execute <Literal remap="tt">fork()</Literal> early, and terminate
the parent. This makes for a short debugging session.
</Para>
<Para>
The simplest way to get around this is to set a breakpoint for
<Literal remap="tt">fork</Literal>, and when the program stops, force it to return 0.
</Para>
<Para>
<Screen>
(gdb) list
1 #include &#60;stdio.h&#62;
2
3 main()
4 {
5 if(fork()==0) printf("child\n");
6 else printf("parent\n");
7 }
(gdb) break fork
Breakpoint 1 at 0x80003b8
(gdb) run
Starting program: /home/dan/src/hello/./fork
Breakpoint 1 at 0x400177c4
Breakpoint 1, 0x400177c4 in fork ()
(gdb) return 0
Make selected stack frame return now? (y or n) y
#0 0x80004a8 in main ()
at fork.c:5
5 if(fork()==0) printf("child\n");
(gdb) next
Single stepping until exit from function fork,
which has no line number information.
child
7 }
</Screen>
</Para>
</Sect3>
<Sect3>
<Title>Core files</Title>
<Para>
When Linux boots it is usually configured not to produce core
files. If you like them, use your shell's builtin command to re-enable them:
for C-shell compatibles (e.g. tcsh) this is
<Screen>
% limit core unlimited
</Screen>
while Bourne-like shells (sh, bash, zsh, pdksh) use
<Screen>
$ ulimit -c unlimited
</Screen>
</Para>
<Para>
If you want a bit more versatility in your core file naming (for
example, if you're trying to conduct a post-mortem using a debugger
that's buggy itself) you can make a simple mod to your kernel. Look
for the code in <Literal remap="tt">fs/binfmt&lowbar;aout.c</Literal> and <Literal remap="tt">fs/binfmt&lowbar;elf.c</Literal> (in
newer kernels, you'll have to grep around a little in older ones) that
says
</Para>
<Para>
<Screen>
memcpy(corefile,"core.",5);
#if 0
memcpy(corefile+5,current-&#62;comm,sizeof(current-&#62;comm));
#else
corefile[4] = '\0';
#endif
</Screen>
</Para>
<Para>
and change the <Literal remap="tt">0</Literal>s to <Literal remap="tt">1</Literal>s.
</Para>
</Sect3>
</Sect2>
<Sect2>
<Title>Profiling</Title>
<Para>
Profiling is a way to examine which bits of a program are called most
often or run for longest. It is a good way to optimize code and look
at where time is being wasted. You must compile all object files that
you require timing information for with <Literal remap="tt">-p</Literal>, and to make sense of
the output file you will also need <Literal remap="tt">gprof</Literal> (from the binutils
package). See the <Literal remap="tt">gprof</Literal> manual page for details.
</Para>
</Sect2>
</Sect1>
<Sect1>
<Title>Linking</Title>
<Para>
Between the two incompatible binary formats, the static vs shared
library distinction, and the overloading of the verb `link' to mean
both `what happens after compilation' and `what happens when a
compiled program is invoked' (and, actually, the overloading of
the word `load' in a comparable but opposite sense), this section is
complicated. Little of it is much more complicated than that
sentence, though, so don't worry too much about it.
</Para>
<Para>
To alleviate the confusion somewhat, we refer to what happens at
runtime as `dynamic loading' and cover it in the next section. You
will also see it described as `dynamic linking', but not here. This
section, then, is exclusively concerned with the kind of linking
that happens at the end of a compilation.
</Para>
<Sect2>
<Title>Shared vs static libraries</Title>
<Para>
The last stage of building a program is to `link' it; to join all
the pieces of it together and see what is missing. Obviously there
are some things that many programs will want to do --- open files, for
example, and the pieces that do these things are provided for you in
the form of libraries. On the average Linux system these can be found
in <Literal remap="tt">/lib</Literal> and <Literal remap="tt">/usr/lib/</Literal>, among other places.
</Para>
<Para>
<Anchor id="index.65">
<Anchor id="index.66">
</Para>
<Para>
When using a static library, the linker finds the bits that the
program modules need, and physically copies them into the executable
output file that it generates. For shared libraries, it doesn't ---
instead it leaves a note in the output saying `when this program is
run, it will first have to load this library'. Obviously shared
libraries tend to make for smaller executables; they also use less
memory and mean that less disk space is used. The default behaviour
of Linux is to link shared if it can find the shared libraries, static
otherwise. If you're getting static binaries when you want shared,
check that the shared library files (<Literal remap="tt">*.sa</Literal> for a.out, <Literal remap="tt">*.so</Literal>
for ELF) are where they should be, and are readable.
</Para>
<Para>
On Linux, static libraries have names like <Literal remap="tt">libname.a</Literal>, while
shared libraries are called <Literal remap="tt">libname.so.x.y.z</Literal> where <Literal remap="tt">x.y.z</Literal> is
some form of version number. Shared libraries often also have links
pointing to them, which are important, and (on a.out configurations)
associated <Literal remap="tt">.sa</Literal> files. The standard libraries come in both shared
and static formats.
</Para>
<Para>
You can find out what shared libraries a program requires by using
<Literal remap="tt">ldd</Literal> (List Dynamic Dependencies)
<Screen>
$ ldd /usr/bin/lynx
libncurses.so.1 =&#62; /usr/lib/libncurses.so.1.9.6
libc.so.5 =&#62; /lib/libc.so.5.2.18
</Screen>
</Para>
<Para>
This shows that on my system the WWW browser `lynx' depends on the
presence of <Literal remap="tt">libc.so.5</Literal> (the C library) and <Literal remap="tt">libncurses.so.1</Literal>
(used for terminal control). If a program has no dependencies,
<Literal remap="tt">ldd</Literal> will say `<Literal remap="tt">statically linked</Literal>' or `<Literal remap="tt">statically linked (ELF)</Literal>'.
</Para>
</Sect2>
<Sect2 id="index.67">
<Title>Interrogating libraries (`which library is <Literal remap="tt">sin()</Literal> in?')
</Title>
<Para>
<Literal remap="tt">nm </Literal><Emphasis>libraryname</Emphasis> should list all the symbols that
<Emphasis>libraryname</Emphasis> has references to. It works on both static and shared
libraries. Suppose that you want to know where <Literal remap="tt">tcgetattr()</Literal> is defined:
you might do
</Para>
<Para>
<Screen>
$ nm libncurses.so.1 |grep tcget
U tcgetattr
</Screen>
</Para>
<Para>
The <Literal remap="tt">U</Literal> stands for `undefined' --- it shows that the ncurses
library uses but does not define it. You could also do
</Para>
<Para>
<Screen>
$ nm libc.so.5 | grep tcget
00010fe8 T __tcgetattr
00010fe8 W tcgetattr
00068718 T tcgetpgrp
</Screen>
</Para>
<Para>
The `<Literal remap="tt">W</Literal>' stands for `weak', which means that the symbol is
defined, but in such a way that it can be overridden by another
definition in a different library. A straightforward `normal'
definition (such as the one for <Literal remap="tt">tcgetpgrp</Literal>) is marked by a
`<Literal remap="tt">T</Literal>'
</Para>
<Para>
<Anchor id="index.70">
</Para>
<Para>
The short answer to the question in the title, by the way, is
<Literal remap="tt">libm.(so&verbar;a)</Literal>. All the functions defined in <Literal remap="tt">&lt;math.h&gt;</Literal> are
kept in the maths library; thus you need to link with <Literal remap="tt">-lm</Literal> when
using any of them.
</Para>
</Sect2>
<Sect2>
<Title>Finding files</Title>
<Para>
<Literal remap="tt">ld: Output file requires shared library `libfoo.so.1`</Literal>
</Para>
<Para>
The file search strategy of ld and friends varies according to
version, but the only default you can reasonably assume is
<Literal remap="tt">/usr/lib</Literal>. If you want libraries elsewhere to be searched,
specify their directories with the <Literal remap="tt">-L</Literal> option to gcc or ld.
</Para>
<Para>
If that doesn't help, check that you have the right file in that
place. For a.out, linking with <Literal remap="tt">-lfoo</Literal> makes ld look for
<Literal remap="tt">libfoo.sa</Literal> (shared stubs), and if unsuccessful then for
<Literal remap="tt">libfoo.a</Literal> (static). For ELF, it looks for <Literal remap="tt">libfoo.so</Literal> then
<Literal remap="tt">libfoo.a</Literal>. <Literal remap="tt">libfoo.so</Literal> is usually a symbolic link to
<Literal remap="tt">libfoo.so.x</Literal>.
</Para>
</Sect2>
<Sect2>
<Title>Building your own libraries</Title>
<Sect3>
<Title>Version control</Title>
<Para>
As any other program, libraries tend to have bugs which get fixed
over time. They also may introduce new features, change the effect of
existing ones, or remove old ones. This could be a problem for
programs using them; what if it was depending on that old feature?
</Para>
<Para>
So, we introduce library versioning. We categorise the changes that
might be made to a library as `minor' or `major', and we rule that a
`minor' change is not allowed to break old programs that are using the
library. You can tell the version of a library by looking at its
filename (actually, this is, strictly speaking, a lie for
ELF; keep reading to find out why) : <Literal remap="tt">libfoo.so.1.2</Literal> has
major version 1, minor version 2. The minor version number can be
more or less anything --- libc puts a `patchlevel' in it, giving
library names like <Literal remap="tt">libc.so.5.2.18</Literal>, and it's also reasonable to
put letters, underscores, or more or less any printable ASCII in it.
</Para>
<Para>
One of the major differences between ELF and a.out format is in
building shared libraries. We look at ELF first, because it's
simpler.
</Para>
</Sect3>
<Sect3 id="index.71">
<Title>ELF? What is it then, anyway?
</Title>
<Para>
ELF (Executable and Linking Format) is a binary format originally
developed by USL (UNIX System Laboratories) and currently used in
Solaris and System V Release 4. Because of its increased flexibility
over the older a.out format that Linux was using, the GCC and C
library developers decided last year to move to using ELF as the Linux
standard binary format also.
</Para>
<Sect4>
<Title>Come again?</Title>
<Para>
This section is from the document '/news-archives/comp.sys.sun.misc'.
</Para>
<Para>
<QUOTE
>ELF ("Executable Linking Format) is the "new, improved" object file
format introduced in SVR4. ELF is much more powerful than straight
COFF, in that it *is* user-extensible. ELF views an object-file as
an arbitarily long list of sections (rather than an array of fixed
size entities), these sections, unlike in COFF, do not HAVE to be in
a certain place and do not HAVE to come in any specific order etc.
Users can add new sections to object-files if they wish to
capture new data. ELF also has a far more powerful debugging format
called DWARF (Debugging With Attribute Record Format) - not currently
fully supported on linux (but work is underway). A linked list
of DWARF DIEs (or Debugging Information Entries) forms the .debug
section in ELF. Instead of being a collection of small, fixed-size
information records, DWARF DIEs each contain an arbitrarily long
list of complex attributes and are written out as a scope-based tree
of program data. DIEs can capture a large amount of information that
the COFF .debug section simply couldn't (like C++ inheritance graphs
etc.).</QUOTE
>
<QUOTE
>ELF files are accessed via the SVR4 (Solaris 2.0 ?) ELF access
library, which provides an easy and fast interface to the more gory
parts of ELF. One of the major boons in using the ELF access library
is that you will never need to look at an ELF file qua. UNIX file, it
is accessed as an Elf *, after an elf&lowbar;open() call and from then on,
you perform elf&lowbar;foobar() calls on its components instead of messing
about with its actual on-disk image (something many COFFers did with
impunity). </QUOTE
>
</Para>
<Para>
The case for/against ELF, and the necessary contortions to upgrade an
a.out system to support it, are covered in the ELF-HOWTO and I don't
propose to cut/paste them here. The HOWTO should be available in the
same place as you found this one.
</Para>
</Sect4>
<Sect4>
<Title>ELF shared libraries</Title>
<Para>
To build <Literal remap="tt">libfoo.so</Literal> as a shared library, the basic steps look
like this:
</Para>
<Para>
<Screen>
$ gcc -fPIC -c *.c
$ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o
$ ln -s libfoo.so.1.0 libfoo.so.1
$ ln -s libfoo.so.1 libfoo.so
$ LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ; export LD_LIBRARY_PATH
</Screen>
</Para>
<Para>
This will generate a shared library called <Literal remap="tt">libfoo.so.1.0</Literal>, and
the appropriate links for ld (<Literal remap="tt">libfoo.so</Literal>) and the dynamic
loader (<Literal remap="tt">libfoo.so.1</Literal>) to find it. To test, we add the current
directory to <Literal remap="tt">LD&lowbar;LIBRARY&lowbar;PATH</Literal>.
</Para>
<Para>
<Anchor id="index.72">
When you're happpy that the library works, you'll have to move it to,
say, <Literal remap="tt">/usr/local/lib</Literal>, and recreate the appropriate links. The
link from <Literal remap="tt">libfoo.so.1</Literal> to <Literal remap="tt">libfoo.so.1.0</Literal> is kept up to date by
<Literal remap="tt">ldconfig</Literal>, which on most systems is run as part of the boot
process. The <Literal remap="tt">libfoo.so</Literal> link must be updated manually. If you are
scrupulous about upgrading all the parts of a library (e.g. the header
files) at the same time, the simplest thing to do is make
<Literal remap="tt">libfoo.so -&#62; libfoo.so.1</Literal>, so that ldconfig will keep both
links current for you. If you <Emphasis>aren't</Emphasis>, you're setting yourself up
to have <Emphasis>all kinds of weird things</Emphasis> happen at a later date. Don't say
you weren't warned.
</Para>
<Para>
<Screen>
$ su
# cp libfoo.so.1.0 /usr/local/lib
# /sbin/ldconfig
# ( cd /usr/local/lib ; ln -s libfoo.so.1 libfoo.so )
</Screen>
</Para>
</Sect4>
<Sect4 id="index.73">
<Title>Version numbering, sonames and symlinks
</Title>
<Para>
Each library has a <Emphasis>soname</Emphasis>. When the linker finds one of
these in a library it is searching, it embeds the soname into the
binary instead of the actual filename it is looking at. At runtime,
the dynamic loader will then search for a file with the name of the
soname, not the library filename. Thus a library called
<Literal remap="tt">libfoo.so</Literal> could have a soname <Literal remap="tt">libbar.so</Literal>, and all programs
linked to it would look for <Literal remap="tt">libbar.so</Literal> instead when they started.
</Para>
<Para>
This sounds like a pointless feature, but it is key to
understanding how multiple versions of the same library can coexist on
a system. The de facto naming standard for libraries in Linux is to
call the library, say, <Literal remap="tt">libfoo.so.1.2</Literal>, and give it a soname of
<Literal remap="tt">libfoo.so.1</Literal>. If it's added to a `standard' library directory
(e.g. <Literal remap="tt">/usr/lib</Literal>), <Literal remap="tt">ldconfig</Literal> will create a symlink
<Literal remap="tt">libfoo.so.1 -&#62; libfoo.so.1.2</Literal> so that the appropriate image
is found at runtime. You also need a link <Literal remap="tt">libfoo.so -&#62;
libfoo.so.1</Literal> so that ld will find the right soname to use at link
time.
</Para>
<Para>
So, when you fix bugs in the library, or add new functions (any
changes that won't adversely affect existing programs), you rebuild
it, keeping the soname as it was, and changing the filename. When you
make changes to the library that would break existing binaries, you
simply increment the number in the soname --- in this case, call the
new version <Literal remap="tt">libfoo.so.2.0</Literal>, and give it a soname of
<Literal remap="tt">libfoo.so.2</Literal>. Now switch the <Literal remap="tt">libfoo.so</Literal> link to point
to the new version and all's well with the world again.
</Para>
<Para>
Note that you don't <Emphasis>have</Emphasis> to name libraries this way, but it's a
good convention. ELF gives you the flexibility to name libraries in
ways that will confuse the pants off people, but that doesn't mean you
have to use it.
</Para>
<Para>
Executive summary: supposing that you observe the tradition that major
upgrades may break compatibility, minor upgrades may not, then link
with
</Para>
<Para>
<Screen>
gcc -shared -Wl,-soname,libfoo.so.major -o libfoo.so.major.minor
</Screen>
</Para>
<Para>
and everything will be all right.
</Para>
</Sect4>
</Sect3>
<Sect3>
<Title>a.out. Ye olde traditional format</Title>
<Para>
The ease of building shared libraries is a major reason for
upgrading to ELF. That said, it's still possible in a.out. Get
<ULink
URL="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz"
>&#65533;</ULink
>
and read the 20 page document that you will find after unpacking it.
I hate to be so transparently partisan, but it should be clear from
context that I never bothered myself :-)
</Para>
<Sect4 id="index.75">
<Title>ZMAGIC vs QMAGIC
</Title>
<Para>
QMAGIC is an executable format just like the old a.out (also known
as ZMAGIC) binaries, but which leaves the first page unmapped. This
allows for easier NULL dereference trapping as no mapping exists in
the range 0-4096. As a side effect your binaries are nominally smaller
as well (by about 1K).
</Para>
<Para>
Obsolescent linkers support ZMAGIC only, semi-obsolescent support both
formats, and current versions support QMAGIC only. This doesn't
actually matter, though, as the kernel can still run both formats.
</Para>
<Para>
Your `file' command should be able to identify whether a program is
QMAGIC.
</Para>
</Sect4>
<Sect4>
<Title>File Placement</Title>
<Para>
An a.out (DLL) shared library consists of two real files and a
symlink. For the `foo' library used throughout this document as an
example, these files would be <Literal remap="tt">libfoo.sa</Literal> and <Literal remap="tt">libfoo.so.1.2</Literal>;
the symlink would be <Literal remap="tt">libfoo.so.1</Literal> and would point at the latter of
the files. What are these for?
</Para>
<Para>
At compile time, <Literal remap="tt">ld</Literal> looks for <Literal remap="tt">libfoo.sa</Literal>. This is the `stub'
file for the library, and contains all exported data and pointers to
the functions required for run time linking.
</Para>
<Para>
At run time, the dynamic loader looks for <Literal remap="tt">libfoo.so.1</Literal>. This is a
symlink rather than a real file so that libraries can be updated with
newer, bugfixed versions without crashing any application that was
using the library at the time. After the new version --- say,
<Literal remap="tt">libfoo.so.1.3</Literal> --- is completely there, running ldconfig will
switch the link to point to it in one atomic operation, leaving any
program which had the old version still perfectly happy.
</Para>
<Para>
DLL libraries (I know that's a tautology --- so sue me) often appear
bigger than their static counterparts. They reserve space for future
expansion in the form of `holes' which can be made to take no disk
space. A simple <Literal remap="tt">cp</Literal> call or using the program <Literal remap="tt">makehole</Literal> will
achieve this. You can also strip them after building, as the
addresses are in fixed locations. <Emphasis remap="bf">Do not attempt to strip ELF
libraries</Emphasis>.
</Para>
</Sect4>
<Sect4>
<Title>``libc-lite''?</Title>
<Para>
A libc-lite is a light-weight version of the libc library built
such that it will fit on a floppy and suffice for all of the most
menial of UNIX tasks. It does <Emphasis>not</Emphasis> include curses, dbm, termcap
etc code. If your <Literal remap="tt">/lib/libc.so.4</Literal> is linked to a lite lib, you are
advised to replace it with a full version.
</Para>
</Sect4>
</Sect3>
<Sect3>
<Title>Linking: common problems</Title>
<Para>
Send me your linking problems! I probably won't do anything about
them, but I will write them up if I get enough ...
</Para>
<Para>
<VariableList>
<VarListEntry>
<Term> Programs link static when you wanted them shared</Term>
<ListItem>
<Para>
<Anchor id="index.77">
<Anchor id="index.78">
</Para>
<Para>
Check that you have the right links for <Literal remap="tt">ld</Literal> to find each shared
library. For ELF this means a <Literal remap="tt">libfoo.so</Literal> symlink to the image,
for a.out a <Literal remap="tt">libfoo.sa</Literal> file. A lot of people had this problem
after moving from ELF binutils 2.5 to 2.6 --- the earlier version
searched more `intelligently' for shared libraries, so they hadn't
created all the links. The intelligent behaviour was removed for
compatibility with other architectures, and because quite often it got
its assumptions wrong and caused more trouble than it solved.
</Para>
</VarListEntry>
<VarListEntry>
<Term> The DLL tool `mkimage' fails to find libgcc, or </Term>
<ListItem>
<Para>
<Anchor id="index.79">
</Para>
<Para>
As of <Literal remap="tt">libc.so.4.5.x</Literal> and above, libgcc is no longer shared. Hence
you must replace occurrences of `<Literal remap="tt">-lgcc</Literal>' on the offending line with
<Literal remap="tt">`gcc -print-libgcc-file-name`</Literal> (complete with the backquotes).
</Para>
<Para>
Also, delete all <Literal remap="tt">/usr/lib/libgcc*</Literal> files. This is important.
</Para>
</VarListEntry>
<VarListEntry>
<Term> <Literal remap="tt">&lowbar;&lowbar;NEEDS&lowbar;SHRLIB&lowbar;libc&lowbar;4 multiply defined</Literal> messages </Term>
<ListItem>
<Para>
are another consequence of the same problem.
</Para>
</VarListEntry>
<VarListEntry>
<Term> ``Assertion failure'' message when rebuilding a DLL ?</Term>
<ListItem>
<Para>
This cryptic message most probably means that one of your jump table
slots has overflowed because too little space has been reserved in the
original <Literal remap="tt">jump.vars</Literal> file. You can locate the culprit(s) by
running the `<Literal remap="tt">getsize</Literal>' command provided in the tools-2.17.tar.gz
package. Probably the only solution, though, is to bump the major
version number of the library, forcing it to be backward incompatible.
</Para>
</VarListEntry>
<VarListEntry>
<Term> <Literal remap="tt">ld: output file needs shared library libc.so.4</Literal> </Term>
<ListItem>
<Para>
This usually happens when you are linking with libraries other than
libc (e.g. X libraries), and use the <Literal remap="tt">-g</Literal> switch on the link line
without also using <Literal remap="tt">-static</Literal>.
</Para>
<Para>
The <Literal remap="tt">.sa</Literal> stubs for the shared libraries usually have an undefined
symbol <Literal remap="tt">&lowbar;NEEDS&lowbar;SHRLIB&lowbar;libc&lowbar;4</Literal> which gets resolved from the
<Literal remap="tt">libc.sa</Literal> stub. However with <Literal remap="tt">-g</Literal> you end up linking with
<Literal remap="tt">libg.a</Literal> or <Literal remap="tt">libc.a</Literal> and thus this symbol never gets resolved,
leading to the above error message.
</Para>
<Para>
In conclusion, add <Literal remap="tt">-static</Literal> when compiling with the <Literal remap="tt">-g</Literal> flag,
or don't link with <Literal remap="tt">-g</Literal>. Quite often you can get enough debugging
information by compiling the individual files with <Literal remap="tt">-g</Literal>, and
linking <Emphasis>without</Emphasis> it.
</Para>
</VarListEntry>
</VariableList>
</Para>
</Sect3>
</Sect2>
</Sect1>
<Sect1>
<Title>Dynamic Loading</Title>
<Para>
<Emphasis>This section is a tad short right now; it will be expanded
over time as I gut the ELF howto </Emphasis>
</Para>
<Sect2>
<Title>Concepts</Title>
<Para>
Linux has shared libraries, as you will by now be sick of hearing
if you read the whole of the last section at a sitting. Some of the
matching-names-to-places work which was traditionally done at link
time must be deferred to load time.
</Para>
</Sect2>
<Sect2>
<Title>Error messages</Title>
<Para>
Send me your link errors! I won't do anything about them, but I
might write them up ...
</Para>
<Para>
<VariableList>
<VarListEntry>
<Term> <Literal remap="tt">can't load library: /lib/libxxx.so, Incompatible version</Literal></Term>
<ListItem>
<Para>
(a.out only) This means that you don't have the correct major version
of the xxx library. No, you can't just make a symlink to another
version that you do have; if you are lucky this will cause your
program to segfault. Get the new version. A similar situation with
ELF will result in a message like
</Para>
<Para>
<Screen>
ftp: can't load library 'libreadline.so.2'
</Screen>
</Para>
</VarListEntry>
<VarListEntry>
<Term><Literal remap="tt">warning using incompatible library version xxx</Literal></Term>
<ListItem>
<Para>
(a.out only) You have an older minor version of the library than the
person who compiled the program used. The program will still run.
Probably. An upgrade wouldn't hurt, though.
</Para>
</VarListEntry>
</VariableList>
</Para>
</Sect2>
<Sect2 id="index.80">
<Title>Controlling the operation of the dynamic loader
</Title>
<Para>
There are a range of environment variables that the dynamic loader
will respond to. Most of these are more use to <Literal remap="tt">ldd</Literal> than they are
to the average user, and can most conveniently be set by running ldd
with various switches. They include
</Para>
<Para>
<ItemizedList>
<ListItem>
<Para>
<Literal remap="tt">LD&lowbar;BIND&lowbar;NOW</Literal> --- normally, functions are not `looked up' in
libraries until they are called. Setting this flag causes all the
lookups to happen when the library is loaded, giving a slower startup
time. It's useful when you want to test a program to make sure that
everything is linked.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">LD&lowbar;PRELOAD</Literal> can be set to a file containing `overriding'
function definitions. For example, if you were testing memory
allocation strategies, and wanted to replace `malloc', you could write
your replacement routine, compile it into <Literal remap="tt">malloc.o</Literal> and then
<Screen>
$ LD_PRELOAD=malloc.o; export LD_PRELOAD
$ some_test_program
</Screen>
<Literal remap="tt">LD&lowbar;ELF&lowbar;PRELOAD</Literal> and <Literal remap="tt">LD&lowbar;AOUT&lowbar;PRELOAD</Literal> are similar, but only
apply to the appropriate type of binary. If
<Literal remap="tt">LD&lowbar;</Literal><Emphasis>something</Emphasis><Literal remap="tt">&lowbar;PRELOAD</Literal> and <Literal remap="tt">LD&lowbar;PRELOAD</Literal> are set, the
more specific one is used.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">LD&lowbar;LIBRARY&lowbar;PATH</Literal> is a colon-separated list of directories
in which to look for shared libraries. It does <Emphasis>not</Emphasis> affect ld; it
only has effect at runtime. Also, it is disabled for programs that
run setuid or setgid. Again, <Literal remap="tt">LD&lowbar;ELF&lowbar;LIBRARY&lowbar;PATH</Literal> and
<Literal remap="tt">LD&lowbar;AOUT&lowbar;LIBRARY&lowbar;PATH</Literal> can also be used to direct the search
differently for different flavours of binary. <Literal remap="tt">LD&lowbar;LIBRARY&lowbar;PATH</Literal>
shouldn't be necessary in normal operation; add the directories to
<Literal remap="tt">/etc/ld.so.conf/</Literal> and rerun ldconfig instead.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">LD&lowbar;NOWARN</Literal> applies to a.out only. When set (e.g. with
<Literal remap="tt">LD&lowbar;NOWARN=true; export LD&lowbar;NOWARN</Literal>) it stops the loader from
issuing non-fatal warnings (such as minor version incompatibility
messages).
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">LD&lowbar;WARN</Literal> applies to ELF only. When set, it turns the
usually fatal ``Can't find library'' messages into warnings. It's not
much use in normal operation, but important for ldd.
</Para>
</ListItem>
<ListItem>
<Para>
<Literal remap="tt">LD&lowbar;TRACE&lowbar;LOADED&lowbar;OBJECTS</Literal> applies to ELF only, and causes
programs to think they're being run under <Literal remap="tt">ldd</Literal>:
<Screen>
$ LD_TRACE_LOADED_OBJECTS=true /usr/bin/lynx
libncurses.so.1 =&#62; /usr/lib/libncurses.so.1.9.6
libc.so.5 =&#62; /lib/libc.so.5.2.18
</Screen>
</Para>
</ListItem>
</ItemizedList>
</Para>
</Sect2>
<Sect2 id="index.82">
<Title>Writing programs with dynamic loading
</Title>
<Para>
This is very close to the way that Solaris 2.x dynamic loading
support works, if you're familiar with that. It is covered
extensively in H J Lu's ELF programming document, and the
<Literal remap="tt">dlopen(3)</Literal> manual page, which can be found in the ld.so
package. Here's a nice simple example though: link it with
<Literal remap="tt">-ldl</Literal>
</Para>
<Para>
<Screen>
#include &#60;dlfcn.h&#62;
#include &#60;stdio.h&#62;
main()
{
void *libc;
void (*printf_call)();
if(libc=dlopen("/lib/libc.so.5",RTLD_LAZY))
{
printf_call=dlsym(libc,"printf");
(*printf_call)("hello, world\n");
}
}
</Screen>
</Para>
</Sect2>
</Sect1>
<Sect1>
<Title>Contacting the developers</Title>
<Sect2 id="index.84">
<Title>Bug reports
</Title>
<Para>
Start by <Emphasis remap="bf">narrowing the problem down</Emphasis>. Is it specific to
Linux, or does it happen with gcc on other systems? Is it specific to
the kernel version? Library version? Does it go away if you link
static? Can you trim the program down to something <Emphasis remap="bf">short</Emphasis> that
demonstrates the bug?
</Para>
<Para>
Having done that, you'll know what program(s) the bug is in. For
GCC, the bug reporting procedure is explained in the info file. For
ld.so or the C or maths libraries, send mail to
<Literal remap="tt">linux-gcc@vger.rutgers.edu</Literal>. If possible, include a short and
self-contained program that exhibits the bug, and a description both
of what you want it to do, and what it actually does.
</Para>
</Sect2>
<Sect2>
<Title>Helping with development</Title>
<Para>
If you want to help with the development effort for GCC or the C
library, the first thing to do is join the
<Literal remap="tt">linux-gcc@vger.rutgers.edu</Literal> mailing list. If you just want to see
what the discussion is about, there are list archives at <ULink
URL="http://homer.ncm.com/linux-gcc/"
>&#65533;</ULink
>. The second and subsequent
things depend on what you want to do!
</Para>
</Sect2>
</Sect1>
<Sect1>
<Title>The Remains</Title>
<Sect2>
<Title>The Credits</Title>
<Para>
<QUOTE
>
Only presidents, editors, and people with tapeworms have the right to
use the editorial ``we''.</QUOTE
>
(Mark Twain)
</Para>
<Para>
This HOWTO is based very closely on Mitchum DSouza's GCC-FAQ; most
of the information (not to mention a reasonable amount of the text) in
it comes directly from that document. Instances of the first person
pronoun in this HOWTO could refer to either of us; generally the ones
that say ``I have not tested this; don't blame me if it toasts your
hard disk/system/spouse'' apply to both of us.
</Para>
<Para>
Contributors to this document have included (in ASCII ordering by
first name)
Andrew Tefft,
Axel Boldt,
Bill Metzenthen,
Bruce Evans,
Bruno Haible,
Daniel Barlow,
Daniel Quinlan,
David Engel,
Dirk Hohndel,
Eric Youngdale,
Fergus Henderson,
H.J. Lu,
Jens Schweikhardt,
Kai Petzke,
Michael Meissner,
Mitchum DSouza,
Olaf Flebbe,
Paul Gortmaker,
Rik Faith,
Steven S. Dick,
Tuomas J Lukka,
and of course Linus Torvalds, without whom the whole exercise would
have been pointless, let alone impossible :-)
</Para>
<Para>
Please do not feel offended if your name has not appeared here and you
have contributed to this document (either as HOWTO or as FAQ). Email
me and I will rectify it.
</Para>
</Sect2>
<Sect2>
<Title>Translations</Title>
<ItemizedList>
<ListItem> <Para>French, Eric Dumas
<address><email>dumas@freenix.fr</email></address>
http://www.freenix.fr/unix/linux/HOWTO/GCC-HOWTO.html
<ListItem> <Para>Italian, Andrea Girotto
<address><email>andrea.girotto@usa.net</email></address>
http://www.pluto.linux.it/ildp/HOWTO/GCC-HOWTO.html
<ListItem> <Para>Japanese,
<address><email>nakano@apm.seikei.ac.jp</email></address>
</Para>
</Sect2>
<Sect2>
<Title>Feedback</Title>
<para>is welcomed. Mail me at <ULink
URL="mailto:daniel.barlow@linux.org" >daniel.barlow@linux.org</ULink
>. My PGP public key (ID 5F263625) is available from my <ULink
URL="http://www.telent.net/#pgp" >web pages</ULink >, if you feel the
need to be secretive about things.</para>
</Sect2>
<Sect2>
<Title>Legalese</Title>
<Para>
All trademarks used in this document are acknowledged as being
owned by their respective owners.
</Para>
<Para>
This document is copyright (C) 1996,1999 Daniel Barlow <Literal
remap="tt">&lt;dan@detached.demon.co.uk&gt;</Literal>. It may be
reproduced and distributed in whole or in part, in any medium physical
or electronic, as long as this copyright notice is retained on all
copies. Commercial redistribution is allowed and encouraged; however,
the author would like to be notified of any such distributions.
</Para>
<Para>
All translations, derivative works, or aggregate works incorporating
any Linux HOWTO documents must be covered under this copyright notice.
That is, you may not produce a derivative work from a HOWTO and impose
additional restrictions on its distribution. Exceptions to these rules
may be granted under certain conditions; please contact the Linux
HOWTO coordinator at the address given below.
</Para>
<Para>
In short, we wish to promote dissemination of this information through
as many channels as possible. However, we do wish to retain copyright
on the HOWTO documents, and would like to be notified of any plans to
redistribute the HOWTOs.
</Para>
<Para>
If you have questions, please contact Tim Bynum, the Linux HOWTO
coordinator, at <Literal remap="tt">linux-howto@sunsite.unc.edu</Literal> via email.
</Para>
</Sect2>
</Sect1>
</Article>