所有 ld-support 接口均在头文件 link.h 中定义。所有接口参数均为基本的 C 类型或 ELF 类型。可以通过 ELF 访问库 libelf 检查 ELF 数据类型。有关 libelf 内容的说明,请参见 elf(3ELF)。以下接口函数由 ld-support 接口提供,并且按照预期的使用顺序进行了说明。
uint_t ld_version(uint_t version);
链接编辑器使用其可以支持的最高版本的 ld-support 接口来调用此接口。支持库可以检验此版本是否达到使用的最低要求,并返回支持库要求使用的版本。此版本通常为 LD_SUP_VCURRENT。
如果支持库没有提供此接口,则采用初始支持级别 LD_SUP_VERSION1。
如果支持库返回版本 LD_SUP_VNONE,则链接编辑器将其卸载而无任何提示,且在不使用它的情况下继续执行。如果返回的版本高于链接编辑器所支持的 ld-support 接口的版本,则将发出致命错误,且链接编辑器将终止执行。否则,使用指定的 ld-support 接口版本的支持库继续执行。
此函数在初始验证链接编辑器命令行之后调用,表示开始处理输入文件。
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);
name 是所创建的输出文件名。type 是输出文件类型,可以为 ET_DYN、ET_REL 或 ET_EXEC,在 sys/elf.h 中定义。caller 是调用接口的应用程序,通常为 /usr/bin/ld 或 /usr/ccs/bin/ld。
此函数会针对每个输入链接编辑的文件调用。版本 LD_SUP_VERSION3 中添加的此函数比 ld_file() 函数具有更大的灵活性。此函数允许支持库替换文件描述符、ELF 描述符以及关联的文件名。此函数提供以下可能的使用情况。
将新的节添加到现有 ELF 文件。在这种情况下,应使用支持更新 ELF 文件的描述符替换原始 ELF 描述符。请参见 elf_begin(3ELF) 的 ELF_C_RDWR 参数。
可以使用替代文件替换整个输入文件。在这种情况下,应使用与新文件关联的描述符替换原始文件描述符和 ELF 描述符。
在这两种情况下,可以使用表示输入文件已修改的替代名称替换路径名和文件名。
void ld_open(const char **pname, const char **fname, int *fd, int flags, Elf **elf, Elf *ref, size_t off, Elf_Kind kind); void ld_open64(const char **pname, const char **fname, int *fd, int flags, Elf **elf, Elf *ref, size_t off, Elf_Kind kind);
pname 是要处理的输入文件的路径名。fname 是要处理的输入文件的文件名。fname 通常是 pname 的基本名称。pname 和 fname 均可由支持库修改。
fd 是输入文件的文件描述符。此描述符可由支持库关闭,且新的文件描述符可返回至链接编辑器。可以返回值为 -1 的文件描述符,以表示应忽略该文件。
flags 字段表示链接编辑器获取文件的方式,可以是以下一个或多个定义:
LD_SUP_DERIVED-文件名不是在命令行中显式指定的。文件是从 –l 扩展派生而来,或者文件标识提取的归档成员。
LD_SUP_EXTRACTED-文件提取自归档。
LD_SUP_INHERITED-文件作为命令行共享目标文件的依赖项获取。
如果未指定 flags 值,则表明已在命令行中显式指定了输入文件。
elf 是输入文件的 ELF 描述符。此描述符可由支持库关闭,且新的 ELF 描述符可返回至链接编辑器。可以返回值为 0 的 ELF 描述符,以表示应忽略该文件。如果 elf 描述符与归档库的成员关联,则 ref 描述符是底层归档文件的 ELF 描述符。off 表示归档文件中归档成员的偏移。
kind 表示输入文件类型,可以是 ELF_K_AR 或 ELF_K_ELF,在 libelf.h 中定义。
此函数针对每个输入链接编辑的文件调用。并且在执行任何文件数据处理之前即会调用此函数。
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);
name 是要处理的输入文件。kind 表示输入文件类型,可以是 ELF_K_AR 或 ELF_K_ELF,在 libelf.h 中定义。flags 字段表示链接编辑器获取文件的方式,此字段可包含与 ld_open() 的 flags 字段相同的定义。
LD_SUP_DERIVED-文件名不是在命令行中显式指定的。文件是从 –l 扩展派生而来,或者文件标识提取的归档成员。
LD_SUP_EXTRACTED-文件提取自归档。
LD_SUP_INHERITED-文件作为命令行共享目标文件的依赖项获取。
如果未指定 flags 值,则表明已在命令行中显式指定了输入文件。
elf 是输入文件的 ELF 描述符。
此函数针对输入文件的每一节调用,并且在链接编辑器确定是否应将节传播给输出文件之前即会调用版本 LD_SUP_VERSION2 中添加的此函数。此函数不同于 ld_section() 处理,后者仅针对组成输出文件的各节进行调用。
void ld_input_section(const char *name, Elf32_Shdr **shdr, Elf32_Word sndx, Elf_Data *data, Elf *elf, unit_t flags); void ld_input_section64(const char *name, Elf64_Shdr **shdr, Elf64_Word sndx, Elf_Data *data, Elf *elf, uint_t flags);
name 是输入节的名称。shdr 是指向关联节头的指针。sndx 是输入文件内的节索引。data 是指向关联数据缓冲区的指针。elf 是指向文件的 ELF 描述符的指针。flags 保留供将来使用。
节头的修改是通过重新分配节头并为新头重新指定 *shdr 来完成的。链接编辑器使用从 ld_input_section() 返回时 *shdr 所指向的节头信息来处理节。
通过重新分配数据并重新指 Elf_Data 缓冲区的 d_buf 指针,可以修改数据。对数据进行任何修改都应确保正确设置 Elf_Data 缓冲区的 d_size 元素。对于成为输出映像一部分的输入节,将 d_size 元素设置为零可以有效地删除输出映像中的数据。
在解压缩压缩的节之前即会调用此函数,这会使检查或替换数据的任务变得更为复杂。因此,建议延迟 ld_section() 的节数据的检查和可能的替换。
flags 字段指向初始值为零的 uint_t 数据字段。虽然在将来的更新中可通过链接编辑器或支持库来指定标志,但是当前未指定任何标志。
系统将针对传播给输出文件的输入文件的每一节调用此函数,并且在执行任何节数据处理之前即会调用此函数。但是,在调用此函数之前,会解压缩包含压缩数据的节。
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);
name 是输入节的名称。shdr 是指向关联节头的指针。sndx 是输入文件内的节索引。data 是指向关联数据缓冲区的指针。elf 是指向文件 ELF 描述符的指针。
通过重新分配数据并重新指 Elf_Data 缓冲区的 d_buf 指针,可以修改数据。对数据进行任何修改都应确保正确设置 Elf_Data 缓冲区的 d_size 元素。对于成为输出映像一部分的输入节,将 d_size 元素设置为零可以有效地删除输出映像中的数据。
在输入文件处理完成之后,将调用版本 LD_SUP_VERSION2 中添加的此函数。
此时,所有输入节均已被指定给输出文件映像。此外,已收集创建和更新此映像所需的信息以备应用于初始映像。任何时侯尝试通过 ld_input_done() 更改之前支持例程记录的任何数据时,均应格外小心。对节的标识或关系进行的所有更改都将丢失,或者可能会影响输出文件映像的创建。可应用无需重定位或不会影响现有定位的次要更新,例如添加节数据。
void ld_input_done(uint_t *flags);
flags 字段指向初始值为零的 uint_t 数据字段。虽然在将来的更新中可通过链接编辑器或支持库来指定标志,但是当前未指定任何标志。
void ld_atexit(int status); void ld_atexit64(int status);
status 是将由链接编辑器返回的 exit(2) 代码,可以是 EXIT_FAILURE 或 EXIT_SUCCESS,在 stdlib.h 中定义。