3 @@ -1547,6 +1547,7 @@ typedef struct
4 #define STO_MIPS_INTERNAL 0x1
5 #define STO_MIPS_HIDDEN 0x2
6 #define STO_MIPS_PROTECTED 0x3
7 +#define STO_MIPS_PLT 0x8
8 #define STO_MIPS_SC_ALIGN_UNUSED 0xff
10 /* MIPS specific values for `st_info'. */
11 @@ -1692,8 +1693,11 @@ typedef struct
12 #define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
13 #define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
14 #define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
15 +#define R_MIPS_GLOB_DAT 51
16 +#define R_MIPS_COPY 126
17 +#define R_MIPS_JUMP_SLOT 127
18 /* Keep this the last entry. */
19 -#define R_MIPS_NUM 51
20 +#define R_MIPS_NUM 128
22 /* Legal values for p_type field of Elf32_Phdr. */
24 @@ -1759,7 +1763,13 @@ typedef struct
25 #define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
26 #define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
27 #define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
28 -#define DT_MIPS_NUM 0x32
29 +/* The address of .got.plt in an executable using the new non-PIC ABI. */
30 +#define DT_MIPS_PLTGOT 0x70000032
31 +/* The base of the PLT in an executable using the new non-PIC ABI if that
32 + PLT is writable. For a non-writable PLT, this is omitted or has a zero
34 +#define DT_MIPS_RWPLT 0x70000034
35 +#define DT_MIPS_NUM 0x35
37 /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
39 --- a/ldso/ldso/dl-hash.c
40 +++ b/ldso/ldso/dl-hash.c
41 @@ -160,6 +160,11 @@ check_match (const ElfW(Sym) *sym, char
42 /* undefined symbol itself */
46 + if (sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT))
50 if (sym->st_value == 0)
53 --- a/ldso/ldso/mips/dl-sysdep.h
54 +++ b/ldso/ldso/mips/dl-sysdep.h
55 @@ -93,10 +93,11 @@ typedef struct
61 #define DT_MIPS_GOTSYM_IDX (DT_NUM + OS_NUM)
62 #define DT_MIPS_LOCAL_GOTNO_IDX (DT_NUM + OS_NUM +1)
63 #define DT_MIPS_SYMTABNO_IDX (DT_NUM + OS_NUM +2)
64 +#define DT_MIPS_PLTGOT_IDX (DT_NUM + OS_NUM +3)
66 #define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
68 @@ -106,6 +107,8 @@ else if (dpnt->d_tag == DT_MIPS_LOCAL_GO
69 dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \
70 else if (dpnt->d_tag == DT_MIPS_SYMTABNO) \
71 dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \
72 +else if (dpnt->d_tag == DT_MIPS_PLTGOT) \
73 + dynamic[DT_MIPS_PLTGOT_IDX] = dpnt->d_un.d_val; \
74 else if (dpnt->d_tag == DT_MIPS_RLD_MAP) \
75 *(ElfW(Addr) *)(dpnt->d_un.d_ptr) = (ElfW(Addr)) debug_addr; \
77 @@ -114,6 +117,7 @@ else if (dpnt->d_tag == DT_MIPS_RLD_MAP)
78 #define INIT_GOT(GOT_BASE,MODULE) \
81 + unsigned long *pltgot; \
83 /* Check if this is the dynamic linker itself */ \
84 if (MODULE->libtype == program_interpreter) \
85 @@ -123,6 +127,12 @@ do { \
86 GOT_BASE[0] = (unsigned long) _dl_runtime_resolve; \
87 GOT_BASE[1] = (unsigned long) MODULE; \
89 + pltgot = MODULE->dynamic_info[DT_MIPS_PLTGOT_IDX]; \
91 + pltgot[0] = (unsigned long) _dl_runtime_pltresolve; \
92 + pltgot[1] = (unsigned long) MODULE; \
95 /* Add load address displacement to all local GOT entries */ \
97 while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
98 @@ -157,9 +167,9 @@ void _dl_perform_mips_global_got_relocat
99 #define OFFS_ALIGN 0x7ffff000
100 #endif /* O32 || N32 */
102 -#define elf_machine_type_class(type) ELF_RTYPE_CLASS_PLT
103 -/* MIPS does not have COPY relocs */
104 -#define DL_NO_COPY_RELOCS
105 +#define elf_machine_type_class(type) \
106 + ((((type) == R_MIPS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
107 + | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY))
109 #define OFFSET_GP_GOT 0x7ff0
111 --- a/ldso/ldso/mips/elfinterp.c
112 +++ b/ldso/ldso/mips/elfinterp.c
116 extern int _dl_runtime_resolve(void);
117 +extern int _dl_runtime_pltresolve(void);
119 #define OFFSET_GP_GOT 0x7ff0
121 @@ -83,6 +84,61 @@ unsigned long __dl_runtime_resolve(unsig
126 +__dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry)
129 + ELF_RELOC *this_reloc;
136 + unsigned long instr_addr;
139 + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
140 + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
141 + reloc_type = ELF32_R_TYPE(this_reloc->r_info);
142 + symtab_index = ELF32_R_SYM(this_reloc->r_info);
144 + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
145 + strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
146 + symname = strtab + symtab[symtab_index].st_name;
148 + /* Address of the jump instruction to fix up. */
149 + instr_addr = ((unsigned long)this_reloc->r_offset +
150 + (unsigned long)tpnt->loadaddr);
151 + got_addr = (char **)instr_addr;
153 + /* Get the address of the GOT entry. */
154 + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
155 + if (unlikely(!new_addr)) {
156 + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
160 +#if defined (__SUPPORT_LD_DEBUG__)
161 + if ((unsigned long)got_addr < 0x40000000) {
162 + if (_dl_debug_bindings) {
163 + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
164 + if (_dl_debug_detail)
165 + _dl_dprintf(_dl_debug_file,
166 + "\n\tpatched: %x ==> %x @ %x",
167 + *got_addr, new_addr, got_addr);
170 + if (!_dl_debug_nofixups) {
171 + *got_addr = new_addr;
174 + *got_addr = new_addr;
177 + return (unsigned long)new_addr;
180 void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
181 unsigned long rel_addr, unsigned long rel_size)
183 @@ -115,6 +171,7 @@ int _dl_parse_relocation_information(str
184 got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
186 for (i = 0; i < rel_size; i++, rpnt++) {
187 + char *symname = NULL;
188 reloc_addr = (unsigned long *) (tpnt->loadaddr +
189 (unsigned long) rpnt->r_offset);
190 reloc_type = ELF_R_TYPE(rpnt->r_info);
191 @@ -128,6 +185,16 @@ int _dl_parse_relocation_information(str
192 old_val = *reloc_addr;
195 + if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
196 + symname = strtab + symtab[symtab_index].st_name;
197 + symbol_addr = (unsigned long)_dl_find_hash(symname,
198 + tpnt->symbol_scope,
200 + elf_machine_type_class(reloc_type));
201 + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
205 switch (reloc_type) {
206 #if _MIPS_SIM == _MIPS_SIM_ABI64
207 case (R_MIPS_64 << 8) | R_MIPS_REL32:
208 @@ -148,6 +215,24 @@ int _dl_parse_relocation_information(str
209 *reloc_addr += (unsigned long) tpnt->loadaddr;
212 + case R_MIPS_JUMP_SLOT:
213 + *reloc_addr = symbol_addr;
217 +#if defined (__SUPPORT_LD_DEBUG__)
218 + if (_dl_debug_move)
219 + _dl_dprintf(_dl_debug_file,
220 + "\n%s move %d bytes from %x to %x",
221 + symname, symtab[symtab_index].st_size,
222 + symbol_addr, reloc_addr);
225 + _dl_memcpy((char *)reloc_addr,
226 + (char *)symbol_addr,
227 + symtab[symtab_index].st_size);
233 --- a/ldso/ldso/mips/resolve.S
234 +++ b/ldso/ldso/mips/resolve.S
235 @@ -112,3 +112,54 @@ _dl_runtime_resolve:
236 .end _dl_runtime_resolve
239 +/* Assembler veneer called from the PLT header code when using the
242 + Code in each PLT entry puts the caller's return address into t7 ($15),
243 + the PLT entry index into t8 ($24), the address of _dl_runtime_pltresolve
244 + into t9 ($25) and the address of .got.plt into gp ($28). __dl_runtime_pltresolve
245 + needs a0 ($4) to hold the link map and a1 ($5) to hold the index into
246 + .rel.plt (== PLT entry index * 4). */
250 + .globl _dl_runtime_pltresolve
251 + .type _dl_runtime_pltresolve,@function
252 + .ent _dl_runtime_pltresolve
253 +_dl_runtime_pltresolve:
254 + .frame $29, 40, $31
256 + # Save arguments and sp value in stack.
259 + # Modify t9 ($25) so as to point .cpload instruction.
265 + /* Store function arguments from registers to stack */
272 + /* Setup functions args and call __dl_runtime_pltresolve. */
275 + jal __dl_runtime_pltresolve
277 + /* Restore function arguments from stack to registers */
284 + /* Do a tail call to the original function */
288 + .end _dl_runtime_pltresolve