我有两个文件
main.c
void swap();
int buf[2] = {1, 2};
int main()
{
swap();
return 0;
}
swap.c
extern int buf[];
int* bufp0 = &buf[0]; /* .data */
int* bufp1; /* .bss */
void swap()
{
int temp;
bufp1 = &buf[1];
temp = *bufp0;
*bufp0 = *bufp1;
*bufp1 = temp;
}
以下是一本书的两个摘录:
During this scan, the linker maintains a set E of relocatable object files that
will be merged to form the executable, a set U of unresolved symbols
(i.e., symbols referred to, but not yet defined), and a set D of symbols that
have been defined in previous input files.
Initially, E, U , and D are empty.
For each input file f on the command line, the linker determines if f is an
object file or an archive. If f is an object file, the linker adds f to E, updates
U and D to reflect the symbol definitions and references in f , and proceeds
to the next input file.
If f is an archive, the linker attempts to match the unresolved symbols in U
against the symbols defined by the members of the archive. If some archive
member, m, defines a symbol that resolves a reference in U , then m is added
to E, and the linker updates U and D to reflect the symbol definitions and
references in m. This process iterates over the member object files in the
archive until a fixed point is reached where U and D no longer change. At
this point, any member object files not contained in E are simply discarded
and the linker proceeds to the next input file.
If U is nonempty when the linker finishes scanning the input files on the
command line, it prints an error and terminates. Otherwise, it merges and
relocates the object files in E to build the output executable file.
The general rule for libraries is to place them at the end of the command
line. If the members of the different libraries are independent, in that no member
references a symbol defined by another member, then the libraries can be placed
at the end of the command line in any order.
If, on the other hand, the libraries are not independent, then they must be
ordered so that for each symbol s that is referenced externally by a member of an
archive, at least one definition of s follows a reference to s on the command line.
For example, suppose foo.c calls functions in libx.a and libz.a that call func-
tions in liby.a. Then libx.a and libz.a must precede liby.a on the command
line:
unix> gcc foo.c libx.a libz.a liby.a
我运行了以下命令来将两个目标文件静态链接(不创建任何归档文件)。
gcc -static -o main.o main.c swap.c
我预计上述命令会失败,因为
main.c
和swap.c
都有相互定义的引用。但与我的预期相反,它成功了。只有当我在命令行结尾再次传递main.c
时,我才希望它能成功。链接器如何解决这两个文件中的引用?当链接器尝试静态链接多个对象文件而不是归档文件时,工作方式是否有所不同? 我猜测链接器回到
main.c
以解决swap.c
中的buf
引用。