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

Use EI_CLASS for base ABI encoding. #47

Merged
merged 2 commits into from
Aug 17, 2022
Merged
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
79 changes: 39 additions & 40 deletions docs/LoongArch-ELF-ABI-CN.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ v1.00

====

[[c-lang-data-model]]
== C 语言数据类型规格

[[dm-lp64]]
.LP64 数据模型 (对应基础 ABI 类型:`lp64d` `lp64f` `lp64s`)
[%header,cols="3,^1,^1"]
|===
Expand Down Expand Up @@ -179,6 +181,7 @@ v1.00
|16
|===

[[dm-ilp32]]
.ILP32 数据模型 (对应基础 ABI 类型:`ilp32d` `ilp32f` `ilp32s`)
[%header,cols="3,^1,^1"]
|===
Expand Down Expand Up @@ -235,7 +238,7 @@ v1.00
本节内容中关于 ELF 目标文件的通用格式定义
均参考 http://sco.com/developers/gabi/latest/contents.html[最新版本的 SysV gABI]。

=== `EI_CLASS`: ELF 文件格式
=== EI_CLASS: ELF 文件格式

[%header,cols="2m,^1m,^3"]
|===
Expand All @@ -245,80 +248,76 @@ v1.00

|ELFCLASS32
|1
|32 位 ELF 格式
|32 位 ELF 格式 (ELF32)

|ELFCLASS64
|2
|64 位 ELF 格式
|64 位 ELF 格式 (ELF64)
|===

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

`LoongArch (258)`

=== `e_flags`: ABI 类型和版本标记
=== e_flags: ABI 类型和版本标记

[%header,cols="1,1,1,1"]
|===
|`[31:8]` 位 | `[7:6]` 位 | `[5:3]` 位 | `[2:0]` 位

|(保留) | ABI 版本 | ABI 扩展特性 | 基础 ABI 类型
|(保留) | ABI 版本 | ABI 扩展特性 | 基础 ABI 修饰符
|===

`e_flags[7:0]` 完整标记了 ELF 目标文件使用的 ABI 类型。
`EI_CLASS` 和 `e_flags[7:0]` 完整确定了 ELF 目标文件使用的 ABI 类型。

其中,**基础 ABI 类型**由 `EI_CLASS` 和 `e_flags[2:0]` 共同标记,
前者唯一确定了 C 语言整数和指针类型的表示(<<c-lang-data-model, 数据模型>>)和传参方式,
后者则在此基础上表示其他基础 ABI 性质,如浮点类型传参方式,称为 **基础 ABI 修饰符**。

因此,龙芯架构的 ELF64 / ELF32 目标文件分别仅用于编码 `lp64*` / `ilp32*` ABI 的程序。

`0x0` `0x4` `0x5` `0x6` `0x7` 为 `e_flags[2:0]` 的保留值。

[[base-abi-type-marks]]
.基础 ABI 类型标记
[%header,cols="2m,^1,^3"]
[%header,cols="2m,^1m,^1m,^3"]
|===
|基础 ABI 名称
|枚举值 (`e_flags[2:0]`)
|EI_CLASS | 基础 ABI 修饰符 (`e_flags[2:0]`)
|含义

|
|`0x0`
|保留值

|lp64s
|`0x1`
|lp64s | ELFCLASS64 | 0x1
|使用 64 位通用寄存器和栈传参,
数据模型为 LP64(`long` 和指针类型宽度为64位,`int` 为32位)

|lp64f
|`0x2`
|使用 64 位通用寄存器,32位浮点寄存器和栈传参,
数据模型为 LP64(`long` 和指针类型宽度为64位,`int` 为32位)
数据模型为 <<dm-lp64, `LP64`>>(`long` 和指针类型宽度为 64 位,`int` 为 32 位)

|lp64d
|`0x3`
|使用 64 位通用寄存器,64位浮点寄存器和栈传参,
数据模型为 LP64(`long` 和指针类型宽度为64位,`int` 为32位)
|lp64f | ELFCLASS64 | 0x2
|使用 64 位通用寄存器,32 位浮点寄存器和栈传参,
数据模型为 <<dm-lp64, `LP64`>>(`long` 和指针类型宽度为 64 位,`int` 为 32 位)

|
|`0x4`
|保留值
|lp64d | ELFCLASS64 | 0x3
|使用 64 位通用寄存器,64 位浮点寄存器和栈传参,
数据模型为 <<dm-lp64, `LP64`>>(`long` 和指针类型宽度为 64 位,`int` 为 32 位)

|ilp32s
|`0x5`
|ilp32s | ELFCLASS32 | 0x1
|使用 32 位通用寄存器和栈传参,
数据模型为 ILP32(`int`,`long` 和指针类型宽度为32位
数据模型为 <<dm-ilp32, `ILP32`>>(`int`,`long` 和指针类型宽度为 32 位

|ilp32f
|`0x6`
|使用 32 位通用寄存器,32位浮点寄存器和栈传参,
数据模型为 ILP32(`int`,`long` 和指针类型宽度为32位)
|ilp32f | ELFCLASS32 | 0x2
|使用 32 位通用寄存器,32 位浮点寄存器和栈传参,
数据模型为 <<dm-ilp32, `ILP32`>>(`int`,`long` 和指针类型宽度为 32 位)

|ilp32d
|`0x7`
|使用 32 位通用寄存器,64位浮点寄存器和栈传参,
数据模型为 ILP32(`int`,`long` 和指针类型宽度为32位)
|ilp32d | ELFCLASS32 | 0x3
|使用 32 位通用寄存器,64 位浮点寄存器和栈传参,
数据模型为 <<dm-ilp32, `ILP32`>>(`int`,`long` 和指针类型宽度为 32 位)
|===

`e_flags[5:3]` 标记了 ABI 扩展特性。

.ABI 扩展特性标记
[%header,cols="2m,^1,^3"]
|===
|ABI 扩展特性名称
|枚举值 (`e_flags[5:3]`)
|e_flags[5:3]
|含义

|base
Expand Down
74 changes: 39 additions & 35 deletions docs/LoongArch-ELF-ABI-EN.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ For the components not yet upstream, and not interacting with other components t

====

[[c-lang-data-model]]
== Type Size and Alignment

[[dm-lp64]]
.LP64 Data Model (base ABI types: `lp64d` `lp64f` `lp64s`)
[%header,cols="3,^1,^1"]
|===
Expand Down Expand Up @@ -179,6 +181,7 @@ For the components not yet upstream, and not interacting with other components t
|16
|===

[[dm-ilp32]]
.ILP32 Data Model (base ABI types: `ilp32d` `ilp32f` `ilp32s`)
[%header,cols="3,^1,^1"]
|===
Expand Down Expand Up @@ -227,15 +230,16 @@ For the components not yet upstream, and not interacting with other components t
|16
|===

For all base ABI types of LoongArch, the `char` datatype is signed by default.
For all <<base-abi-type-marks, base ABI types>> of LoongArch,
the `char` datatype is signed by default.


== ELF Object Files

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].

=== `EI_CLASS`: File class
=== EI_CLASS: File class

[%header,cols="2m,^1m,^3"]
|===
Expand All @@ -252,71 +256,71 @@ can be found in http://sco.com/developers/gabi/latest/contents.html[the latest S
|ELF64 object file
|===

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

`LoongArch (258)`

=== `e_flags`: Identifies ABI type and version
=== e_flags: Identifies ABI type and version

[%header,cols="1,1,1,1"]
|====
| Bit 31 - 8 | Bit 7 - 6 | Bit 5 - 3 | Bit 2 - 0
| (reserved) | ABI version | ABI extension | Base ABI
| (reserved) | ABI version | ABI extension | Base ABI Modifier
|====

The ABI type of an ELF object is uniquely identified by `e_flags[7:0]` in its header.
The ABI type of an ELF object is uniquely identified by `EI_CLASS` and `e_flags[7:0]` in its header.

Within this combination, `EI_CLASS` and `e_flags[2:0]` correspond to the **base ABI** type,
where the expression of C integral and pointer types (<<c-lang-data-model, data model>>)
is uniquely determined by `EI_CLASS` value, and `e_flags[2:0]` represents additional properties
of the base ABI type, including the FP calling convention. We refer to `e_flags[2:0]` as
the **base ABI modifier*.

As a result, programs in `lp64*` / `ilp32*` ABI should only be encoded with ELF64 / ELF32
object files, respectively.

`0x0` `0x4` `0x5` `0x6` `0x7` are reserved values for `e_flags[2:0]`.

[[base-abi-type-marks]]
.Base ABI Types
[%header,cols="2m,^1,^3"]
[%header,cols="2m,^1m,^1m,^3"]
|===
|Name
|Value of `e_flags[2:0]`
|EI_CLASS | Base ABI Modifier (`e_flags[2:0]`)
|Description

|
|`0x0`
|(reserved)

|lp64s
|`0x1`
|lp64s | ELFCLASS64 | 0x1
|Uses 64-bit GPRs and the stack for parameter passing.
Data model is LP64, where `long` and pointers are 64-bit while `int` is 32-bit.
Data model is <<dm-lp64, LP64>>, where `long` and pointers are 64-bit while `int` is 32-bit.

|lp64f
|`0x2`
|lp64f | ELFCLASS64 | 0x2
|Uses 64-bit GPRs, 32-bit FPRs and the stack for parameter passing.
Data model is LP64, where `long` and pointers are 64-bit while `int` is 32-bit.
Data model is <<dm-lp64, LP64>>, where `long` and pointers are 64-bit while `int` is 32-bit.

|lp64d
|`0x3`
|lp64d | ELFCLASS64 | 0x3
|Uses 64-bit GPRs, 64-bit FPRs and the stack for parameter passing.
Data model is LP64, where `long` and pointers are 64-bit while `int` is 32-bit.

|
|`0x4`
|(reserved)
Data model is <<dm-lp64, LP64>>, where `long` and pointers are 64-bit while `int` is 32-bit.

|ilp32s
|`0x5`
|ilp32s | ELFCLASS32 | 0x1
|Uses 32-bit GPRs and the stack for parameter passing.
Data model is ILP32, where `int`, `long` and pointers are 32-bit.
Data model is <<dm-ilp32, ILP32>>, where `int`, `long` and pointers are 32-bit.

|ilp32f
|`0x6`
|ilp32f | ELFCLASS32 | 0x2
|Uses 32-bit GPRs, 32-bit FPRs and the stack for parameter passing.
Data model is ILP32, where `int`, `long` and pointers are 32-bit.
Data model is <<dm-ilp32, ILP32>>, where `int`, `long` and pointers are 32-bit.

|ilp32d
|`0x7`
|ilp32d | ELFCLASS32 | 0x3
|Uses 32-bit GPRs, 64-bit FPRs and the stack for parameter passing.
Data model is ILP32, where `int`, `long` and pointers are 32-bit.
Data model is <<dm-ilp32, ILP32>>, where `int`, `long` and pointers are 32-bit.
|===

`e_flags[5:3]` correspond to the ABI extension type.

.ABI Extension types
[%header,cols="2m,^1,^3"]
|===
|Name
|Value of `e_flags[5:3]`
|e_flags[5:3]
|Description

|base
Expand Down