Linker and Libraries Guide

Link-Editor Support Interface

As described in Chapter 2, Link-Editor, the link-editor performs many operations including the opening of files and the concatenation of sections from these files. Monitoring, and sometimes modifying, these operations can often be beneficial to components of a compilation system.

This section describes the supported interface for input file inspection, and to some degree, input file data modification of those files that compose a link-edit. This interface is referred to as the ld-support interface. Two applications that employ this interface are the link-editor itself, which uses it to process debugging information within relocatable objects, and the make(1S) utility, which uses it to save state information.

The ld-support interface is composed of a support library that offers one or more support interface routines. This library is loaded as part of the link-edit process, and any support routines found are called at various stages of link-editing.

You should be familiar with the elf(3ELF) structures and file format when using this interface.

Invoking the Support Interface

The link-editor accepts one or more support libraries provided by either the SGS_SUPPORT environment variable or with the link-editor's -S option. The environment variable consists of a colon separated list of support libraries:


$ SGS_SUPPORT=./support.so.1:libldstab.so.1 cc ...

The -S option specifies a single support library. Multiple -S options can be specified:


$ LD_OPTIONS="-S./support.so.1 -Slibldstab.so.1" cc ...

A support library is a shared object. The link-editor performs a dlopen(3DL) on each support library, in the order they are specified. If both the environment variable and -S option are encountered, then the support libraries specified with the environment variable are processed first. Each support library is then searched, using dlsym(3DL), for any support interface routines. These support routines are then called at various stages of link-editing.


Note -

By default, the Solaris support library libldstab.so.1 is used by the link-editor to process, and compact, compiler-generated debugging information supplied within input relocatable objects. This default processing is suppressed if you invoke the link-editor with any support libraries specified using the -S option. If the default processing of libldstab.so.1 is required in addition to your support library services, then libldstab.so.1 should be explicitly added to the list of support libraries supplied to the link-editor.


32 and 64-bit Environments

As described in "32- and 64-bit Environments", the 64-bit link-editor (ld(1)) is capable of generating 32-bit objects and the 32-bit link-editor is capable of generating 64-bit objects. Each of these objects has an associated support interface defined.

The support interface for 64-bit objects is similar to that of 32-bit objects, but ends in a 64 suffix, for example ld_start() and ld_start64(). This convention allows both implementations of the support interface to reside in a single shared object libldstab.so.1 of each class, 32-bit and 64-bit.

Support Interface Functions

All ld-support interfaces are defined in the header file link.h. All interface arguments are basic C types or ELF types. The ELF data types can be examined with the ELF access library libelf (see elf(3ELF) for a description of libelf contents). The following interface functions are provided by the ld-support interface, and are described in their expected order of use:

ld_start()

void ld_start(const char * name, const Elf32_Half type,
    const char * caller);

void ld_start64(const char * name, const Elf64_Half type,
    const char * caller);

This function is called after initial validation of the link-editor command line, and indicates the start of input file processing.

name is the output filename being created. type is the output file type, which is either ET_DYN, ET_REL, or ET_EXEC (as defined in sys/elf.h). caller is the application calling the interface, which is normally /usr/ccs/bin/ld.

ld_file()

void ld_file(const char * name, const Elf_Kind kind, int flags,
    Elf * elf);

void ld_file64(const char * name, const Elf_Kind kind, int flags,
    Elf * elf);

This function is called for each input file before any processing of the files data is carried out.

name is the input file about to be processed. kind indicates the input file type, which is either ELF_K_AR, or ELF_K_ELF (as defined in libelf.h). flags indicates how the link-editor obtained the file, and can be one or more of the following definitions:

  • LD_SUP_DERIVED -- The filename was not explicitly named on the command-line. It was either derived from a -l expansion, or it identifies an extracted archive member.

  • LD_SUP_INHERITED -- The file was obtained as a dependency of a command-line shared object.

  • LD_SUP_EXTRACTED -- The file was extracted from an archive.

If no flags values are specified then the input file has been explicitly named on the command-line. elf is a pointer to the files ELF descriptor.

ld_section()

void ld_section(const char * name, Elf32_Shdr * shdr, Elf32_Word sndx,
        Elf_Data * data, Elf * elf);

void ld_section64(const char * name, Elf64_Shdr * shdr, Elf64_Word sndx,
        Elf_Data * data, Elf * elf);

This function is called for each section of the input file before any processing of the section data is carried out.

name is the input section name. shdr is a pointer to the associated section header. sndx is the section index within the input file. data is a pointer to the associated data buffer. elf is a pointer to the files ELF descriptor.

Modification of the data is permitted by reallocating the data itself and reassigning the Elf_Data buffer's d_buf pointer. Any modification to the data should ensure the correct setting of the Elf_Data buffers d_size element. For input sections that will become part of the output image, setting the d_size element to zero will effectively remove the data from the output image.


Note -

Any sections that are stripped by use of the link-editor's -s option, or discarded due to SHT_SUNW_COMDAT processing (see "Comdat Section") are not reported to ld_section().


ld_atexit()

void ld_atexit(int status);

void ld_atexit64(int status);

This function is called on completion of the link-edit.

status is the exit(2) code that will be returned by the link-editor and is either EXIT_FAILURE or EXIT_SUCCESS (as defined in stdlib.h).

Support Interface Example

The following example creates a support library that prints the section name (see Table 7-17) of any relocatable object file processed as part of a 32-bit link-edit.


$ cat support.c
#include        <link.h>
 
static int      indent = 0;
 
void
ld_start(const char * name, const Elf32_Half type,
    const char * caller)
{
        (void) printf("output image: %s\n", name);
}
 
void
ld_file(const char * name, const Elf_Kind kind, int flags,
    Elf * elf)
{
        if (flags & LD_SUP_EXTRACTED)
                indent = 4;
        else
                indent = 2;
 
        (void) printf("%*sfile: %s\n", indent, "", name);
}
 
void
ld_section(const char * name, Elf32_Shdr * shdr, Elf32_Word sndx,
    Elf_Data * data, Elf * elf)
{
        Elf32_Ehdr *    ehdr = elf32_getehdr(elf);
 
        if (ehdr->e_type == ET_REL)
                (void) printf("%*s   section [%ld]: %s\n", indent,
                    "", sndx, name);
}

This support library is dependent upon libelf to provide the ELF access function elf32_getehdr(3ELF) used to determine the input file type. The support library is built using:


$ cc -o support.so.1 -G -K pic support.c -lelf -lc

The following example shows the section diagnostics resulting from the construction of a trivial application from a relocatable object and a local archive library. The invocation of the support library, in addition to default debugging information processing, is brought about by the -S option usage:


$ LD_OPTIONS="-S./support.so.1 -Slibldstab.so.1" \ 
cc -o prog main.c -L. -lfoo

output image: prog
  file: /opt/COMPILER/crti.o
     section [1]: .shstrtab
     section [2]: .text
     .......
  file: /opt/COMPILER/crt1.o
     section [1]: .shstrtab
     section [2]: .text
     .......
  file: /opt/COMPILER/values-xt.o
     section [1]: .shstrtab
     section [2]: .text
     .......
  file: main.o
     section [1]: .shstrtab
     section [2]: .text
     .......
  file: ./libfoo.a
    file: ./libfoo.a(foo.o)
       section [1]: .shstrtab
       section [2]: .text
       .......
  file: /usr/lib/libc.so
  file: /opt/COMPILER/crtn.o
     section [1]: .shstrtab
     section [2]: .text
     .......
  file: /usr/lib/libdl.so.1

Note -

The number of sections displayed in this example have been reduced to simplify the output. Also, the files included by the compiler driver can vary.