Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Update ELF psABI spec to include new ABI types #20

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 98 additions & 31 deletions docs/LoongArch-ELF-ABI-CN.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ v1.00
临时寄存器也被称为调用者保存寄存器。
静态寄存器也被称为被调用者保存寄存器。


== C 语言数据类型规格

.LP64 ABI
Expand Down Expand Up @@ -153,11 +154,15 @@ v1.00

`char` 是有符号类型。


== ELF 目标文件

=== EI_CLASS: ELF 文件格式
本节内容中关于 ELF 目标文件的通用格式定义
均参考 http://sco.com/developers/gabi/latest/contents.html[最新版本的 SysV gABI]。

[%header,cols="2m,^1,^3"]
=== `EI_CLASS`: ELF 文件格式

[%header,cols="2m,^1m,^3"]
|===
|EI_CLASS
|枚举值
Expand All @@ -172,64 +177,95 @@ v1.00
|64 位 ELF 格式
|===

=== e_machine: 体系结构 ID
=== `e_machine`: 体系结构 ID

`LoongArch (258)`

LoongArch (258)
=== `e_flags`: ABI 类型和版本标记

=== e_flags: ABI 变体标记
[%header,cols="1,1,1,1"]
|=========================================
|`[1:0]` 位 | `[5:2]` 位 | `[17:16]` 位 | `[31:18]` `[15:6]` 位
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

从左到右按低位到高位依次解释,/31:18... 1:0/,这样更好看一些?


| 整型 ABI | 浮点 / 扩展 ABI | ABI 版本 | (保留)
|=========================================

`e_flags[5:0]` 标记了 ELF 目标文件使用的 ABI 类型。
其中, `e_flags[1:0]` 标记整型 ABI, `e_flags[5:2]` 标记浮点 / 扩展 ABI。

.整型 ABI 标记
[%header,cols="2m,^1,^3"]
|===
|ABIs
|整型 ABI 名称
|枚举值
|含义

|lp32
|0x1
|32 位整型 ABI,仅支持软件浮点数
|lp64
|`0x3`
|使用 64 位通用寄存器和栈传参

|ilp32
|`0x1`
|使用 32 位通用寄存器和栈传参

|(保留值)
|0x2
|`0x2` `0x0`
|--
|===

|lp64
|0x3
|64 位整型 ABI,支持双精度硬件浮点数
.浮点 / 扩展 ABI 标记
[%header,cols="2m,^1,^3"]
|===
|浮点 / 扩展 ABI 名称
|枚举值
|含义

|double
|`0x0`
|使用 64 位浮点寄存器传参

|lp32f
|0x4
|32 位整型 ABI,支持单精度硬件浮点数
|soft
|`0x3`
|不使用浮点寄存器传参

|lp32d
|0x5
|32 位整型 ABI,支持双精度硬件浮点数
|single
|`0x2`
|使用 32 位浮点寄存器传参

|(保留值)
|0x6 --
|`0x1` `0x4 - 0xf`
|--
|===

=== ABI 版本
[[abi-versioning]]
`e_flags[17:16]` 标记了 ELF 目标文件使用的 ABI 版本,
它和动态链接器标准文件名 (`ld-*.so`) 的版本后缀一一对应。

[%header,cols="2m,^1,^5"]
.ABI 版本标记
[%header,cols="2,^1,^5,^1"]
|===
|ABI 版本
|枚举值
|描述
|动态链接器版本后缀

|v0
|0
|支持具有栈操作语义的重定位类型(旧版兼容)
|`v0`
|`0x0`
|支持具有栈操作语义的重定位类型
|`.1`

|v1
|1
|新版重定位类型
|`v1`
|`0x1`
|按需保留
|`.2`

|--
|2 --
|保留
|`--`
|`0x2` `0x3`
|(保留值)
|`.3` `.4`
|===


== 重定位类型

.ELF 重定位类型
Expand Down Expand Up @@ -524,3 +560,34 @@ LoongArch (258)
|GNU C++ vtable 支持
|
|===


== 动态链接器路径

.各 ABI 类型对应的动态链接器路径惯例:
[%header,cols="^1m,^3m"]
|===
|ABI 类型
|Glibc 动态链接器路径

|lp64/double
|/lib64/ld-linux-loongarch-lp64-df.so.<abiversion>

|lp64/single
|/lib64/ld-linux-loongarch-lp64-sf.so.<abiversion>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我怎么感觉看到 sf 的第一反应,应该是 soft float?而现在是表示为 single float 的。

按目前的规则,缩写为2个字母,那么 single floatsoft float 都是可以缩写为 sf 的,这样存在比较明显的歧义,或者说不具备唯一性,建议重新考虑一下这里的命名方案。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

讨论了一下。我们认为在有-df的情况下,-sf的歧义并不是很大。

选用两个字母后缀单独标定浮点/扩展ABI类型的原因是:

  1. 我们希望编译器的ABI命令行选项 (-mabi / -mfloat-abi) 和动态链接器名称能有一个明显的对应关系。
  2. 为了让命令行界面的逻辑保持简单,我们不太希望提供功能较复杂的ABI选项别名 (例如-mabi=lp64d)。
    (这个是集体意见)

在满足这个要求的情况下,感觉并没有更好的方案。(RISC-V的MUSL动态链接器也用两个字母后缀标定浮点ABI,单精度对应-sp,软浮点对应-sf,也并没有特别一目了然)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在满足这个要求的情况下,感觉并没有更好的方案。(RISC-V的MUSL动态链接器也用两个字母后缀标定浮点ABI,单精度对应-sp,软浮点对应-sf,也并没有特别一目了然)

那是不是可以和它们保持一致呢(单精度对应-sp,软浮点对应-sf)?感觉没必要对相同的东西采用不同的缩写。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

它没有"-df"这种情况,64位整数 + 双精度浮点ABI对应的就是"ld-musl-riscv64.so.1"。我们还是比较希望保持各ABI类型的后缀格式一样。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没有其他更好方案的话,就尽快按这个执行吧。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoongArch LP64 ABI 不隐含支持 SP/DP 硬浮点?

如果隐含支持的话,LP64 不需要特意标注。否则的话,RV 的做法是在 ABI 名字里带上“F/D”字样,建议是 LA 这边也一样写成“LP64/LP64F/LP64D”的形式,否则单说“LP64”不能精确指定一个 ABI 了。但考虑到先前已经进行的工作都把 LP64(-mabi=lp64)当作支持双精度硬浮点看待了,那可能我们得采用 LP64S/LP64F/LP64 之类的写法了。

无论如何,nf 表示软浮点都不是一个好的选择,我除了用中式英语理解为“non float”之外找不到任何可行的解释可以说明“n”的含义。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

参见 #23 的讨论,lp64 确实不代表完整的 ABI 类型,也不隐含支持硬浮点,使用双精度硬浮点传参的 ABI 是 lp64/doublenf 代表 no fpu


|lp64/soft
|/lib64/ld-linux-loongarch-lp64-nf.so.<abiversion>

|ilp32/double
|/lib32/ld-linux-loongarch-ilp32-df.so.<abiversion>

|ilp32/single
|/lib32/ld-linux-loongarch-ilp32-sf.so.<abiversion>

|ilp32/soft
|/lib32/ld-linux-loongarch-ilp32-nf.so.<abiversion>
|===

表中 `<abiversion>` 与 ELF文件编码的 `e_flags[17:16]` 一一对应,
参见 <<abi-versioning, ABI 版本>> 。
133 changes: 101 additions & 32 deletions docs/LoongArch-ELF-ABI-EN.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ v1.00
Temporary registers are also known as caller-saved registers.
Static registers are also known as callee-saved registers.


== Type Size and Alignment

.LP64 ABI
Expand Down Expand Up @@ -151,11 +152,15 @@ Static registers are also known as callee-saved registers.

`char` is signed.


== ELF Object Files

=== EI_CLASS: File class
All common ELF definitions referenced in this section
can be found in http://sco.com/developers/gabi/latest/contents.html[the latest SysV gABI specification].

[%header,cols="2m,^1,^3"]
=== `EI_CLASS`: File class

[%header,cols="2m,^1m,^3"]
|===
|EI_CLASS
|Value
Expand All @@ -170,64 +175,97 @@ Static registers are also known as callee-saved registers.
|64-bit objects
|===

=== e_machine: Identifies the machine
=== `e_machine`: Identifies the machine

`LoongArch (258)`

LoongArch (258)
=== `e_flags`: Identifies ABI type and version

=== e_flags: Identifies the ABIs of this ELF file
[%header,cols="1,1,1,1"]
|====
| Bit 0 - 1 | Bit 2 - 5 | Bit 16 - 17 | Bit 6 - 15, 18 - 31

| integer ABI | floating-point/extended ABI | ABI version | (reserved)
|====

The ABI type of an ELF object is described by `e_flags[5:0]` in its header,
where `e_flags[1:0]` encodes the integer ABI type while `e_flags[5:2]` encodes
the floating-point/extended ABI type.

.Integer ABI types
[%header,cols="2m,^1,^3"]
|===
|ABIs
|Value
|Name
|`e_flags[1:0]`
|Description

|lp32
|0x1
|soft float
|lp64
|`0x3`
|64-bit GPRs and the stack are used for parameter passing.

|Reserved
|0x2
|ilp32
|`0x1`
|32-bit GPRs and the stack are used for parameter passing.

|(reserved)
|`0x2` `0x0`
|--
|===

|lp64
|0x3
|64bit default ABI
.Floating-point / extended ABI types
[%header,cols="2m,^1,^3"]
|===
|Name
|`e_flags[5:2]`
|Description

|lp32f
|0x4
|single float
|double
|`0x0`
|64-bit FPRs are used for parameter passing.

|lp32d
|0x5
|double float
|soft
|`0x3`
|No FPR is used for parameter passing.

|Reserved
|0x6 --
|single
|`0x2`
|32-bit FPRs are used for parameter passing.

|(reserved)
|`0x1` `0x4 - 0xf`
|--
|===

=== ABI Version
[[abi-versioning]]
`e_flags[17:16]` marks the ABI version of an ELF object,
it also corresponds to the version suffix of standard
program interpreters (`ld-*.so`).

[%header,cols="2m,^1,^5"]
.ABI Version
[%header,cols="2,^1,^5,^1"]
|===
|ABI Version:
|ABI version
|Value
|Description
|Program interpreter version suffix

|v0
|0
|`v0`
|`0x0`
|Stack operands base relocation type.
|`.1`

|v1
|1
|`v1`
|`0x1`
|Another relocation type IF needed.
|`.2`

|--
|2 --
|`--`
|`0x2` `0x3`
|Reserved.
|`.3` `.4`
|===


== Relocations

.ELF Relocation types
Expand Down Expand Up @@ -522,3 +560,34 @@ with check 32-bit unsigned overflow
|GNU C++ vtable member usage
|
|===


== Program Interpreter Path

.Program interpreter paths of different ABI types:
[%header,cols="^1m,^3m"]
|===
|ABI Type
|Glibc dynamic linker path

|lp64/double
|/lib64/ld-linux-loongarch-lp64-df.so.<abiversion>

|lp64/single
|/lib64/ld-linux-loongarch-lp64-sf.so.<abiversion>

|lp64/soft
|/lib64/ld-linux-loongarch-lp64-nf.so.<abiversion>

|ilp32/double
|/lib32/ld-linux-loongarch-ilp32-df.so.<abiversion>

|ilp32/single
|/lib32/ld-linux-loongarch-ilp32-sf.so.<abiversion>

|ilp32/soft
|/lib32/ld-linux-loongarch-ilp32-nf.so.<abiversion>
|===

Note: Each ABI version listed in <<abi-versioning, ABI versions>> corresponds
to a unique `<abiversion>`.