mirror of https://github.com/tLDP/LDP
2538 lines
77 KiB
Plaintext
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">#</Literal> rather than <Literal remap="tt">$</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/"
|
|
>�</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|lib|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|lib|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"><linux/*.h></Literal> and <Literal remap="tt"><asm/*.h></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"><linux/autoconf.h></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"><float.h></Literal>, <Literal remap="tt"><limits.h></Literal>,
|
|
<Literal remap="tt"><varargs.h></Literal>, <Literal remap="tt"><stdarg.h></Literal> and
|
|
<Literal remap="tt"><stddef.h></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/"
|
|
>�</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"
|
|
>�</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">__linux__</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"
|
|
>�</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% 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_ioctl</Literal>, <Literal remap="tt">daemon</Literal> and <Literal remap="tt"><sgtty.h></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__USE_BSD_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"><signal.h></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">#ifdef</Literal>s:
|
|
</Para>
|
|
|
|
<Para>
|
|
|
|
<Screen>
|
|
#ifdef SIGSYS
|
|
/* ... non-posix SIGSYS code here .... */
|
|
#endif
|
|
</Screen>
|
|
|
|
</Para>
|
|
|
|
</Sect3>
|
|
|
|
<Sect3 id="index.39">
|
|
<Title>K & 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_*</Literal> stuff ?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</Title>
|
|
|
|
<Para>
|
|
In <Literal remap="tt"><sys/time.h></Literal>. If you are using <Literal remap="tt">fcntl</Literal> you
|
|
probably want to include <Literal remap="tt"><unistd.h></Literal> too, for the actual
|
|
prototype.
|
|
</Para>
|
|
|
|
<Para>
|
|
Generally speaking, the manual page for a function lists the necessary
|
|
<Literal remap="tt">#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,&timeout);
|
|
</Screen>
|
|
|
|
to, say,
|
|
|
|
<Screen>
|
|
struct timeval timeout;
|
|
while (some_condition) {
|
|
timeout.tv_sec = 1; timeout.tv_usec = 0;
|
|
select(n,readfds,writefds,exceptfds,&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_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_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, &sa);
|
|
#ifdef SA_RESTART
|
|
sa.sa_flags |= SA_RESTART;
|
|
#endif
|
|
#ifdef SA_INTERRUPT
|
|
sa.sa_flags &= ~ SA_INTERRUPT;
|
|
#endif
|
|
sigaction (sig_nr, &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 > 0) {
|
|
result = read(fd,buffer,len);
|
|
if (result < 0) break;
|
|
buffer += result; len -= result;
|
|
}
|
|
</Screen>
|
|
|
|
becomes
|
|
</Para>
|
|
|
|
<Para>
|
|
|
|
<Screen>
|
|
int result;
|
|
while (len > 0) {
|
|
result = read(fd,buffer,len);
|
|
if (result < 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) && (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_INTERRUPT</Literal> or <Literal remap="tt">SA_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"
|
|
>�</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"
|
|
>�</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/"
|
|
>�</ULink
|
|
>, and the
|
|
original source at <ULink
|
|
URL="ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z"
|
|
>�</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/"
|
|
>�</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 <stdio.h>
|
|
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_aout.c</Literal> and <Literal remap="tt">fs/binfmt_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->comm,sizeof(current->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 => /usr/lib/libncurses.so.1.9.6
|
|
libc.so.5 => /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|a)</Literal>. All the functions defined in <Literal remap="tt"><math.h></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_open() call and from then on,
|
|
you perform elf_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_LIBRARY_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 -> 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 -> libfoo.so.1.2</Literal> so that the appropriate image
|
|
is found at runtime. You also need a link <Literal remap="tt">libfoo.so ->
|
|
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"
|
|
>�</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">__NEEDS_SHRLIB_libc_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">_NEEDS_SHRLIB_libc_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_BIND_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_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_ELF_PRELOAD</Literal> and <Literal remap="tt">LD_AOUT_PRELOAD</Literal> are similar, but only
|
|
apply to the appropriate type of binary. If
|
|
<Literal remap="tt">LD_</Literal><Emphasis>something</Emphasis><Literal remap="tt">_PRELOAD</Literal> and <Literal remap="tt">LD_PRELOAD</Literal> are set, the
|
|
more specific one is used.
|
|
|
|
</Para>
|
|
</ListItem>
|
|
<ListItem>
|
|
|
|
<Para>
|
|
<Literal remap="tt">LD_LIBRARY_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_ELF_LIBRARY_PATH</Literal> and
|
|
<Literal remap="tt">LD_AOUT_LIBRARY_PATH</Literal> can also be used to direct the search
|
|
differently for different flavours of binary. <Literal remap="tt">LD_LIBRARY_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_NOWARN</Literal> applies to a.out only. When set (e.g. with
|
|
<Literal remap="tt">LD_NOWARN=true; export LD_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_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_TRACE_LOADED_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 => /usr/lib/libncurses.so.1.9.6
|
|
libc.so.5 => /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 <dlfcn.h>
|
|
#include <stdio.h>
|
|
|
|
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/"
|
|
>�</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"><dan@detached.demon.co.uk></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>
|