Skip to content

Commit 22468ff

Browse files
authored
Merge pull request #373 from ishitatsuyuki/tlsdesc
Add specification for TLS descriptors
2 parents 2d77081 + eaf0b30 commit 22468ff

File tree

1 file changed

+146
-2
lines changed

1 file changed

+146
-2
lines changed

riscv-elf.adoc

Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ Description:: Additional information about the relocation
368368
<| S + A + TLSOFFSET
369369
.2+| 11 .2+| TLS_TPREL64 .2+| Dynamic | _word64_ .2+|
370370
<| S + A + TLSOFFSET
371+
.2+| 12 .2+| TLSDESC .2+| Dynamic | See <<TLS Descriptors>> .2+|
372+
<| TLSDESC(S+A)
371373
.2+| 16 .2+| BRANCH .2+| Static | _B-Type_ .2+| 12-bit PC-relative branch offset
372374
<| S + A - P
373375
.2+| 17 .2+| JAL .2+| Static | _J-Type_ .2+| 20-bit PC-relative jump offset
@@ -452,7 +454,15 @@ Description:: Additional information about the relocation
452454
<| S + A
453455
.2+| 61 .2+| SUB_ULEB128 .2+| Static | _ULEB128_ .2+| Local label subtraction <<uleb128-note,*note>>
454456
<| V - S - A
455-
.2+| 62-191 .2+| *Reserved* .2+| - | .2+| Reserved for future standard use
457+
.2+| 62 .2+| TLSDESC_HI20 .2+| Static | _U-Type_ .2+| High 20 bits of a 32-bit PC-relative offset into a TLS descriptor entry, `%tlsdesc_hi(symbol)`
458+
<| S + A - P
459+
.2+| 63 .2+| TLSDESC_LOAD_LO12 .2+| Static | _I-Type_ .2+| Low 12 bits of a 32-bit PC-relative offset into a TLS descriptor entry, `%tlsdesc_load_lo(address of %tlsdesc_hi)`, the addend must be 0
460+
<| S - P
461+
.2+| 64 .2+| TLSDESC_ADD_LO12 .2+| Static | _I-Type_ .2+| Low 12 bits of a 32-bit PC-relative offset into a TLS descriptor entry, `%tlsdesc_add_lo(address of %tlsdesc_hi)`, the addend must be 0
462+
<| S - P
463+
.2+| 65 .2+| TLSDESC_CALL .2+| Static | .2+| Annotate call to TLS descriptor resolver function, `%tlsdesc_call(address of %tlsdesc_hi)`, for relaxation purposes only
464+
<|
465+
.2+| 66-191 .2+| *Reserved* .2+| - | .2+| Reserved for future standard use
456466
<|
457467
.2+| 192-255 .2+| *Reserved* .2+| - | .2+| Reserved for nonstandard ABI extensions
458468
<|
@@ -805,7 +815,7 @@ thread local storage models:
805815

806816
[[tls-model]]
807817
.TLS models
808-
[cols="1,2,3"]
818+
[cols="1,2"]
809819
[width=70%]
810820
|===
811821
| Mnemonic | Model
@@ -941,6 +951,55 @@ typedef struct
941951
} tls_index;
942952
----
943953

954+
==== TLS Descriptors
955+
956+
TLS Descriptors (TLSDESC) are an alternative implementation of the Global Dynamic model
957+
that allows the dynamic linker to achieve performance close to that
958+
of Initial Exec when the library was not loaded dynamically with `dlopen`.
959+
960+
The linker reserves a consecutive pair of pointer-sized entry in the GOT for each `TLSDESC`
961+
relocation. At runtime, the dynamic linker fills in the TLS descriptor entry as defined below:
962+
963+
[,c]
964+
----
965+
typedef struct
966+
{
967+
unsigned long (*entry)(tls_descriptor *);
968+
unsigned long arg;
969+
} tls_descriptor;
970+
----
971+
972+
Upon accessing the thread local variable, the `entry` function is called with the address
973+
of `tls_descriptor` containing it, returning `<address of thread local variable> - tp`.
974+
975+
The TLS descriptor `entry` is called with a special calling convention, specified as follows:
976+
977+
- `a0` is used to pass the argument and return value.
978+
- `t0` is used as the link register.
979+
- Any other registers are callee-saved. This includes any vector registers when the vector extension is supported.
980+
981+
Example assembler load and store of a thread local variable `i` using the `%tlsdesc_hi`, `%tlsdesc_load_lo`, `%tlsdesc_add_lo` and `%tlsdesc_call`
982+
assembler functions. The emitted relocations are in the comments.
983+
984+
[,asm]
985+
----
986+
label:
987+
auipc tX, %tlsdesc_hi(symbol) // R_RISCV_TLSDESC_HI20 (symbol)
988+
lw tY, tX, %tlsdesc_load_lo(label) // R_RISCV_TLSDESC_LOAD_LO12_I (label)
989+
addi a0, tX, %tlsdesc_add_lo(label) // R_RISCV_TLSDESC_ADD_LO12_I (label)
990+
jalr t0, tY, %tlsdesc_call(label) // R_RISCV_TLSDESC_CALL (label)
991+
----
992+
993+
`tX` and `tY` in the example may be replaced with any combination of two general purpose registers.
994+
995+
The `%tlsdesc_call` assembler function does not return a value and is used purely
996+
to associate the `R_RISCV_TLSDESC_CALL` relocation with the `jalr` instruction.
997+
998+
The linker can use the relocations to recognize the sequence and to perform relaxations. To ensure correctness, only the following changes to the sequence are allowed:
999+
1000+
- Instructions outside the sequence that do not clobber the registers used within the sequence may be inserted in-between the instructions of the sequence (known as instruction scheduling).
1001+
- Instructions in the sequence with no data dependency may be reordered. In the preceding example, the only instructions that can be reordered are `lw` and `addi`.
1002+
9441003
=== Sections
9451004

9461005
==== Section Types
@@ -1613,6 +1672,91 @@ Relaxation result:
16131672
----
16141673
--
16151674

1675+
==== TLS Descriptors -> Initial Exec Relaxation
1676+
1677+
Target Relocation:: R_RISCV_TLSDESC_HI20, R_RISCV_TLSDESC_LOAD_LO12_I, R_RISCV_TLSDESC_ADD_LO12_I, R_RISCV_TLSDESC_CALL
1678+
1679+
Description:: This relaxation can relax a sequence loading the address of a thread-local symbol reference into a GOT load instruction.
1680+
1681+
Condition::
1682+
- Linker output is an executable.
1683+
1684+
Relaxation::
1685+
1686+
- Instruction associated with `R_RISCV_TLSDESC_HI20` or `R_RISCV_TLSDESC_LOAD_LO12_I` can be removed.
1687+
- Instruction associated with `R_RISCV_TLSDESC_ADD_LO12_I` can be replaced with load of the high PC-relative offset of the symbol's GOT entry.
1688+
- Instruction associated with `R_RISCV_TLSDESC_CALL` can be replaced with load of the low PC-relative offset of the symbol's GOT entry.
1689+
Example::
1690+
+
1691+
--
1692+
Relaxation candidate (`tX` and `tY` can be any combination of two general purpose registers):
1693+
1694+
[,asm]
1695+
----
1696+
label:
1697+
auipc tX, <hi> // R_RISCV_TLSDESC_HI20 (symbol), R_RISCV_RELAX
1698+
lw tY, tX, <lo> // R_RISCV_TLSDESC_LOAD_LO12_I (label), R_RISCV_RELAX
1699+
addi a0, tX, <lo> // R_RISCV_TLSDESC_ADD_LO12_I (label), R_RISCV_RELAX
1700+
jalr t0, tY // R_RISCV_TLSDESC_CALL (label), R_RISCV_RELAX
1701+
----
1702+
1703+
Relaxation result:
1704+
1705+
[,asm]
1706+
----
1707+
lui a0, <pcrel-got-offset-for-symbol-hi>
1708+
{ld,lw} a0, <pcrel-got-offset-for-symbol-lo>(a0)
1709+
----
1710+
--
1711+
1712+
==== TLS Descriptors -> Local Exec Relaxation
1713+
1714+
Target Relocation:: R_RISCV_TLSDESC_HI20, R_RISCV_TLSDESC_LOAD_LO12_I, R_RISCV_TLSDESC_ADD_LO12_I, R_RISCV_TLSDESC_CALL
1715+
1716+
Description:: This relaxation can relax a sequence loading the address of a thread-local symbol reference into a thread-pointer-relative instruction sequence.
1717+
1718+
Condition::
1719+
1720+
- Short form only: Offset between thread-pointer and thread-local symbol is within +-2KiB.
1721+
- Linker output is an executable.
1722+
- Target symbol is non-preemptible.
1723+
1724+
Relaxation::
1725+
1726+
- Instruction associated with `R_RISCV_TLSDESC_HI20` or `R_RISCV_TLSDESC_LOAD_LO12_I` can be removed.
1727+
- Instruction associated with `R_RISCV_TLSDESC_ADD_LO12_I` can be replaced with the high TP-relative offset of symbol (long form) or be removed (short form).
1728+
- Instruction associated with `R_RISCV_TLSDESC_CALL` can be replaced with the low TP-relative offset of symbol.
1729+
1730+
Example::
1731+
+
1732+
--
1733+
Relaxation candidate (`tX` and `tY` can be any combination of two general purpose registers):
1734+
1735+
[,asm]
1736+
----
1737+
label:
1738+
auipc tX, <hi> // R_RISCV_TLSDESC_HI20 (symbol), R_RISCV_RELAX
1739+
lw tY, tX, <lo> // R_RISCV_TLSDESC_LOAD_LO12_I (label), R_RISCV_RELAX
1740+
addi a0, tX, <lo> // R_RISCV_TLSDESC_ADD_LO12_I (label), R_RISCV_RELAX
1741+
jalr t0, tY // R_RISCV_TLSDESC_CALL (label), R_RISCV_RELAX
1742+
----
1743+
1744+
Relaxation result (long form):
1745+
1746+
[,asm]
1747+
----
1748+
lui a0, <tp-offset-for-symbol-hi>
1749+
addi a0, a0, <tp-offset-for-symbol-lo>
1750+
----
1751+
1752+
Relaxation result (short form):
1753+
1754+
[,asm]
1755+
----
1756+
addi a0, zero, <tp-offset-for-symbol>
1757+
----
1758+
--
1759+
16161760
==== Table Jump Relaxation
16171761

16181762
Target Relocation::: R_RISCV_CALL, R_RISCV_CALL_PLT, R_RISCV_JAL.

0 commit comments

Comments
 (0)