> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/man5/ar.5.md).

# ar(5)

`ar` — 归档文件格式

## 名称

`ar`, [ar(1)](/man1/ar.1.md), [ranlib(1)](/man1/ar.1.md)

## 概要

`#include <ar.h>`

## 描述

[ar(1)](/man1/ar.1.md) 归档由 [ar(1)](/man1/ar.1.md) 和 [ranlib(1)](/man1/ar.1.md) 实用程序创建和管理。这些归档通常在程序开发期间用于保存程序对象库。一个 [ar(1)](/man1/ar.1.md) 归档包含在单个操作系统文件中。

本手册页记录了 [ar(1)](/man1/ar.1.md) 归档格式的两种变体：BSD 归档格式和 SVR4/GNU 归档格式。

在两种变体中，归档文件都以一个标识字节序列开始，该序列由七个 ASCII 字符 ‘`!<arch>`’ 后跟一个 ASCII 换行符组成（参见头文件中的常量 “ARMAG”）

`#include <ar.h>`

归档成员紧跟在初始标识字节序列之后。每个归档成员前面都有一个固定大小的头部，描述与该成员相关联的文件属性。

### 归档头部

归档头部描述其后的归档成员的文件属性。`ar` 格式仅支持有限的属性：文件名、文件创建时间戳、创建者的 uid 和 gid、文件模式和文件大小。

归档头部位于归档文件中偶数字节偏移处。如果某个归档成员的数据结束于奇数字节偏移处，则使用一个值为 0x0A 的填充字节将下一个归档头部定位到偶数字节偏移处。

归档头部由以下固定大小的字段组成：

**`ar_name`** （16 字节）归档成员的文件名。此字段的格式在 BSD 和 SVR4/GNU 格式之间有所不同，详见下文 “表示文件名” 小节。

**`ar_date`** （12 字节）成员的文件修改时间，以自纪元以来的秒数表示，编码为十进制数。

**`ar_uid`** （6 字节）与归档成员关联的 uid，编码为十进制数。

**`ar_gid`** （6 字节）与归档成员关联的 gid，编码为十进制数。

**`ar_mode`** （8 字节）归档成员的文件模式，编码为八进制数。

**`ar_size`** （10 字节）在 SVR4/GNU 归档格式中，此字段持有归档成员的字节大小，编码为十进制数。在 BSD 归档格式中，对于短文件名，此字段持有归档成员的字节大小，编码为十进制数。对于长文件名（见下文 “表示文件名” 小节），此字段包含归档成员及其文件名的合并大小，编码为十进制数。

**`ar_fmag`** （2 字节）此字段持有 2 个字节，值分别为 0x96 和 0x0A，标记头部的结束。

归档头部字段中未使用的字节设置为值 0x20。

### 表示文件名

BSD 和 SVR4/GNU 变体使用不同的方案来编码成员的文件名。

**BSD** 长度不超过 16 字节且不包含嵌入空格的文件名直接存储在归档头部的 `ar_name` 字段中。长度超过 16 字节或包含嵌入空格的文件名存储在归档头部之后，归档头部的 `ar_name` 字段设置为字符串 “#1/” 后跟文件名所需字节数的十进制表示。此外，归档头部的 `ar_size` 字段设置为归档成员和文件名合并大小的十进制表示。成员的文件内容紧跟在文件名之后，无需进一步填充。例如，如果某个成员的文件名为 “A B” 且其内容为字符串 “C D”，则头部的 `ar_name` 字段将包含 “`#1/3`”，头部的 `ar_size` 字段将包含 “`6`”，而头部之后的字节将是 0x41、0x20、0x42、0x43、0x20 和 0x44（ASCII “A BC D”）

**SVR4/GNU** 长度不超过 15 个字符的文件名直接存储在头部的 `ar_name` 字段中，以 “`/`” 字符终止。如果文件名大于 `ar_name` 字段所能容纳的空间，则实际文件名保存在归档字符串表（见下文 “归档字符串表” 小节）中，文件名在字符串表中的十进制偏移量存储在 `ar_name` 字段中，以 “`/`” 字符为前缀。例如，如果实际文件名已存储在归档字符串表的偏移量 768 处，则头部的 `ar_name` 字段将包含字符串 “/768”。

### 特殊归档成员

以下归档成员是特殊的。

**“`/`”** 在 SVR4/GNU 变体的归档格式中，名为 “`/`” 的归档成员表示归档符号表。如果存在，此成员将是归档中的第一个成员。

**“`//`”** 在 SVR4/GNU 变体的归档格式中，名为 “`//`” 的归档成员表示归档字符串表。此特殊成员用于保存无法容纳在头部的文件名字段中的文件名（见上文 “表示文件名” 小节）。如果存在，此成员紧跟在归档符号表之后（如果存在归档符号表），否则为第一个成员。

**“`__.SYMDEF`”** 此特殊成员在 BSD 变体的归档格式中包含归档符号表。如果存在，此成员将是归档中的第一个成员。

### 归档字符串表

归档字符串表用于 SVR4/GNU 归档格式，保存因过大而无法容纳在归档头部 `ar_name` 字段约束中的文件名。归档字符串表包含一系列文件名。归档字符串表中的每个文件名以字节序列 0x2F、0x0A（ASCII 字符串 “/en”）终止。不在相邻文件名之间使用填充。

### 归档符号表

归档符号表用于通过提供归档中定义的程序符号与对应归档成员之间的映射来加速链接编辑。归档符号表由 [ranlib(1)](/man1/ar.1.md) 实用程序管理。

归档符号表的格式如下：

**`ran_strx`** （C `long`）此字段包含符号名在符号字符串表中从零开始的偏移量。

**`ran_off`** （C `long`）此字段是定义该符号的归档成员的归档头部的文件偏移量。

**BSD** 在 BSD 归档格式中，归档符号表由两部分组成：一部分包含 `struct ranlib` 描述符数组，另一部分包含符号字符串表。构成 BSD 格式归档符号表的结构的大小和布局取决于具体机器。包含 `struct ranlib` 描述符的部分以一个字段开始，该字段包含以 C `long` 值编码的 `struct ranlib` 描述符数组的字节大小。`struct ranlib` 描述符数组紧跟在大小字段之后。每个 `struct ranlib` 描述符描述一个符号。一个 `struct ranlib` 描述符包含两个字段：包含符号字符串表的部分以一个字段开始，该字段包含以 C `long` 值编码的字符串表的字节大小。此字符串表紧跟在大小字段之后，包含符号表中符号的以 NUL 结尾的字符串。

**SVR4/GNU** 在 SVR4/GNU 归档格式中，归档符号表以一个 4 字节的二进制值开始，该值包含归档符号表中包含的条目数。此条目计数以最高有效字节在前的方式存储。接下来是 `count` 个 4 字节数字，每个都以最高有效字节在前的方式存储。每个数字是对应符号表条目的成员在归档文件中归档头部的二进制偏移量。在二进制偏移值之后，依次有 `count` 个以 NUL 结尾的字符串，保存对应符号表条目的符号名。

## 标准合规

[ar(1)](/man1/ar.1.md) 归档格式目前未由任何标准规定。

本手册页记录了 4.4BSD 和 UNIX 操作系统版本所使用的 [ar(1)](/man1/ar.1.md) 归档格式。

## 参见

[ar(1)](/man1/ar.1.md), [ld(1)](/man1/ld.lld.1.md), [ranlib(1)](/man1/ar.1.md), elf(3), elf\_getarsym(3), elf\_rand(3)
