^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Code to process dynamic relocations for PPC32.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyrights (C) IBM Corporation, 2011.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Suzuki Poulose <suzuki@in.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - Based on ppc64 code - reloc_64.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/ppc_asm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* Dynamic section table entry tags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) DT_RELA = 7 /* Tag for Elf32_Rela section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) DT_RELASZ = 8 /* Size of the Rela relocs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) DT_RELAENT = 9 /* Size of one Rela reloc entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) STN_UNDEF = 0 /* Undefined symbol index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) STB_LOCAL = 0 /* Local binding for the symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) R_PPC_ADDR16_LO = 4 /* Lower half of (S+A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) R_PPC_ADDR16_HI = 5 /* Upper half of (S+A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) R_PPC_ADDR16_HA = 6 /* High Adjusted (S+A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) R_PPC_RELATIVE = 22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * r3 = desired final address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) _GLOBAL(relocate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) mflr r0 /* Save our LR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) bl 0f /* Find our current runtime address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 0: mflr r12 /* Make it accessible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) mtlr r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) lwz r11, (p_dyn - 0b)(r12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) add r11, r11, r12 /* runtime address of .dynamic section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) lwz r9, (p_rela - 0b)(r12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) add r9, r9, r12 /* runtime address of .rela.dyn section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) lwz r10, (p_st - 0b)(r12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) add r10, r10, r12 /* runtime address of _stext section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) lwz r13, (p_sym - 0b)(r12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) add r13, r13, r12 /* runtime address of .dynsym section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Scan the dynamic section for RELA, RELASZ entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) li r6, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) li r7, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) li r8, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 1: lwz r5, 0(r11) /* ELF_Dyn.d_tag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) cmpwi r5, 0 /* End of ELF_Dyn[] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) beq eodyn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) cmpwi r5, DT_RELA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) bne relasz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) lwz r7, 4(r11) /* r7 = rela.link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) b skip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) relasz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) cmpwi r5, DT_RELASZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) bne relaent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) lwz r8, 4(r11) /* r8 = Total Rela relocs size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) b skip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) relaent:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) cmpwi r5, DT_RELAENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bne skip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) lwz r6, 4(r11) /* r6 = Size of one Rela reloc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) addi r11, r11, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) b 1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) eodyn: /* End of Dyn Table scan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Check if we have found all the entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) cmpwi r7, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) beq done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) cmpwi r8, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) beq done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) cmpwi r6, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) beq done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Work out the current offset from the link time address of .rela
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * cur_offset[r7] = rela.run[r9] - rela.link [r7]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * _stext.link[r12] = _stext.run[r10] - cur_offset[r7]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * final_offset[r3] = _stext.final[r3] - _stext.link[r12]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) subf r7, r7, r9 /* cur_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) subf r12, r7, r10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) subf r3, r12, r3 /* final_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) subf r8, r6, r8 /* relaz -= relaent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Scan through the .rela table and process each entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * r9 - points to the current .rela table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * r13 - points to the symbol table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Check if we have a relocation based on symbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * r5 will hold the value of the symbol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) applyrela:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) lwz r4, 4(r9) /* r4 = rela.r_info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) srwi r5, r4, 8 /* ELF32_R_SYM(r_info) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) cmpwi r5, STN_UNDEF /* sym == STN_UNDEF ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) beq get_type /* value = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Find the value of the symbol at index(r5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) slwi r5, r5, 4 /* r5 = r5 * sizeof(Elf32_Sym) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) add r12, r13, r5 /* r12 = &__dyn_sym[Index] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * GNU ld has a bug, where dynamic relocs based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * STB_LOCAL symbols, the value should be assumed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * to be zero. - Alan Modra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* XXX: Do we need to check if we are using GNU ld ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) lbz r5, 12(r12) /* r5 = dyn_sym[Index].st_info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) extrwi r5, r5, 4, 24 /* r5 = ELF32_ST_BIND(r5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) cmpwi r5, STB_LOCAL /* st_value = 0, ld bug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) beq get_type /* We have r5 = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) lwz r5, 4(r12) /* r5 = __dyn_sym[Index].st_value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) get_type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Load the relocation type to r4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) extrwi r4, r4, 8, 24 /* r4 = ELF32_R_TYPE(r_info) = ((char*)r4)[3] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* R_PPC_RELATIVE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cmpwi r4, R_PPC_RELATIVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) bne hi16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) lwz r4, 0(r9) /* r_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) lwz r0, 8(r9) /* r_addend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) add r0, r0, r3 /* final addend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) stwx r0, r4, r7 /* memory[r4+r7]) = (u32)r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) b nxtrela /* continue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* R_PPC_ADDR16_HI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) hi16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) cmpwi r4, R_PPC_ADDR16_HI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) bne ha16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) lwz r4, 0(r9) /* r_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) lwz r0, 8(r9) /* r_addend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) add r0, r0, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) add r0, r0, r5 /* r0 = (S+A+Offset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) extrwi r0, r0, 16, 0 /* r0 = (r0 >> 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) b store_half
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* R_PPC_ADDR16_HA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ha16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) cmpwi r4, R_PPC_ADDR16_HA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) bne lo16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) lwz r4, 0(r9) /* r_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) lwz r0, 8(r9) /* r_addend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) add r0, r0, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) add r0, r0, r5 /* r0 = (S+A+Offset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) extrwi r5, r0, 1, 16 /* Extract bit 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) extrwi r0, r0, 16, 0 /* r0 = (r0 >> 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) add r0, r0, r5 /* Add it to r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) b store_half
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* R_PPC_ADDR16_LO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) lo16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) cmpwi r4, R_PPC_ADDR16_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) bne unknown_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) lwz r4, 0(r9) /* r_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) lwz r0, 8(r9) /* r_addend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) add r0, r0, r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) add r0, r0, r5 /* r0 = (S+A+Offset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) extrwi r0, r0, 16, 16 /* r0 &= 0xffff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Fall through to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Store half word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) store_half:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) sthx r0, r4, r7 /* memory[r4+r7] = (u16)r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) nxtrela:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * We have to flush the modified instructions to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * main storage from the d-cache. And also, invalidate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * cached instructions in i-cache which has been modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * We delay the sync / isync operation till the end, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * we won't be executing the modified instructions until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * we return from here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dcbst r4,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sync /* Ensure the data is flushed before icbi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) icbi r4,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unknown_type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) cmpwi r8, 0 /* relasz = 0 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ble done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) add r9, r9, r6 /* move to next entry in the .rela table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) subf r8, r6, r8 /* relasz -= relaent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) b applyrela
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) sync /* Wait for the flush to finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) isync /* Discard prefetched instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) blr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) p_dyn: .long __dynamic_start - 0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) p_rela: .long __rela_dyn_start - 0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) p_sym: .long __dynamic_symtab - 0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) p_st: .long _stext - 0b