mirror of
https://github.com/ipxe/ipxe
synced 2025-12-07 18:00:28 +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.
|
||||
#
|
||||
CFLAGS += -mcmodel=medany -fpie
|
||||
LDFLAGS += -pie --no-dynamic-linker
|
||||
LDFLAGS += -pie --no-dynamic-linker -z combreloc
|
||||
|
||||
# Linker script
|
||||
#
|
||||
|
||||
@@ -32,14 +32,23 @@
|
||||
.section ".note.GNU-stack", "", @progbits
|
||||
.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
|
||||
* current address.
|
||||
* Apply compressed relocation records to fix up iPXE to run at its
|
||||
* current virtual address.
|
||||
*
|
||||
* This function must run before .bss is zeroed (since the relocation
|
||||
* records are overlaid with .bss). It does not require a valid stack
|
||||
@@ -51,58 +60,63 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* Relative relocation type */
|
||||
#define R_RISCV_RELATIVE 3
|
||||
|
||||
/* 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
|
||||
/** Number of bits in a skip value */
|
||||
#define ZREL_SKIP_BITS 19
|
||||
|
||||
.section ".prefix.apply_relocs", "ax", @progbits
|
||||
.globl 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 */
|
||||
la t0, _reloc
|
||||
la t1, _ereloc
|
||||
/* Calculate relocation addend */
|
||||
la t0, prefix_virt
|
||||
LOADN a0, (t0)
|
||||
sub a0, a1, a0
|
||||
|
||||
/* Determine current location */
|
||||
la t2, reloc_base
|
||||
LOADN t2, (t2)
|
||||
sub t2, t0, t2
|
||||
/* Skip applying relocations if addend is zero */
|
||||
beqz a0, apply_relocs_done
|
||||
|
||||
1: /* Read relocation record */
|
||||
LOADN t3, rela_offset(t0)
|
||||
LOADN t4, rela_type(t0)
|
||||
LOADN t5, rela_addend(t0)
|
||||
apply_relocs_loop:
|
||||
/* Read new relocation record */
|
||||
LOADN a3, (a2)
|
||||
addi a2, a2, ( __riscv_xlen / 8 )
|
||||
li a4, ( __riscv_xlen - 1 )
|
||||
|
||||
/* Check relocation type */
|
||||
addi t4, t4, -R_RISCV_RELATIVE
|
||||
bnez t4, 2f
|
||||
/* Consume and apply skip, if present (i.e. if MSB=0) */
|
||||
bltz a3, 1f
|
||||
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 */
|
||||
add t3, t3, t2
|
||||
add t5, t5, t2
|
||||
STOREN t5, (t3)
|
||||
2:
|
||||
/* Loop until done */
|
||||
addi t0, t0, rela_len
|
||||
blt t0, t1, 1b
|
||||
/* Loop until we have reached a terminator record (MSB=0, offset=0) */
|
||||
bnez a3, apply_relocs_loop
|
||||
|
||||
apply_relocs_done:
|
||||
/* Return to caller */
|
||||
ret
|
||||
.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
|
||||
@@ -187,12 +201,6 @@ reloc_base:
|
||||
.globl enable_paging
|
||||
.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
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
#define SBI_SRST_SYSTEM_RESET 0x00
|
||||
#define SBI_RESET_COLD 0x00000001
|
||||
|
||||
/* ELF machine type */
|
||||
#define EM_RISCV 243
|
||||
|
||||
/*
|
||||
* Display progress message via debug console
|
||||
*/
|
||||
@@ -127,5 +130,12 @@ _sbi_start:
|
||||
.section ".zinfo", "a", @progbits
|
||||
.ascii "COPY"
|
||||
.word 0
|
||||
.word _sbi_filesz
|
||||
.word _filesz
|
||||
.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) */
|
||||
.rela.dyn {
|
||||
_reloc = .;
|
||||
*(.rela)
|
||||
*(.rela.dyn)
|
||||
}
|
||||
@@ -88,25 +87,15 @@ SECTIONS {
|
||||
}
|
||||
}
|
||||
|
||||
/* Absolute link-time address of _reloc
|
||||
*
|
||||
* 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 );
|
||||
/* Base virtual address */
|
||||
_base = ABSOLUTE ( _prefix );
|
||||
|
||||
/* Calculate end of relocations
|
||||
*
|
||||
* This cannot be done by placing "_ereloc = .;" inside the
|
||||
* .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 );
|
||||
/* Relocations */
|
||||
_reloc_offset = ( LOADADDR ( .rela.dyn ) - LOADADDR ( .prefix ) );
|
||||
_reloc_filesz = SIZEOF ( .rela.dyn );
|
||||
|
||||
/* Length of initialised data */
|
||||
_sbi_filesz = ( ABSOLUTE ( _ereloc ) - ABSOLUTE ( _prefix ) );
|
||||
_filesz = ( ABSOLUTE ( _edata ) - ABSOLUTE ( _prefix ) );
|
||||
|
||||
/* Unwanted sections */
|
||||
/DISCARD/ : {
|
||||
|
||||
Reference in New Issue
Block a user