]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/uclibc/uclibc-0.9.27/thumb-interwork-asm.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / uclibc / uclibc-0.9.27 / thumb-interwork-asm.patch
1 --- uClibc-0.9.27/ldso/include/dl-elf.h 2005-01-11 23:59:21.000000000 -0800
2 +++ uClibc-0.9.27/ldso/include/dl-elf.h 2005-08-12 18:24:43.000000000 -0700
3 @@ -112,6 +112,13 @@
4  # define ELF_RTYPE_CLASS_COPY  (0x2)
5  #endif
6  #define ELF_RTYPE_CLASS_PLT    (0x1)
7 +/* The type class can be qualified by a list (mask) of the acceptable
8 + * STT_ symbol types, if not given the default is everything numerically
9 + * <= STT_FUNC (from the original code...)
10 + */
11 +#define ELF_RTYPE_CLASS_OF(type) ((1<<2) << (type))
12 +#define ELF_RTYPE_CLASS_ALL      (0xffff << 2)
13 +#define ELF_RTYPE_CLASS_DEFAULT  (((ELF_RTYPE_CLASS_OF(STT_FUNC) << 1) - 1)&ELF_RTYPE_CLASS_ALL)
14  
15  
16  /* Convert between the Linux flags for page protections and the
17 --- uClibc-0.9.27/ldso/ldso/arm/resolve.S       2005-01-11 23:59:21.000000000 -0800
18 +++ uClibc-0.9.27/ldso/ldso/arm/resolve.S       2005-08-13 15:08:27.523344709 -0700
19 @@ -1,43 +1,117 @@
20  /*
21 - * This function is _not_ called directly.  It is jumped to (so no return
22 - * address is on the stack) when attempting to use a symbol that has not yet
23 - * been resolved.  The first time a jump symbol (such as a function call inside
24 - * a shared library) is used (before it gets resolved) it will jump here to
25 - * _dl_linux_resolve.  When we get called the stack looks like this:
26 - *     reloc_entry
27 - *     tpnt
28 - *
29 - * This function saves all the registers, puts a copy of reloc_entry and tpnt
30 - * on the stack (as function arguments) then make the function call
31 - * _dl_linux_resolver(tpnt, reloc_entry).  _dl_linux_resolver() figures out
32 - * where the jump symbol is _really_ supposed to have jumped to and returns
33 - * that to us.  Once we have that, we overwrite tpnt with this fixed up
34 - * address. We then clean up after ourselves, put all the registers back how we
35 - * found them, then we jump to the fixed up address, which is where the jump
36 - * symbol that got us here really wanted to jump to in the first place.
37 - *  -Erik Andersen
38 + * On ARM the PLT contains the following three instructions (for ARM calls):
39 + *
40 + *     add   ip, pc, #0xNN00000
41 + *     add   ip, ip, #0xNN000
42 + *     ldr   pc, [ip, #0xNNN]!
43 + *
44 + * So that, effectively, causes the following to happen:
45 + *
46 + *     ip := pc+0x0NNNNNNN
47 + *     pc := *ip
48 + *
49 + * For thumb the above fragment is preceded by "bx pc, nop" to switch to ARM
50 + * mode and the thumb 'bl' must go to PLT-4 - the PLT entry is expanded by
51 + * four bytes to accomodate the trampoline code.
52 + *
53 + * 0x0NNNNNNN is the offset of the GOT entry for this function relative to
54 + * the PLT entry for this function (where the code is).  So the code in the
55 + * PLT causes a branch to whatever is in the GOT, leaving the actual address
56 + * of the GOT entry in ip.  (Note that the GOT must follow the PLT - the
57 + * added value is 28 bit unsigned).
58 + *
59 + * ip is a pointer to the GOT entry for this function, the first time round
60 + * *ip points to this code:
61 + *
62 + *     str   lr, [sp, #-4]!    @ save lr
63 + *     ldr   lr, [pc, #4]      @ lr := *dat (&GOT_TABLE[0]-.)
64 + *     add   lr, pc, lr        @ lr += &dat (so lr == &GOT_TABLE[0])
65 + *     ldr   pc, [lr, #8]!     @ pc := GOT_TABLE[2]
66 + *dat: .long &GOT_TABLE[0] - .
67 + *
68 + * (this code is actually held in the first entry of the PLT).  The code
69 + * preserves lr then uses it as a scratch register (this preserves the ip
70 + * value calculated above).  GOT_TABLE[2] is initialized by INIT_GOT in
71 + * dl-sysdep.h to point to _dl_linux_resolve - this function.  The first
72 + * three entries in the GOT are reserved, then they are followed by the
73 + * entries for the PLT entries, in order.
74 + *
75 + * The linker initialises the following (non-reserved) GOT entries to
76 + * the offset of the PLT with an associated relocation so that on load
77 + * the entry is relocated to point to the PLT - the above code.
78 + *
79 + * The net effect of all this is that on the first call to an external (as
80 + * yet unresolved) function all seven of the above instructions are
81 + * executed in sequence and the program ends up executing _dl_linux_resolve
82 + * with the following important values in registers:
83 + *
84 + *     ip - a pointer to the GOT entry for the as yet unresolved function
85 + *     lr - &GOT_TABLE[2]
86 + *
87 + * GOT_TABLE[2] has already been initialised to _dl_linux_resolve, and
88 + * GOT_TABLE[1] is a pointer to the (elf_resolve*) from INIT_GOT.
89 + * _dl_linux_resolve unfrobnicates the ip and lr values to obtain arguments
90 + * for a call to _dl_linux_resolver (not the additional 'r' on the end) -
91 + * this is in elfinterp.c in this directory.  The call takes arguments:
92 + *
93 + *     _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
94 + *
95 + * And returns the address of the function, it also overwrites the GOT
96 + * table entry so that the next time round only the first code fragment will
97 + * be executed - it will call the function directly.
98 + *
99 + * [[Of course, this simply doesn't work on ARM 4T with a thumb target - because
100 + * 4T did not do the thumb/arm change on ldr pc!  It can be made to work by
101 + * changing _dl_linux_resolver to return __%s_from_arm for an STT_TFUNC, but
102 + * this hasn't been done, and there is no guarantee that the linker generated
103 + * that glue anyway.]]
104 + *
105 + * _dl_linux_resolve gets the arguments to call the resolver as follows:
106 + *
107 + *     tpnt            GOT_TABLE[1], [lr-4]
108 + *     reloc-entry     &GOT-&GOT_TABLE[3], (ip - lr - 4)/4
109 + *
110 + * (I.e. 'GOT' means the table entry for this function, the thing for which
111 + * ip holds the address.)  The reloc-entry is passed as an index, since
112 + * since the GOT table has 4 byte entries the code needs to divide this by 4
113 + * to get the actual index.
114 + *
115 + * John Bowler, August 13, 2005 - determined by experiment and examination
116 + * of generated ARM code (there was no documentation...)
117 + *
118 + * This code is all ARM code - not thumb - _dl_linux_resolver may, itself,
119 + * be thumb, in which case the linker will insert the appropriate glue.  A
120 + * call from thumb to the PLT hits the trampoline code described above.
121 + * This code (now) builds a proper stack frame.
122 + *
123 + * The code does *not* set sb (r9,v6) - to do that the basic PLT instructions
124 + * would need to save sb and load the new value and that would require
125 + * support in the linker since it generates those instructions.  (Also note
126 + * that linux/uclibc seems to be using r10 - sl - as a PIC base register - see
127 + * dl-startup.c).
128   */
129  
130 -#define sl r10
131 -#define fp r11
132 -#define ip r12
133 -
134  .text
135  .globl _dl_linux_resolve
136  .type _dl_linux_resolve,%function
137  .align 4;
138  
139  _dl_linux_resolve:
140 -       stmdb sp!, {r0, r1, r2, r3, sl, fp}
141 -       sub r1, ip, lr
142 -       sub r1, r1, #4
143 -       add r1, r1, r1
144 -       ldr r0, [lr, #-4]
145 -       mov r3,r0
146 +       @ _dl_linux_resolver is a standard subroutine call, therefore it
147 +       @ preserves everything except r0-r3 (a1-a4), ip and lr.  This
148 +       @ function must branch to the real function, and that expects
149 +       @ r0-r3 and lr to be as they were before the whole PLT stuff -
150 +       @ ip can be trashed.
151 +       stmdb sp!, {r0-r3}
152 +       ldr r0, [lr, #-4]       @ r0 := [lr-4] (GOT_TABLE[1])
153 +       sub r1, lr, ip          @ r1 := (lr-ip) (a multple of 4)
154 +       mvn r1, r1, ASR #2      @ r1 := ~((lr-ip)>>2), since -x = (1+~x)
155 +                               @ ~x = -x-1, therefore ~(r1>>2) = (-((lr-ip)>>2)-1)
156 +                               @ = - ((lr-ip)/4) - 1 = (ip - lr - 4)/4, as required
157  
158         bl _dl_linux_resolver
159  
160 -       mov ip, r0
161 -       ldmia sp!, {r0, r1, r2, r3, sl, fp, lr}
162 -       mov pc,ip
163 +       mov   ip, r0
164 +       ldmia sp!, {r0-r3, lr}
165 +       bx    ip
166  .size _dl_linux_resolve, .-_dl_linux_resolve
167 --- uClibc-0.9.27/ldso/ldso/arm/elfinterp.c     2005-01-11 23:59:21.000000000 -0800
168 +++ uClibc-0.9.27/ldso/ldso/arm/elfinterp.c     2005-08-13 16:08:19.061345947 -0700
169 @@ -128,7 +128,7 @@
170  
171         rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
172  
173 -       this_reloc = rel_addr + (reloc_entry >> 3);
174 +       this_reloc = rel_addr + reloc_entry;
175         reloc_type = ELF32_R_TYPE(this_reloc->r_info);
176         symtab_index = ELF32_R_SYM(this_reloc->r_info);
177  
178 @@ -149,13 +149,20 @@
179         got_addr = (char **) instr_addr;
180  
181         /* Get the address of the GOT entry */
182 -       new_addr = _dl_find_hash(symname, tpnt->symbol_scope,
183 -                                tpnt, ELF_RTYPE_CLASS_PLT);
184 -       if (unlikely(!new_addr)) {
185 -               _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
186 -                       _dl_progname, symname);
187 -               _dl_exit(1);
188 -       };
189 +       new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt,
190 +               ELF_RTYPE_CLASS_PLT+ELF_RTYPE_CLASS_OF(STT_FUNC));
191 +       if (!new_addr) {
192 +               new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt,
193 +                       ELF_RTYPE_CLASS_PLT+ELF_RTYPE_CLASS_OF(STT_ARM_TFUNC));
194 +               if (new_addr) {
195 +                       /* Fix up the address for thumb. */
196 +                       new_addr = (char*)((unsigned long)new_addr | 1);
197 +               } else {
198 +                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
199 +                               _dl_progname, symname);
200 +                       _dl_exit(1);
201 +               }
202 +       }
203  #if defined (__SUPPORT_LD_DEBUG__)
204         if ((unsigned long) got_addr < 0x40000000)
205         {
206 @@ -278,7 +285,8 @@
207         if (symtab_index) {
208  
209                 symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
210 -                               scope, tpnt, elf_machine_type_class(reloc_type));
211 +                               scope, tpnt, elf_machine_type_class(reloc_type) +
212 +                               ELF_RTYPE_CLASS_DEFAULT + ELF_RTYPE_CLASS_OF(STT_ARM_TFUNC));
213  
214                 /*
215                  * We want to allow undefined references to weak symbols - this might
216 --- uClibc-0.9.27/ldso/ldso/dl-hash.c   2005-01-11 23:59:21.000000000 -0800
217 +++ uClibc-0.9.27/ldso/ldso/dl-hash.c   2005-08-12 18:28:05.000000000 -0700
218 @@ -148,7 +148,11 @@
219         char *weak_result = NULL;
220  
221         elf_hash_number = _dl_elf_hash(name);
222 -          
223 +       /* The type class argument may specify the valid symbol types, if not
224 +        * any type <= STT_FUNC is permitted.
225 +        */
226 +       if ((type_class & ELF_RTYPE_CLASS_ALL) == 0)
227 +               type_class += ELF_RTYPE_CLASS_DEFAULT;
228         for (; rpnt; rpnt = rpnt->next) {
229                 tpnt = rpnt->dyn;
230  
231 @@ -178,13 +182,16 @@
232                 for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
233                         sym = &symtab[si];
234  
235 +                       /*... nb, ELF_RTYPE_CLASS_PLT is, must be, "1" - at least
236 +                        * it must be for the following to work.
237 +                        */
238                         if (type_class & (sym->st_shndx == SHN_UNDEF))
239                                 continue;
240 -                       if (_dl_strcmp(strtab + sym->st_name, name) != 0)
241 -                               continue;
242                         if (sym->st_value == 0)
243                                 continue;
244 -                       if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
245 +                       if ((ELF_RTYPE_CLASS_OF(ELF32_ST_TYPE(sym->st_info)) & type_class) == 0)
246 +                               continue;
247 +                       if (_dl_strcmp(strtab + sym->st_name, name) != 0)
248                                 continue;
249  
250                         switch (ELF32_ST_BIND(sym->st_info)) {
251 --- uClibc-0.9.27/libc/sysdeps/linux/arm/clone.S        2005-01-11 23:59:21.000000000 -0800
252 +++ uClibc-0.9.27/libc/sysdeps/linux/arm/clone.S        2005-08-13 11:56:47.275679748 -0700
253 @@ -49,12 +49,13 @@
254         swi     __NR_clone
255         movs    a1, a1
256         blt     __syscall_error  (PLT)
257 -       movne    pc, lr
258 +       bxne    lr
259  
260         @ pick the function arg and call address off the stack and execute
261         ldr     r0, [sp, #4]
262 +       ldr     ip, [sp]
263         mov     lr, pc
264 -       ldr     pc, [sp]
265 +       bx      ip
266  
267         @ and we are done, passing the return value through r0
268         b       _exit   (PLT)
269 @@ -70,7 +71,7 @@
270  
271         /* return -1 */
272         mvn  r0, $0
273 -       mov  pc, lr
274 +       bx   lr
275  .size __clone,.-__clone;
276  
277  .L4:  .word errno
278 --- uClibc-0.9.27/libc/sysdeps/linux/arm/mmap64.S       2005-01-11 23:59:21.000000000 -0800
279 +++ uClibc-0.9.27/libc/sysdeps/linux/arm/mmap64.S       2005-08-13 12:20:35.633560643 -0700
280 @@ -44,7 +44,7 @@
281         mov     ip, r0
282         swi     __NR_mmap2
283         cmn     r0, $4096
284 -       ldmccfd sp!, {r4, r5, pc}
285 +       ldmccfd sp!, {r4, r5, pc}       @ requires >=5T
286         cmn     r0, $ENOSYS
287         ldmnefd sp!, {r4, r5, lr}
288         bne     __syscall_error (PLT)
289 @@ -71,7 +71,7 @@
290  
291         /* return -1 */
292         mvn  r0, $0
293 -       mov  pc, lr
294 +       bx   lr
295  .size mmap64,.-mmap64;
296  
297  .L4:  .word errno
298 --- uClibc-0.9.27/libc/sysdeps/linux/arm/vfork.S        2005-01-11 23:59:21.000000000 -0800
299 +++ uClibc-0.9.27/libc/sysdeps/linux/arm/vfork.S        2005-08-13 12:23:27.500375540 -0700
300 @@ -37,7 +37,7 @@
301  #ifdef __NR_vfork
302                 swi             __NR_vfork
303                 cmn             r0, #4096
304 -               movcc   pc, lr
305 +               bxcc    lr
306  
307                 /* Check if vfork even exists.  */
308                 ldr     r1, =-ENOSYS
309 @@ -50,7 +50,7 @@
310                 cmn     r0, #4096
311  
312                 /* Syscal worked.  Return to child/parent */
313 -               movcc   pc, lr
314 +               bxcc    lr
315  
316  __syscall_error:
317  
318 @@ -64,7 +64,7 @@
319  
320                 /* return -1 */
321                 mvn  r0, $0
322 -               mov  pc, lr
323 +               bx   lr
324  
325  .L4:  .word errno
326