mirror of
https://github.com/ipxe/ipxe
synced 2025-12-08 10:20:24 +03:00
[riscv] Use compressed relocation records
Use compressed relocation records instead of raw Elf_Rela records. This saves around 15% of the total binary size for the all-drivers image bin-riscv64/ipxe.sbi. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
# prefix code.
|
# prefix code.
|
||||||
#
|
#
|
||||||
CFLAGS += -mcmodel=medany -fpie
|
CFLAGS += -mcmodel=medany -fpie
|
||||||
LDFLAGS += -pie --no-dynamic-linker
|
LDFLAGS += -pie --no-dynamic-linker -z combreloc
|
||||||
|
|
||||||
# Linker script
|
# Linker script
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -32,14 +32,23 @@
|
|||||||
.section ".note.GNU-stack", "", @progbits
|
.section ".note.GNU-stack", "", @progbits
|
||||||
.text
|
.text
|
||||||
|
|
||||||
|
/* Virtual address of _prefix
|
||||||
|
*
|
||||||
|
* This will be updated if runtime relocations are applied.
|
||||||
|
*/
|
||||||
|
.section ".rodata.prefix_virt", "a", @progbits
|
||||||
|
prefix_virt:
|
||||||
|
.dword _prefix
|
||||||
|
.size prefix_virt, . - prefix_virt
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* Apply relocation records
|
* Apply compressed relocation records
|
||||||
*
|
*
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
*
|
*
|
||||||
* Apply relocation records from .rel.dyn to fix up iPXE to run at its
|
* Apply compressed relocation records to fix up iPXE to run at its
|
||||||
* current address.
|
* current virtual address.
|
||||||
*
|
*
|
||||||
* This function must run before .bss is zeroed (since the relocation
|
* This function must run before .bss is zeroed (since the relocation
|
||||||
* records are overlaid with .bss). It does not require a valid stack
|
* records are overlaid with .bss). It does not require a valid stack
|
||||||
@@ -51,58 +60,63 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Relative relocation type */
|
/** Number of bits in a skip value */
|
||||||
#define R_RISCV_RELATIVE 3
|
#define ZREL_SKIP_BITS 19
|
||||||
|
|
||||||
/* Layout of a relocation record */
|
|
||||||
.struct 0
|
|
||||||
rela_offset: .space ( __riscv_xlen / 8 )
|
|
||||||
rela_type: .space ( __riscv_xlen / 8 )
|
|
||||||
rela_addend: .space ( __riscv_xlen / 8 )
|
|
||||||
rela_len:
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.section ".prefix.apply_relocs", "ax", @progbits
|
.section ".prefix.apply_relocs", "ax", @progbits
|
||||||
.globl apply_relocs
|
.globl apply_relocs
|
||||||
apply_relocs:
|
apply_relocs:
|
||||||
|
/* Register usage:
|
||||||
|
*
|
||||||
|
* a0 - relocation addend
|
||||||
|
* a1 - current relocation target address
|
||||||
|
* a2 - current relocation record pointer
|
||||||
|
* a3 - current relocation record value
|
||||||
|
* a4 - number of bits remaining in current relocation record
|
||||||
|
*/
|
||||||
|
la a1, _prefix
|
||||||
|
la a2, _edata
|
||||||
|
|
||||||
/* Get relocation records */
|
/* Calculate relocation addend */
|
||||||
la t0, _reloc
|
la t0, prefix_virt
|
||||||
la t1, _ereloc
|
LOADN a0, (t0)
|
||||||
|
sub a0, a1, a0
|
||||||
|
|
||||||
/* Determine current location */
|
/* Skip applying relocations if addend is zero */
|
||||||
la t2, reloc_base
|
beqz a0, apply_relocs_done
|
||||||
LOADN t2, (t2)
|
|
||||||
sub t2, t0, t2
|
|
||||||
|
|
||||||
1: /* Read relocation record */
|
apply_relocs_loop:
|
||||||
LOADN t3, rela_offset(t0)
|
/* Read new relocation record */
|
||||||
LOADN t4, rela_type(t0)
|
LOADN a3, (a2)
|
||||||
LOADN t5, rela_addend(t0)
|
addi a2, a2, ( __riscv_xlen / 8 )
|
||||||
|
li a4, ( __riscv_xlen - 1 )
|
||||||
|
|
||||||
/* Check relocation type */
|
/* Consume and apply skip, if present (i.e. if MSB=0) */
|
||||||
addi t4, t4, -R_RISCV_RELATIVE
|
bltz a3, 1f
|
||||||
bnez t4, 2f
|
addi a4, a4, -ZREL_SKIP_BITS
|
||||||
|
srli t0, a3, ( __riscv_xlen - ( ZREL_SKIP_BITS + 1 ) )
|
||||||
|
slli t0, t0, ( ( __riscv_xlen / 32 ) + 1 )
|
||||||
|
add a1, a1, t0
|
||||||
|
1:
|
||||||
|
/* Apply relocations corresponding to set bits in record */
|
||||||
|
1: andi t0, a3, 1
|
||||||
|
beqz t0, 2f
|
||||||
|
LOADN t1, (a1)
|
||||||
|
add t1, t1, a0
|
||||||
|
STOREN t1, (a1)
|
||||||
|
2: addi a1, a1, ( __riscv_xlen / 8 )
|
||||||
|
srli a3, a3, 1
|
||||||
|
addi a4, a4, -1
|
||||||
|
bnez a4, 1b
|
||||||
|
|
||||||
/* Apply relocation */
|
/* Loop until we have reached a terminator record (MSB=0, offset=0) */
|
||||||
add t3, t3, t2
|
bnez a3, apply_relocs_loop
|
||||||
add t5, t5, t2
|
|
||||||
STOREN t5, (t3)
|
|
||||||
2:
|
|
||||||
/* Loop until done */
|
|
||||||
addi t0, t0, rela_len
|
|
||||||
blt t0, t1, 1b
|
|
||||||
|
|
||||||
|
apply_relocs_done:
|
||||||
/* Return to caller */
|
/* Return to caller */
|
||||||
ret
|
ret
|
||||||
.size apply_relocs, . - apply_relocs
|
.size apply_relocs, . - apply_relocs
|
||||||
|
|
||||||
/* Link-time address of _reloc */
|
|
||||||
.section ".rodata", "a", @progbits
|
|
||||||
reloc_base:
|
|
||||||
.dword _reloc_base
|
|
||||||
.size reloc_base, . - reloc_base
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* Enable paging
|
* Enable paging
|
||||||
@@ -187,12 +201,6 @@ reloc_base:
|
|||||||
.globl enable_paging
|
.globl enable_paging
|
||||||
.equ enable_paging, _C2 ( enable_paging_, __riscv_xlen )
|
.equ enable_paging, _C2 ( enable_paging_, __riscv_xlen )
|
||||||
|
|
||||||
/* Link-time address of _prefix */
|
|
||||||
.section ".rodata.prefix_virt", "a", @progbits
|
|
||||||
prefix_virt:
|
|
||||||
.dword _prefix
|
|
||||||
.size prefix_virt, . - prefix_virt
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* Enable 64-bit paging
|
* Enable 64-bit paging
|
||||||
|
|||||||
@@ -41,6 +41,9 @@
|
|||||||
#define SBI_SRST_SYSTEM_RESET 0x00
|
#define SBI_SRST_SYSTEM_RESET 0x00
|
||||||
#define SBI_RESET_COLD 0x00000001
|
#define SBI_RESET_COLD 0x00000001
|
||||||
|
|
||||||
|
/* ELF machine type */
|
||||||
|
#define EM_RISCV 243
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Display progress message via debug console
|
* Display progress message via debug console
|
||||||
*/
|
*/
|
||||||
@@ -127,5 +130,12 @@ _sbi_start:
|
|||||||
.section ".zinfo", "a", @progbits
|
.section ".zinfo", "a", @progbits
|
||||||
.ascii "COPY"
|
.ascii "COPY"
|
||||||
.word 0
|
.word 0
|
||||||
.word _sbi_filesz
|
.word _filesz
|
||||||
.word 1
|
.word 1
|
||||||
|
.ascii "BASE"
|
||||||
|
.word 0
|
||||||
|
.dword _base
|
||||||
|
.ascii "ZREL"
|
||||||
|
.word _reloc_offset
|
||||||
|
.word _reloc_filesz
|
||||||
|
.word EM_RISCV
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ SECTIONS {
|
|||||||
|
|
||||||
/* Runtime relocations (discarded after use) */
|
/* Runtime relocations (discarded after use) */
|
||||||
.rela.dyn {
|
.rela.dyn {
|
||||||
_reloc = .;
|
|
||||||
*(.rela)
|
*(.rela)
|
||||||
*(.rela.dyn)
|
*(.rela.dyn)
|
||||||
}
|
}
|
||||||
@@ -88,25 +87,15 @@ SECTIONS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Absolute link-time address of _reloc
|
/* Base virtual address */
|
||||||
*
|
_base = ABSOLUTE ( _prefix );
|
||||||
* The runtime relocator needs to know the link-time addresses.
|
|
||||||
* Since RISC-V uses .rela (rather than .rel), the only way to
|
|
||||||
* expose this to the relocator is via an absolute symbol.
|
|
||||||
*/
|
|
||||||
_reloc_base = ABSOLUTE ( _reloc );
|
|
||||||
|
|
||||||
/* Calculate end of relocations
|
/* Relocations */
|
||||||
*
|
_reloc_offset = ( LOADADDR ( .rela.dyn ) - LOADADDR ( .prefix ) );
|
||||||
* This cannot be done by placing "_ereloc = .;" inside the
|
_reloc_filesz = SIZEOF ( .rela.dyn );
|
||||||
* .rela.dyn section, since the dynamic relocations are not
|
|
||||||
* present in the input sections but are instead generated during
|
|
||||||
* linking.
|
|
||||||
*/
|
|
||||||
_ereloc = ( _reloc + __load_stop_reladyn - __load_start_reladyn );
|
|
||||||
|
|
||||||
/* Length of initialised data */
|
/* Length of initialised data */
|
||||||
_sbi_filesz = ( ABSOLUTE ( _ereloc ) - ABSOLUTE ( _prefix ) );
|
_filesz = ( ABSOLUTE ( _edata ) - ABSOLUTE ( _prefix ) );
|
||||||
|
|
||||||
/* Unwanted sections */
|
/* Unwanted sections */
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
|
|||||||
Reference in New Issue
Block a user