nptl-supoprt should not autoselect EXTRA_WARNINGS as this results in extra CFLAGS...
[openwrt.git] / toolchain / uClibc / patches-0.9.30.1 / 440-backport_mips_nonpic.patch
1 --- a/include/elf.h
2 +++ b/include/elf.h
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
9  
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
21  
22  /* Legal values for p_type field of Elf32_Phdr.  */
23  
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
33 +   value.  */
34 +#define DT_MIPS_RWPLT        0x70000034
35 +#define DT_MIPS_NUM         0x35
36  
37  /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
38  
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 */
43                 return NULL;
44  
45 +#ifdef __mips__
46 +    if (sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT))
47 +        return NULL;
48 +#endif
49 +
50         if (sym->st_value == 0)
51                 /* No value */
52                 return NULL;
53 --- a/ldso/ldso/mips/dl-sysdep.h
54 +++ b/ldso/ldso/mips/dl-sysdep.h
55 @@ -93,10 +93,11 @@ typedef struct
56  
57  #include <link.h>
58  
59 -#define ARCH_NUM 3
60 +#define ARCH_NUM 4
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)
65  
66  #define ARCH_DYNAMIC_INFO(dpnt,  dynamic, debug_addr) \
67  do { \
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; \
76  } while (0)
77 @@ -114,6 +117,7 @@ else if (dpnt->d_tag == DT_MIPS_RLD_MAP)
78  #define INIT_GOT(GOT_BASE,MODULE)                                              \
79  do {                                                                           \
80         unsigned long idx;                                                      \
81 +       unsigned long *pltgot;                                                  \
82                                                                                 \
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;                                   \
88                                                                                 \
89 +       pltgot = MODULE->dynamic_info[DT_MIPS_PLTGOT_IDX];                      \
90 +       if (pltgot) {                                                           \
91 +               pltgot[0] = (unsigned long) _dl_runtime_pltresolve;             \
92 +               pltgot[1] = (unsigned long) MODULE;                             \
93 +       }                                                                       \
94 +                                                                               \
95         /* Add load address displacement to all local GOT entries */            \
96         idx = 2;                                                                        \
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 */
101  
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))
108  
109  #define OFFSET_GP_GOT 0x7ff0
110  
111 --- a/ldso/ldso/mips/elfinterp.c
112 +++ b/ldso/ldso/mips/elfinterp.c
113 @@ -30,6 +30,7 @@
114  #include "ldso.h"
115  
116  extern int _dl_runtime_resolve(void);
117 +extern int _dl_runtime_pltresolve(void);
118  
119  #define OFFSET_GP_GOT 0x7ff0
120  
121 @@ -83,6 +84,61 @@ unsigned long __dl_runtime_resolve(unsig
122         return new_addr;
123  }
124  
125 +unsigned long
126 +__dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry)
127 +{
128 +       int reloc_type;
129 +       ELF_RELOC *this_reloc;
130 +       char *strtab;
131 +       Elf32_Sym *symtab;
132 +       int symtab_index;
133 +       char *rel_addr;
134 +       char *new_addr;
135 +       char **got_addr;
136 +       unsigned long instr_addr;
137 +       char *symname;
138 +
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);
143 +
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;
147 +
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;
152 +
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);
157 +               _dl_exit(1);
158 +       }
159 +
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);
168 +               }
169 +       }
170 +       if (!_dl_debug_nofixups) {
171 +               *got_addr = new_addr;
172 +       }
173 +#else
174 +       *got_addr = new_addr;
175 +#endif
176 +
177 +       return (unsigned long)new_addr;
178 +}
179 +
180  void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
181         unsigned long rel_addr, unsigned long rel_size)
182  {
183 @@ -115,6 +171,7 @@ int _dl_parse_relocation_information(str
184         got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
185  
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;
193  #endif
194  
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,
199 +                                                                  tpnt,
200 +                                                                  elf_machine_type_class(reloc_type));
201 +                       if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
202 +                               return 1;
203 +               }
204 +
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;
210                         }
211                         break;
212 +               case R_MIPS_JUMP_SLOT:
213 +                       *reloc_addr = symbol_addr;
214 +                       break;
215 +               case R_MIPS_COPY:
216 +                       if (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);
223 +#endif
224 +
225 +                               _dl_memcpy((char *)reloc_addr,
226 +                                          (char *)symbol_addr,
227 +                                          symtab[symtab_index].st_size);
228 +                       }
229 +                       break;
230                 case R_MIPS_NONE:
231                         break;
232                 default:
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
237  .previous
238  
239 +/* Assembler veneer called from the PLT header code when using the
240 +   non-PIC ABI.
241 +
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).  */
247 +
248 +       .text
249 +       .align  2
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
255 +       .set noreorder
256 +       # Save arguments and sp value in stack.
257 +       subu    $29, 40
258 +       lw      $10, 4($28)
259 +       # Modify t9 ($25) so as to point .cpload instruction.
260 +       addiu   $25, 12
261 +       # Compute GP.
262 +       .cpload $25
263 +       .set reorder
264 +
265 +       /* Store function arguments from registers to stack */
266 +       sw      $15, 36($29)
267 +       sw      $4, 16($29)
268 +       sw      $5, 20($29)
269 +       sw      $6, 24($29)
270 +       sw      $7, 28($29)
271 +
272 +       /* Setup functions args and call __dl_runtime_pltresolve.  */
273 +       move    $4, $10
274 +       sll     $5, $24, 3
275 +       jal     __dl_runtime_pltresolve
276 +
277 +       /* Restore function arguments from stack to registers */
278 +       lw      $31, 36($29)
279 +       lw      $4, 16($29)
280 +       lw      $5, 20($29)
281 +       lw      $6, 24($29)
282 +       lw      $7, 28($29)
283 +
284 +       /* Do a tail call to the original function */
285 +       addiu   $29, 40
286 +       move    $25, $2
287 +       jr      $25
288 +       .end    _dl_runtime_pltresolve
289 +       .previous