@@ -736,8 +736,8 @@ for using any of the other PLT sytles.
736736[cols="1,2"]
737737[width=70%]
738738|===
739- | Default PLT | -
740- | Unlabeled landing pad PLT | Must use this PLT style when `GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED` is set.
739+ | Default PLT | -
740+ | Landing pad PLT | Must use this PLT style when `GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED` is set.
741741|===
742742
743743The first entry of a shared object PLT is a special entry that calls
@@ -749,12 +749,20 @@ dynamic linker before the executable is started. Lazy resolution of GOT
749749entries is intended to speed up program loading by deferring symbol
750750resolution to the first time the function is called.
751751
752+ Landing pad PLT can't be used with lazy binding.
753+
754+ NOTE: Landing pads are designed for use with Control-Flow Integrity (CFI).
755+ Lazy binding may delay resolution of indirect branches until runtime, potentially
756+ allowing attackers to hijack control flow before CFI protections are fully
757+ enforced. Therefore, lazy binding is considered unsafe in conjunction with
758+ landing pad-based PLTs.
759+
752760The first entry in the PLT occupies two 16 byte entries for the default PLT style:
753761
754762[,asm]
755763----
7567641: auipc t2, %pcrel_hi(.got.plt)
757- sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12
765+ sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12
758766 l[w|d] t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve
759767 addi t1, t1, -(hdr size + 12) # shifted .got.plt offset
760768 addi t0, t2, %pcrel_lo(1b) # &.got.plt
@@ -763,23 +771,24 @@ The first entry in the PLT occupies two 16 byte entries for the default PLT styl
763771 jr t3
764772----
765773
766- And occupies three 16 byte entries for the unlabeled landing pad PLT style:
774+ And occupies two 16 byte entries for the unlabeled landing pad PLT style:
775+
767776[,asm]
768777----
769- lpad 0
770- 1: auipc t2, %pcrel_hi(.got.plt)
771- sub t1, t1, t3 # shifted .got.plt offset + hdr size + 16
772- l[w|d] t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve
778+ 1: auipc t3, %pcrel_hi(.got.plt)
779+ sub t1, t1, t2 # shifted .got.plt offset + hdr size + 16
780+ l[w|d] t2, %pcrel_lo(1b)(t3) # _dl_runtime_resolve
773781 addi t1, t1, -(hdr size + 16) # shifted .got.plt offset
774- addi t0, t2 , %pcrel_lo(1b) # &.got.plt
782+ addi t0, t3 , %pcrel_lo(1b) # &.got.plt
775783 srli t1, t1, log2(16/PTRSIZE) # .got.plt offset
776784 l[w|d] t0, PTRSIZE(t0) # link map
777- jr t3
778- nop
779- nop
780- nop
785+ jr t2
781786----
782787
788+ NOTE: Although lazy binding is prohibited for landing pad PLTs, the PLT
789+ header is still retained so that features implemented by the C library, such
790+ as LD_AUDIT and LD_PROFILE in glibc, continue to function as intended.
791+
783792Subsequent function entry stubs in the PLT take up 16 bytes.
784793On the first call to a function, the entry redirects to the first PLT entry
785794which calls `_dl_runtime_resolve` and fills in the GOT entry for subsequent
@@ -794,13 +803,13 @@ The code sequences of the PLT entry for the default PLT style:
794803 nop
795804----
796805
797- The code sequences of the PLT entry for the unlabeled landing pad PLT style:
806+ The code sequences of the PLT entry for the landing pad PLT style:
798807[,asm]
799808----
800809 lpad 0
801- 1: auipc t3 , %pcrel_hi([email protected] ) 802- l[w|d] t3 , %pcrel_lo(1b)(t3 )
803- jalr t1, t3
810+ 1: auipc t2 , %pcrel_hi([email protected] ) 811+ l[w|d] t2 , %pcrel_lo(1b)(t2 )
812+ jalr t1, t2
804813----
805814
806815==== Procedure Calls
0 commit comments