OSDN Git Service

Add new debug target (disabled by default) so that when debug
[uclinux-h8/uClibc.git] / ldso / ldso / m68k / elfinterp.c
1 /* Run an ELF binary on a linux system.
2
3    Copyright (C) 1993, Eric Youngdale.
4    Copyright (C) 1995, Andreas Schwab.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19 \f
20 /* Adapted to ELF/68k by Andreas Schwab.  */
21
22 #ifndef VERBOSE_DLINKER
23 #define VERBOSE_DLINKER
24 #endif
25 #ifdef VERBOSE_DLINKER
26 static char *_dl_reltypes[] =
27 {
28   "R_68K_NONE",
29   "R_68K_32", "R_68K_16", "R_68K_8",
30   "R_68K_PC32", "R_68K_PC16", "R_68K_PC8",
31   "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8",
32   "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O",
33   "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8",
34   "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O",
35   "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE",
36   "R_68K_NUM"
37 };
38 #endif
39
40 /* Program to load an ELF binary on a linux system, and run it.
41    References to symbols in sharable libraries can be resolved by either
42    an ELF sharable library or a linux style of shared library. */
43
44 /* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
45    I ever taken any courses on internals.  This program was developed using
46    information available through the book "UNIX SYSTEM V RELEASE 4,
47    Programmers guide: Ansi C and Programming Support Tools", which did
48    a more than adequate job of explaining everything required to get this
49    working. */
50
51
52 unsigned int _dl_linux_resolver (int dummy1, int dummy2, 
53         struct elf_resolve *tpnt, int reloc_entry)
54 {
55   int reloc_type;
56   Elf32_Rela *this_reloc;
57   char *strtab;
58   Elf32_Sym *symtab;
59   char *rel_addr;
60   int symtab_index;
61   char *new_addr;
62   char **got_addr;
63   unsigned int instr_addr;
64
65   rel_addr = tpnt->loadaddr + tpnt->dynamic_info[DT_JMPREL];
66   this_reloc = (Elf32_Rela *) (rel_addr + reloc_entry);
67   reloc_type = ELF32_R_TYPE (this_reloc->r_info);
68   symtab_index = ELF32_R_SYM (this_reloc->r_info);
69
70   symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
71                                  + tpnt->loadaddr);
72   strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
73
74
75   if (reloc_type != R_68K_JMP_SLOT)
76     {
77       _dl_dprintf (2, "%s: incorrect relocation type in jump relocations\n",
78                     _dl_progname);
79       _dl_exit (1);
80     }
81
82   /* Address of jump instruction to fix up.  */
83   instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
84   got_addr = (char **) instr_addr;
85
86 #ifdef DL_DEBUG_SYMBOLS
87   _dl_dprintf (2, "Resolving symbol %s\n",
88                 strtab + symtab[symtab_index].st_name);
89 #endif
90
91   /* Get the address of the GOT entry.  */
92   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
93                             tpnt->symbol_scope, (int) got_addr, tpnt, 0);
94   if (!new_addr)
95     {
96       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
97                     _dl_progname, strtab + symtab[symtab_index].st_name);
98       _dl_exit (1);
99     }
100 #ifdef DL_NEVER_FIXUP_SYMBOLS
101   if ((unsigned int) got_addr < 0x40000000) {
102       _dl_dprintf (2, "Calling library function: %s\n",
103               strtab + symtab[symtab_index].st_name);
104   } else {
105       *got_addr = new_addr;
106   }
107 #else
108   *got_addr = new_addr;
109 #endif
110   return (unsigned int) new_addr;
111 }
112
113 void
114 _dl_parse_lazy_relocation_information (struct elf_resolve *tpnt,
115                        unsigned long rel_addr, unsigned long rel_size, int type)
116 {
117   int i;
118   char *strtab;
119   int reloc_type;
120   int symtab_index;
121   Elf32_Sym *symtab;
122   Elf32_Rela *rpnt;
123   unsigned int *reloc_addr;
124
125   /* Now parse the relocation information.  */
126   rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
127   rel_size = rel_size / sizeof (Elf32_Rela);
128
129   symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
130                                  + tpnt->loadaddr);
131   strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
132
133   for (i = 0; i < rel_size; i++, rpnt++)
134     {
135       reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
136       reloc_type = ELF32_R_TYPE (rpnt->r_info);
137       symtab_index = ELF32_R_SYM (rpnt->r_info);
138
139       /* When the dynamic linker bootstrapped itself, it resolved some symbols.
140          Make sure we do not do them again.  */
141       if (tpnt->libtype == program_interpreter
142           && (!symtab_index
143               || _dl_symbol (strtab + symtab[symtab_index].st_name)))
144         continue;
145
146       switch (reloc_type)
147         {
148         case R_68K_NONE:
149           break;
150         case R_68K_JMP_SLOT:
151           *reloc_addr += (unsigned int) tpnt->loadaddr;
152           break;
153         default:
154           _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
155 #ifdef VERBOSE_DLINKER
156           _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
157 #endif
158           if (symtab_index)
159             _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
160           _dl_dprintf (2, "\n");
161           _dl_exit (1);
162         }
163     }
164 }
165
166 int 
167 _dl_parse_relocation_information (struct elf_resolve *tpnt,
168                   unsigned long rel_addr, unsigned long rel_size, int type)
169 {
170   int i;
171   char *strtab;
172   int reloc_type;
173   int goof = 0;
174   Elf32_Sym *symtab;
175   Elf32_Rela *rpnt;
176   unsigned int *reloc_addr;
177   unsigned int symbol_addr;
178   int symtab_index;
179   /* Now parse the relocation information */
180
181   rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
182   rel_size = rel_size / sizeof (Elf32_Rela);
183
184   symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
185                                  + tpnt->loadaddr);
186   strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
187
188   for (i = 0; i < rel_size; i++, rpnt++)
189     {
190       reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
191       reloc_type = ELF32_R_TYPE (rpnt->r_info);
192       symtab_index = ELF32_R_SYM (rpnt->r_info);
193       symbol_addr = 0;
194
195       if (tpnt->libtype == program_interpreter
196           && (!symtab_index
197               || _dl_symbol (strtab + symtab[symtab_index].st_name)))
198         continue;
199
200       if (symtab_index)
201         {
202           symbol_addr = (unsigned int)
203             _dl_find_hash (strtab + symtab[symtab_index].st_name,
204                            tpnt->symbol_scope, (int) reloc_addr,
205                            reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
206
207           /* We want to allow undefined references to weak symbols -
208              this might have been intentional.  We should not be
209              linking local symbols here, so all bases should be
210              covered.  */
211           if (!symbol_addr
212               && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
213             {
214               _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
215                             _dl_progname, strtab + symtab[symtab_index].st_name);
216               goof++;
217             }
218         }
219       switch (reloc_type)
220         {
221         case R_68K_NONE:
222           break;
223         case R_68K_8:
224           *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
225           break;
226         case R_68K_16:
227           *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
228           break;
229         case R_68K_32:
230           *reloc_addr = symbol_addr + rpnt->r_addend;
231           break;
232         case R_68K_PC8:
233           *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
234                                   - (unsigned int) reloc_addr);
235           break;
236         case R_68K_PC16:
237           *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
238                                    - (unsigned int) reloc_addr);
239           break;
240         case R_68K_PC32:
241           *reloc_addr = (symbol_addr + rpnt->r_addend
242                          - (unsigned int) reloc_addr);
243           break;
244         case R_68K_GLOB_DAT:
245         case R_68K_JMP_SLOT:
246           *reloc_addr = symbol_addr;
247           break;
248         case R_68K_RELATIVE:
249           *reloc_addr = ((unsigned int) tpnt->loadaddr
250                          /* Compatibility kludge.  */
251                          + (rpnt->r_addend ? : *reloc_addr));
252           break;
253         case R_68K_COPY:
254 #if 0 /* Do this later.  */
255           _dl_dprintf (2, "Doing copy");
256           if (symtab_index)
257             _dl_dprintf (2, " for symbol %s",
258                           strtab + symtab[symtab_index].st_name);
259           _dl_dprintf (2, "\n");
260           _dl_memcpy ((void *) symtab[symtab_index].st_value,
261                       (void *) symbol_addr,
262                       symtab[symtab_index].st_size);
263 #endif
264           break;
265         default:
266           _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
267 #ifdef VERBOSE_DLINKER
268           _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
269 #endif
270           if (symtab_index)
271             _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
272           _dl_dprintf (2, "\n");
273           _dl_exit (1);
274         }
275
276     }
277   return goof;
278 }
279
280 /* This is done as a separate step, because there are cases where
281    information is first copied and later initialized.  This results in
282    the wrong information being copied.  Someone at Sun was complaining about
283    a bug in the handling of _COPY by SVr4, and this may in fact be what he
284    was talking about.  Sigh.  */
285
286 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
287    at all.  */
288
289 int 
290 _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
291                             unsigned long rel_size, int type)
292 {
293   int i;
294   char *strtab;
295   int reloc_type;
296   int goof = 0;
297   Elf32_Sym *symtab;
298   Elf32_Rela *rpnt;
299   unsigned int *reloc_addr;
300   unsigned int symbol_addr;
301   struct elf_resolve *tpnt;
302   int symtab_index;
303   /* Now parse the relocation information */
304
305   tpnt = xpnt->dyn;
306
307   rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
308   rel_size = rel_size / sizeof (Elf32_Rela);
309
310   symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
311                                  + tpnt->loadaddr);
312   strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
313
314   for (i = 0; i < rel_size; i++, rpnt++)
315     {
316       reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
317       reloc_type = ELF32_R_TYPE (rpnt->r_info);
318       if (reloc_type != R_68K_COPY)
319         continue;
320       symtab_index = ELF32_R_SYM (rpnt->r_info);
321       symbol_addr = 0;
322       if (tpnt->libtype == program_interpreter
323           && (!symtab_index
324               || _dl_symbol (strtab + symtab[symtab_index].st_name)))
325         continue;
326       if (symtab_index)
327         {
328           symbol_addr = (unsigned int)
329             _dl_find_hash (strtab + symtab[symtab_index].st_name,
330                            xpnt->next, (int) reloc_addr, NULL, 1);
331           if (!symbol_addr)
332             {
333               _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
334                             _dl_progname, strtab + symtab[symtab_index].st_name);
335               goof++;
336             }
337         }
338       if (!goof)
339       _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
340                   symtab[symtab_index].st_size);
341     }
342   return goof;
343 }