Reloc fixes for PowerPC PE
[external/binutils.git] / bfd / coff-ppc.c
1 /* BFD back-end for PowerPC Microsoft Portable Executable files.
2    Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3
4    Original version pieced together by Kim Knuttila (krk@cygnus.com)
5
6    There is nothing new under the sun. This file draws a lot on other
7    coff files, in particular, those for the rs/6000, alpha, mips, and 
8    intel backends, and the PE work for the arm.
9
10 This file is part of BFD, the Binary File Descriptor library.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
25
26 /* Current State:
27    - objdump works
28    - relocs generated by gas
29    - ld will link files, but they do not run.
30    - dlltool will not produce correct output in some .reloc cases, and will 
31      not produce the right glue code for dll function calls.
32 */
33
34
35 #include "bfd.h"
36 #include "sysdep.h"
37 #include "libbfd.h"
38 #include "obstack.h"
39
40 #include "coff/powerpc.h"
41 #include "coff/internal.h"
42
43 #include "coff/pe.h"
44
45 #ifdef BADMAG
46 #undef BADMAG
47 #endif
48
49 #define BADMAG(x) PPCBADMAG(x)
50
51 #include "libcoff.h"
52
53 /* In order not to add an int to every hash table item for every coff
54    linker, we define our own hash table, derived from the coff one */
55
56 /* PE linker hash table entries. */
57
58 struct ppc_coff_link_hash_entry
59 {
60   struct coff_link_hash_entry root; /* First entry, as required  */
61
62   /* As we wonder around the relocs, we'll keep the assigned toc_offset
63      here */
64   bfd_vma toc_offset;               /* Our addition, as required */
65   int symbol_is_glue;
66   unsigned long int glue_insn;
67   char eye_catcher[8];
68 };
69
70 /* Need a 7 char string for an eye catcher */
71 #define EYE "krkjunk"
72
73 #define CHECK_EYE(addr) \
74  if (strcmp(addr, EYE) != 0) \
75   { \
76     fprintf(stderr,\
77     "File %s, line %d, Hash check failure, bad eye %8s\n", \
78     __FILE__, __LINE__, addr); \
79     abort(); \
80  }
81
82 /* PE linker hash table.  */
83
84 struct ppc_coff_link_hash_table
85 {
86   struct coff_link_hash_table root; /* First entry, as required */
87 };
88
89 static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
90   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
91            const char *));
92
93 /* Routine to create an entry in the link hash table.  */
94
95 static struct bfd_hash_entry *
96 ppc_coff_link_hash_newfunc (entry, table, string)
97      struct bfd_hash_entry *entry;
98      struct bfd_hash_table *table;
99      const char *string;
100 {
101   struct ppc_coff_link_hash_entry *ret = 
102     (struct ppc_coff_link_hash_entry *) entry;
103
104   /* Allocate the structure if it has not already been allocated by a
105      subclass.  */
106   if (ret == (struct ppc_coff_link_hash_entry *) NULL)
107     ret = (struct ppc_coff_link_hash_entry *)
108       bfd_hash_allocate (table, 
109                          sizeof (struct ppc_coff_link_hash_entry));
110
111   if (ret == (struct ppc_coff_link_hash_entry *) NULL)
112     return NULL;
113
114   /* Call the allocation method of the superclass.  */
115   ret = ((struct ppc_coff_link_hash_entry *)
116          _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret, 
117                                       table, string));
118
119   if (ret)
120     {
121       /* Initialize the local fields.  */
122       ret->toc_offset = 1;
123       ret->symbol_is_glue = 0;
124       ret->glue_insn = 0;
125       strcpy(ret->eye_catcher, EYE);
126     }
127
128   return (struct bfd_hash_entry *) ret;
129 }
130
131 /* Initialize a PE linker hash table.  */
132
133 static boolean
134 ppc_coff_link_hash_table_init (table, abfd, newfunc)
135      struct ppc_coff_link_hash_table *table;
136      bfd *abfd;
137      struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
138                                                 struct bfd_hash_table *,
139                                                 const char *));
140 {
141   return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
142 }
143
144 /* Create a PE linker hash table.  */
145
146 static struct bfd_link_hash_table *
147 ppc_coff_link_hash_table_create (abfd)
148      bfd *abfd;
149 {
150   struct ppc_coff_link_hash_table *ret;
151
152   ret = ((struct ppc_coff_link_hash_table *)
153          bfd_alloc (abfd, sizeof (struct ppc_coff_link_hash_table)));
154   if (ret == NULL)
155     {
156       bfd_set_error (bfd_error_no_memory);
157       return NULL;
158     }
159   if (! ppc_coff_link_hash_table_init (ret, abfd,
160                                         ppc_coff_link_hash_newfunc))
161     {
162       bfd_release (abfd, ret);
163       return (struct bfd_link_hash_table *) NULL;
164     }
165   return &ret->root.root;
166 }
167
168 /* Now, tailor coffcode.h to use our hash stuff */
169
170 #define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
171
172 \f
173 /* The nt loader points the toc register to &toc + 32768, in order to */
174 /* use the complete range of a 16-bit displacement (I guess). We have */
175 /* to adjust for this when we fix up loads displaced off the toc reg. */
176 #define TOC_LOAD_ADJUSTMENT (-32768)
177 #define TOC_SECTION_NAME ".private.toc"
178
179 /* The main body of code is in coffcode.h.  */
180
181 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
182
183 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
184    from smaller values.  Start with zero, widen, *then* decrement.  */
185 #define MINUS_ONE       (((bfd_vma)0) - 1)
186
187 /* these should definitely go in a header file somewhere... */
188
189 /* NOP */
190 #define IMAGE_REL_PPC_ABSOLUTE          0x0000
191
192 /* 64-bit address */
193 #define IMAGE_REL_PPC_ADDR64            0x0001
194
195 /* 32-bit address */
196 #define IMAGE_REL_PPC_ADDR32            0x0002
197
198 /* 26-bit address, shifted left 2 (branch absolute) */
199 #define IMAGE_REL_PPC_ADDR24            0x0003
200
201 /* 16-bit address */
202 #define IMAGE_REL_PPC_ADDR16            0x0004
203
204 /* 16-bit address, shifted left 2 (load doubleword) */
205 #define IMAGE_REL_PPC_ADDR14            0x0005
206
207 /* 26-bit PC-relative offset, shifted left 2 (branch relative) */
208 #define IMAGE_REL_PPC_REL24             0x0006
209
210 /* 16-bit PC-relative offset, shifted left 2 (br cond relative) */
211 #define IMAGE_REL_PPC_REL14             0x0007
212
213 /* 16-bit offset from TOC base */
214 #define IMAGE_REL_PPC_TOCREL16          0x0008
215
216 /* 16-bit offset from TOC base, shifted left 2 (load doubleword) */
217 #define IMAGE_REL_PPC_TOCREL14          0x0009
218
219 /* 32-bit addr w/o image base */
220 #define IMAGE_REL_PPC_ADDR32NB          0x000A
221
222 /* va of containing section (as in an image sectionhdr) */
223 #define IMAGE_REL_PPC_SECREL            0x000B
224
225 /* sectionheader number */
226 #define IMAGE_REL_PPC_SECTION           0x000C
227
228 /* substitute TOC restore instruction iff symbol is glue code */
229 #define IMAGE_REL_PPC_IFGLUE            0x000D
230
231 /* symbol is glue code; virtual address is TOC restore instruction */
232 #define IMAGE_REL_PPC_IMGLUE            0x000E
233
234 /* va of containing section (limited to 16 bits) */
235 #define IMAGE_REL_PPC_SECREL16          0x000F
236
237 /* stuff to handle immediate data when the number of bits in the */
238 /* data is greater than the number of bits in the immediate field */
239 /* We need to do (usually) 32 bit arithmetic on 16 bit chunks */
240 #define IMAGE_REL_PPC_REFHI             0x0010
241 #define IMAGE_REL_PPC_REFLO             0x0011
242 #define IMAGE_REL_PPC_PAIR              0x0012
243
244
245 /*  Flag bits in IMAGE_RELOCATION.TYPE */
246
247 /* subtract reloc value rather than adding it */
248 #define IMAGE_REL_PPC_NEG               0x0100
249
250 /* fix branch prediction bit to predict branch taken */
251 #define IMAGE_REL_PPC_BRTAKEN           0x0200
252
253 /* fix branch prediction bit to predict branch not taken */
254 #define IMAGE_REL_PPC_BRNTAKEN          0x0400
255
256 /* toc slot defined in file (or, data in toc) */
257 #define IMAGE_REL_PPC_TOCDEFN           0x0800
258
259 /* masks to isolate above values in IMAGE_RELOCATION.Type */
260 #define IMAGE_REL_PPC_TYPEMASK          0x00FF
261 #define IMAGE_REL_PPC_FLAGMASK          0x0F00
262
263 #define EXTRACT_TYPE(x)                 ((x) & IMAGE_REL_PPC_TYPEMASK)
264 #define EXTRACT_FLAGS(x) ((x) & IMAGE_REL_PPC_FLAGMASK)
265 #define EXTRACT_JUNK(x)  \
266            ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK))
267
268 \f
269 /* static helper functions to make relocation work */
270 /* (Work In Progress) */
271
272 static bfd_reloc_status_type ppc_refhi_reloc PARAMS ((bfd *abfd,
273                                                       arelent *reloc,
274                                                       asymbol *symbol,
275                                                       PTR data,
276                                                       asection *section,
277                                                       bfd *output_bfd,
278                                                       char **error));
279 static bfd_reloc_status_type ppc_reflo_reloc PARAMS ((bfd *abfd,
280                                                       arelent *reloc,
281                                                       asymbol *symbol,
282                                                       PTR data,
283                                                       asection *section,
284                                                       bfd *output_bfd,
285                                                       char **error));
286 static bfd_reloc_status_type ppc_pair_reloc PARAMS ((bfd *abfd,
287                                                      arelent *reloc,
288                                                      asymbol *symbol,
289                                                      PTR data,
290                                                      asection *section,
291                                                      bfd *output_bfd,
292                                                      char **error));
293
294 \f
295 static bfd_reloc_status_type ppc_toc16_reloc PARAMS ((bfd *abfd,
296                                                       arelent *reloc,
297                                                       asymbol *symbol,
298                                                       PTR data,
299                                                       asection *section,
300                                                       bfd *output_bfd,
301                                                       char **error));
302
303 static bfd_reloc_status_type ppc_addr32nb_reloc PARAMS ((bfd *abfd,
304                                                          arelent *reloc,
305                                                          asymbol *symbol,
306                                                          PTR data,
307                                                          asection *section,
308                                                          bfd *output_bfd,
309                                                          char **error));
310
311 static bfd_reloc_status_type ppc_section_reloc PARAMS ((bfd *abfd,
312                                                         arelent *reloc,
313                                                         asymbol *symbol,
314                                                         PTR data,
315                                                         asection *section,
316                                                         bfd *output_bfd,
317                                                         char **error));
318
319 static bfd_reloc_status_type ppc_secrel_reloc PARAMS ((bfd *abfd,
320                                                        arelent *reloc,
321                                                        asymbol *symbol,
322                                                        PTR data,
323                                                        asection *section,
324                                                        bfd *output_bfd,
325                                                        char **error));
326
327 static bfd_reloc_status_type ppc_imglue_reloc PARAMS ((bfd *abfd,
328                                                        arelent *reloc,
329                                                        asymbol *symbol,
330                                                        PTR data,
331                                                        asection *section,
332                                                        bfd *output_bfd,
333                                                        char **error));
334
335
336
337 static boolean in_reloc_p PARAMS((bfd *abfd, reloc_howto_type *howto));
338
339 \f
340 /* FIXME: It'll take a while to get through all of these. I only need a few to
341    get us started, so those I'll make sure work. Those marked FIXME are either
342    completely unverified or have a specific unknown marked in the comment */
343
344 /*---------------------------------------------------------------------------*/
345 /*                                                                           */
346 /* Relocation entries for Windows/NT on PowerPC.                             */
347 /*                                                                           */
348 /* From the document "" we find the following listed as used relocs:         */
349 /*                                                                           */
350 /*   ABSOLUTE       : The noop                                               */
351 /*   ADDR[64|32|16] : fields that hold addresses in data fields or the       */
352 /*                    16 bit displacement field on a load/store.             */
353 /*   ADDR[24|14]    : fields that hold addresses in branch and cond          */
354 /*                    branches. These represent [26|16] bit addresses.       */
355 /*                    The low order 2 bits are preserved.                    */
356 /*   REL[24|14]     : branches relative to the Instruction Address           */
357 /*                    register. These represent [26|16] bit addresses,       */
358 /*                    as before. The instruction field will be zero, and     */
359 /*                    the address of the SYM will be inserted at link time.  */
360 /*   TOCREL16       : 16 bit displacement field referring to a slot in       */
361 /*                    toc.                                                   */
362 /*   TOCREL14       : 16 bit displacement field, similar to REL14 or ADDR14. */
363 /*   ADDR32NB       : 32 bit address relative to the virtual origin.         */
364 /*                    (On the alpha, this is always a linker generated thunk)*/
365 /*                    (i.e. 32bit addr relative to the image base)           */
366 /*   SECREL         : The value is relative to the start of the section      */
367 /*                    containing the symbol.                                 */
368 /*   SECTION        : access to the header containing the item. Supports the */
369 /*                    codeview debugger.                                     */
370 /*                                                                           */
371 /* In particular, note that the document does not indicate that the          */
372 /* relocations listed in the header file are used.                           */
373 /*                                                                           */
374 /*                                                                           */
375 /*                                                                           */
376 /*---------------------------------------------------------------------------*/
377
378 static reloc_howto_type ppc_coff_howto_table[] =
379 {
380   /* IMAGE_REL_PPC_ABSOLUTE 0x0000   NOP */
381   /* Unused: */
382   HOWTO (IMAGE_REL_PPC_ABSOLUTE, /* type */                                 
383          0,                      /* rightshift */                           
384          0,                      /* size (0 = byte, 1 = short, 2 = long) */ 
385          0,                      /* bitsize */                   
386          false,                  /* pc_relative */                          
387          0,                      /* bitpos */                               
388          complain_overflow_dont, /* dont complain_on_overflow */
389          0,                      /* special_function */                     
390          "ABSOLUTE",             /* name */
391          false,                  /* partial_inplace */                      
392          0x00,                   /* src_mask */                             
393          0x00,                   /* dst_mask */                             
394          false),                 /* pcrel_offset */
395   
396   /* IMAGE_REL_PPC_ADDR64 0x0001  64-bit address */
397   /* Unused: */
398   HOWTO(IMAGE_REL_PPC_ADDR64,    /* type */                                 
399         0,                       /* rightshift */                           
400         3,                       /* size (0 = byte, 1 = short, 2 = long) */ 
401         64,                      /* bitsize */                   
402         false,                   /* pc_relative */                          
403         0,                       /* bitpos */                               
404         complain_overflow_bitfield,      /* complain_on_overflow */
405         0,                       /* special_function */                     
406         "ADDR64",               /* name */
407         true,                    /* partial_inplace */                      
408         MINUS_ONE,               /* src_mask */
409         MINUS_ONE,               /* dst_mask */
410         false),                 /* pcrel_offset */
411
412   /* IMAGE_REL_PPC_ADDR32 0x0002  32-bit address */
413   /* Used: */
414   HOWTO (IMAGE_REL_PPC_ADDR32,  /* type */
415          0,                     /* rightshift */                           
416          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
417          32,                    /* bitsize */                   
418          false,                 /* pc_relative */                          
419          0,                     /* bitpos */                               
420          complain_overflow_bitfield, /* complain_on_overflow */
421          0,                     /* special_function */                     
422          "ADDR32",              /* name */
423          true,                  /* partial_inplace */                      
424          0xffffffff,            /* src_mask */                             
425          0xffffffff,            /* dst_mask */                             
426          false),                /* pcrel_offset */
427   
428   /* IMAGE_REL_PPC_ADDR24 0x0003  26-bit address, shifted left 2 (branch absolute) */
429   /* the LI field is in bit 6 through bit 29 is 24 bits, + 2 for the shift */
430   /* Of course, That's the IBM approved bit numbering, which is not what */
431   /* anyone else uses.... The li field is in bit 2 thru 25 */ 
432   /* Used: */
433   HOWTO (IMAGE_REL_PPC_ADDR24,  /* type */
434          0,                     /* rightshift */                           
435          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
436          26,                    /* bitsize */
437          false,                 /* pc_relative */                          
438          0,                     /* bitpos */                               
439          complain_overflow_bitfield, /* complain_on_overflow */
440          0,                     /* special_function */                     
441          "ADDR24",              /* name */
442          true,                  /* partial_inplace */                      
443          0x07fffffc,            /* src_mask */                             
444          0x07fffffc,            /* dst_mask */                             
445          false),                /* pcrel_offset */
446   
447   /* IMAGE_REL_PPC_ADDR16 0x0004  16-bit address */
448   /* Used: */
449   HOWTO (IMAGE_REL_PPC_ADDR16,  /* type */             
450          0,                     /* rightshift */                           
451          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
452          16,                    /* bitsize */                   
453          false,                 /* pc_relative */                          
454          0,                     /* bitpos */                               
455          complain_overflow_signed, /* complain_on_overflow */
456          0,                     /* special_function */                     
457          "ADDR16",              /* name */
458          true,                  /* partial_inplace */                      
459          0xffff,                /* src_mask */                             
460          0xffff,                /* dst_mask */                             
461          false),                /* pcrel_offset */
462   
463   /* IMAGE_REL_PPC_ADDR14 0x0005 */
464   /*  16-bit address, shifted left 2 (load doubleword) */
465   /* FIXME: the mask is likely wrong, and the bit position may be as well */
466   /* Unused: */
467   HOWTO (IMAGE_REL_PPC_ADDR14,  /* type */             
468          1,                     /* rightshift */                           
469          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
470          16,                    /* bitsize */                   
471          false,                 /* pc_relative */                          
472          0,                     /* bitpos */                               
473          complain_overflow_signed, /* complain_on_overflow */
474          0,                     /* special_function */                     
475          "ADDR16",              /* name */
476          true,                  /* partial_inplace */                      
477          0xffff,                /* src_mask */                             
478          0xffff,                /* dst_mask */                             
479          false),                /* pcrel_offset */
480   
481   /* IMAGE_REL_PPC_REL24 0x0006 */
482   /*   26-bit PC-relative offset, shifted left 2 (branch relative) */
483   /* Used: */
484   HOWTO (IMAGE_REL_PPC_REL24,   /* type */
485          0,                     /* rightshift */                           
486          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
487          26,                    /* bitsize */                   
488          true,                  /* pc_relative */                          
489          0,                     /* bitpos */                               
490          complain_overflow_signed, /* complain_on_overflow */
491          0,                     /* special_function */                     
492          "REL24",               /* name */
493          true,                  /* partial_inplace */                      
494          0x3fffffc,             /* src_mask */                             
495          0x3fffffc,             /* dst_mask */                             
496          false),                /* pcrel_offset */
497   
498   /* IMAGE_REL_PPC_REL14 0x0007 */
499   /*   16-bit PC-relative offset, shifted left 2 (br cond relative) */
500   /* FIXME: the mask is likely wrong, and the bit position may be as well */
501   /* FIXME: how does it know how far to shift? */
502   /* Unused: */
503   HOWTO (IMAGE_REL_PPC_ADDR14,  /* type */             
504          1,                     /* rightshift */                           
505          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
506          16,                    /* bitsize */                   
507          false,                 /* pc_relative */                          
508          0,                     /* bitpos */                               
509          complain_overflow_signed, /* complain_on_overflow */
510          0,                     /* special_function */                     
511          "ADDR16",              /* name */
512          true,                  /* partial_inplace */                      
513          0xffff,                /* src_mask */                             
514          0xffff,                /* dst_mask */                             
515          true),                 /* pcrel_offset */
516   
517   /* IMAGE_REL_PPC_TOCREL16 0x0008 */
518   /*   16-bit offset from TOC base */
519   /* Used: */
520   HOWTO (IMAGE_REL_PPC_TOCREL16,/* type */             
521          0,                     /* rightshift */                           
522          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
523          16,                    /* bitsize */                   
524          false,                 /* pc_relative */                          
525          0,                     /* bitpos */                               
526          complain_overflow_dont, /* complain_on_overflow */
527          ppc_toc16_reloc,       /* special_function */                     
528          "TOCREL16",            /* name */
529          false,                 /* partial_inplace */                      
530          0xffff,                /* src_mask */                             
531          0xffff,                /* dst_mask */                             
532          false),                /* pcrel_offset */
533   
534   /* IMAGE_REL_PPC_TOCREL14 0x0009 */
535   /*   16-bit offset from TOC base, shifted left 2 (load doubleword) */
536   /* Unused: */
537   HOWTO (IMAGE_REL_PPC_TOCREL14,/* type */             
538          1,                     /* rightshift */                           
539          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
540          16,                    /* bitsize */                   
541          false,                 /* pc_relative */                          
542          0,                     /* bitpos */                               
543          complain_overflow_signed, /* complain_on_overflow */
544          0,                     /* special_function */                     
545          "TOCREL14",            /* name */
546          false,                 /* partial_inplace */                      
547          0xffff,                /* src_mask */                             
548          0xffff,                /* dst_mask */                             
549          false),                /* pcrel_offset */
550   
551   /* IMAGE_REL_PPC_ADDR32NB 0x000A */
552   /*   32-bit addr w/ image base */
553   /* Unused: */
554   HOWTO (IMAGE_REL_PPC_ADDR32NB,/* type */             
555          0,                     /* rightshift */                           
556          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
557          32,                    /* bitsize */                   
558          false,                 /* pc_relative */                          
559          0,                     /* bitpos */                               
560          complain_overflow_signed, /* complain_on_overflow */
561          0,                     /* special_function */                     
562          "ADDR32NB",            /* name */
563          true,                  /* partial_inplace */                      
564          0xffffffff,            /* src_mask */                             
565          0xffffffff,            /* dst_mask */                             
566          false),                 /* pcrel_offset */
567   
568   /* IMAGE_REL_PPC_SECREL 0x000B */
569   /*   va of containing section (as in an image sectionhdr) */
570   /* Unused: */
571   HOWTO (IMAGE_REL_PPC_SECREL,/* type */             
572          0,                     /* rightshift */                           
573          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
574          32,                    /* bitsize */                   
575          false,                 /* pc_relative */                          
576          0,                     /* bitpos */                               
577          complain_overflow_signed, /* complain_on_overflow */
578          ppc_secrel_reloc,      /* special_function */                     
579          "SECREL",              /* name */
580          true,                  /* partial_inplace */                      
581          0xffffffff,            /* src_mask */                             
582          0xffffffff,            /* dst_mask */                             
583          true),                 /* pcrel_offset */
584
585   /* IMAGE_REL_PPC_SECTION 0x000C */
586   /*   sectionheader number */
587   /* Unused: */
588   HOWTO (IMAGE_REL_PPC_SECTION,/* type */             
589          0,                     /* rightshift */                           
590          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
591          32,                    /* bitsize */                   
592          false,                 /* pc_relative */                          
593          0,                     /* bitpos */                               
594          complain_overflow_signed, /* complain_on_overflow */
595          ppc_section_reloc,     /* special_function */                     
596          "SECTION",             /* name */
597          true,                  /* partial_inplace */                      
598          0xffffffff,            /* src_mask */                             
599          0xffffffff,            /* dst_mask */                             
600          true),                 /* pcrel_offset */
601
602   /* IMAGE_REL_PPC_IFGLUE 0x000D */
603   /*   substitute TOC restore instruction iff symbol is glue code */
604   /* Used: */
605   HOWTO (IMAGE_REL_PPC_IFGLUE,/* type */             
606          0,                     /* rightshift */                           
607          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
608          32,                    /* bitsize */                   
609          false,                 /* pc_relative */                          
610          0,                     /* bitpos */                               
611          complain_overflow_signed, /* complain_on_overflow */
612          0,                     /* special_function */                     
613          "IFGLUE",              /* name */
614          true,                  /* partial_inplace */                      
615          0xffffffff,            /* src_mask */                             
616          0xffffffff,            /* dst_mask */                             
617          false),                /* pcrel_offset */
618
619   /* IMAGE_REL_PPC_IMGLUE 0x000E */
620   /*   symbol is glue code; virtual address is TOC restore instruction */
621   /* Unused: */
622   HOWTO (IMAGE_REL_PPC_IMGLUE,/* type */             
623          0,                     /* rightshift */                           
624          2,                     /* size (0 = byte, 1 = short, 2 = long) */ 
625          32,                    /* bitsize */                   
626          false,                 /* pc_relative */                          
627          0,                     /* bitpos */                               
628          complain_overflow_dont, /* complain_on_overflow */
629          ppc_imglue_reloc,      /* special_function */                     
630          "IMGLUE",              /* name */
631          false,                 /* partial_inplace */                      
632          0xffffffff,            /* src_mask */                             
633          0xffffffff,            /* dst_mask */                             
634          false),                 /* pcrel_offset */
635
636   /* IMAGE_REL_PPC_SECREL16 0x000F */
637   /*   va of containing section (limited to 16 bits) */
638   /* Unused: */
639   HOWTO (IMAGE_REL_PPC_SECREL16,/* type */             
640          0,                     /* rightshift */                           
641          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
642          16,                    /* bitsize */                   
643          false,                 /* pc_relative */                          
644          0,                     /* bitpos */                               
645          complain_overflow_signed, /* complain_on_overflow */
646          0,                     /* special_function */                     
647          "SECREL16",            /* name */
648          true,                  /* partial_inplace */                      
649          0xffff,                /* src_mask */                             
650          0xffff,                /* dst_mask */                             
651          true),                 /* pcrel_offset */
652
653   /* IMAGE_REL_PPC_REFHI             0x0010 */
654   /* Unused: */
655   HOWTO (IMAGE_REL_PPC_REFHI,   /* type */             
656          0,                     /* rightshift */                           
657          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
658          16,                    /* bitsize */                   
659          false,                 /* pc_relative */                          
660          0,                     /* bitpos */                               
661          complain_overflow_signed, /* complain_on_overflow */
662          ppc_refhi_reloc,       /* special_function */                     
663          "REFHI",               /* name */
664          true,                  /* partial_inplace */                      
665          0xffffffff,            /* src_mask */                             
666          0xffffffff,            /* dst_mask */                             
667          false),                 /* pcrel_offset */
668
669   /* IMAGE_REL_PPC_REFLO             0x0011 */
670   /* Unused: */
671   HOWTO (IMAGE_REL_PPC_REFLO,   /* type */             
672          0,                     /* rightshift */                           
673          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
674          16,                    /* bitsize */                   
675          false,                 /* pc_relative */                          
676          0,                     /* bitpos */                               
677          complain_overflow_signed, /* complain_on_overflow */
678          ppc_refhi_reloc,       /* special_function */                     
679          "REFLO",               /* name */
680          true,                  /* partial_inplace */                      
681          0xffffffff,            /* src_mask */                             
682          0xffffffff,            /* dst_mask */                             
683          false),                /* pcrel_offset */
684
685   /* IMAGE_REL_PPC_PAIR              0x0012 */
686   /* Unused: */
687   HOWTO (IMAGE_REL_PPC_PAIR,    /* type */             
688          0,                     /* rightshift */                           
689          1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
690          16,                    /* bitsize */                   
691          false,                 /* pc_relative */                          
692          0,                     /* bitpos */                               
693          complain_overflow_signed, /* complain_on_overflow */
694          ppc_pair_reloc,        /* special_function */                     
695          "PAIR",                /* name */
696          true,                  /* partial_inplace */                      
697          0xffffffff,            /* src_mask */                             
698          0xffffffff,            /* dst_mask */                             
699          false)                 /* pcrel_offset */
700 };
701
702
703 \f
704
705 /* Some really cheezy macros that can be turned on to test stderr :-) */
706
707 #ifdef DEBUG_RELOC
708 #define UN_IMPL(x)                                           \
709 {                                                            \
710    static int i;                                             \
711    if (i == 0)                                               \
712      {                                                       \
713        i = 1;                                                \
714        fprintf(stderr,"Unimplemented Relocation -- %s\n",x); \
715      }                                                       \
716 }
717
718 #define DUMP_RELOC(n,r)                              \
719 {                                                    \
720    fprintf(stderr,"%s sym %d, addr %d, addend %d\n", \
721            n, (*(r->sym_ptr_ptr))->name,             \
722            r->address, r->addend);                   \
723 }
724
725 /* Given a reloc name, n, and a pointer to an internal_reloc, 
726    dump out interesting information on the contents 
727
728 #define n_name          _n._n_name
729 #define n_zeroes        _n._n_n._n_zeroes
730 #define n_offset        _n._n_n._n_offset
731
732 */
733
734 #define DUMP_RELOC2(n,r)                     \
735 {                                            \
736    fprintf(stderr,"%s sym %d, r_vaddr %d %s\n", \
737            n, r->r_symndx, r->r_vaddr,\
738            (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \
739            ?" ":" TOCDEFN"  );      \
740 }
741
742 #else
743 #define UN_IMPL(x)
744 #define DUMP_RELOC(n,r)
745 #define DUMP_RELOC2(n,r)
746 #endif
747
748
749 \f
750 /* toc construction and management routines */
751 extern bfd* bfd_of_toc_owner;
752 extern long int global_toc_size;
753
754 extern long int import_table_size;
755 extern long int first_thunk_address;
756 extern long int thunk_size;
757
758 enum toc_type
759 {
760   default_toc,
761   toc_32,
762   toc_64
763 };
764
765 struct list_ele
766 {
767   struct list_ele *next;
768   bfd_vma addr;
769   int offset;
770   const char *name;
771 };
772
773 extern struct list_ele *head;
774 extern struct list_ele *tail;
775
776 static void
777 record_toc(toc_section, our_toc_offset, name)
778      asection *toc_section;
779      int our_toc_offset;
780      const char *name;
781 {
782   /* add this entry to our toc addr-offset-name list */
783   struct list_ele *t;
784   t = malloc(sizeof(struct list_ele));
785   t->next = 0;
786   t->offset = our_toc_offset;
787   t->name = name;
788   t->addr = toc_section->output_offset + our_toc_offset;
789
790   if (head == 0)
791     {
792       head = t;
793       tail = t;
794     }
795   else
796     {
797       tail->next = t;
798       tail = t;
799     }
800 }
801
802 /* record a toc offset against a symbol */
803 static int
804 ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
805      bfd *abfd;
806      struct bfd_link_info *info;
807      asection *sec;
808      int sym;
809      enum toc_type toc_kind;
810 {
811   bfd_byte *t;
812   bfd_byte *old_contents;
813   asection *s;
814   int element_size;
815   int data;
816   int offset;
817   struct ppc_coff_link_hash_entry *h;
818   struct coff_symbol_struct *target;
819   int ret_val;
820   const char *name;
821
822   int *local_syms;
823
824   h = 0;
825
826   h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
827   if (h != 0)
828     {
829       CHECK_EYE(h->eye_catcher);
830     }
831
832   if (h == 0) 
833     { 
834       local_syms = obj_coff_local_toc_table(abfd);
835       if (local_syms == 0)
836         {
837           int i;
838           /* allocate a table */
839           local_syms = 
840             (int *) bfd_zalloc (abfd, 
841                                 obj_raw_syment_count(abfd) * sizeof(int));
842           if (local_syms == 0)
843             {
844               bfd_set_error (bfd_error_no_memory);
845               return false;
846             }
847           obj_coff_local_toc_table(abfd) = local_syms;
848           for (i = 0; i < obj_raw_syment_count(abfd); ++i)
849             local_syms[i] = 1;
850         }
851
852       if (local_syms[sym] == 1) 
853         {
854           local_syms[sym] = global_toc_size;
855           ret_val = global_toc_size;
856           global_toc_size += 4;
857 #ifdef TOC_DEBUG
858           fprintf(stderr,
859                   "Setting toc_offset for local sym %d to %d\n",
860                   sym, ret_val);
861 #endif
862         }
863       else
864         {
865           ret_val = local_syms[sym];
866 #ifdef TOC_DEBUG
867           fprintf(stderr,
868                   "toc_offset already set for local sym %d to %d\n",
869                   sym, ret_val);
870 #endif
871         }
872     }
873   else
874     {
875       name = h->root.root.root.string;
876
877       /* check to see if there's a toc slot allocated. If not, do it
878          here. It will be used in relocate_section */
879       if (h->toc_offset == 1)
880         {
881           h->toc_offset = global_toc_size;
882           ret_val = global_toc_size;
883           global_toc_size += 4;
884 #ifdef TOC_DEBUG
885           fprintf(stderr,
886                   "Setting toc_offset for sym %d (%s) [h=%p] to %d\n",
887                   sym, name, h, ret_val);
888 #endif
889         }
890       else
891         {
892           ret_val = h->toc_offset;
893 #ifdef TOC_DEBUG
894           fprintf(stderr,
895                   "toc_offset already set for sym %d (%s) [h=%p] to %d\n",
896                   sym, name, h, ret_val);
897 #endif
898         }
899     }
900
901   return ret_val;
902 }
903 /* FIXME: record a toc offset against a data-in-toc symbol */
904 /* Now, there is currenly some confusion on what this means. In some 
905    compilers one sees the moral equivalent of:
906       .tocd
907       define some data
908       .text
909       refer to the data with a [tocv] qualifier
910    In general, one sees something to indicate that a tocd has been
911    seen, and that would trigger the allocation of data in toc. The IBM
912    docs seem to suggest that anything with the TOCDEFN qualifier should
913    never trigger storage allocation. However, in the kernel32.lib that 
914    we've been using for our test bed, there are a couple of variables
915    referenced that fail that test.
916
917    So it can't work that way.
918 */
919 static int
920 ppc_record_data_in_toc_entry(abfd, info, sec, sym, toc_kind)
921      bfd *abfd;
922      struct bfd_link_info *info;
923      asection *sec;
924      int sym;
925      enum toc_type toc_kind;
926 {
927   bfd_byte *t;
928   bfd_byte *old_contents;
929   asection *s;
930   int element_size;
931   int data;
932   int offset;
933   struct ppc_coff_link_hash_entry *h = 0;
934   struct coff_symbol_struct *target;
935   int ret_val;
936   const char *name;
937
938   int *local_syms;
939
940   h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
941
942   if (h == 0) 
943     { 
944       local_syms = obj_coff_local_toc_table(abfd);
945       if (local_syms == 0)
946         {
947           int i;
948           /* allocate a table */
949           local_syms = 
950             (int *) bfd_zalloc (abfd, 
951                                 obj_raw_syment_count(abfd) * sizeof(int));
952           if (local_syms == 0)
953             {
954               bfd_set_error (bfd_error_no_memory);
955               return false;
956             }
957           obj_coff_local_toc_table(abfd) = local_syms;
958           for (i = 0; i < obj_raw_syment_count(abfd); ++i)
959             local_syms[i] = 1;
960         }
961
962       if (local_syms[sym] == 1) 
963         {
964           local_syms[sym] = global_toc_size;
965           ret_val = global_toc_size;
966           global_toc_size += 4;
967 #ifdef TOC_DEBUG
968           fprintf(stderr,
969                   "Setting data_in_toc_offset for local sym %d to %d\n",
970                   sym, ret_val);
971 #endif
972         }
973       else
974         {
975           ret_val = local_syms[sym];
976 #ifdef TOC_DEBUG
977           fprintf(stderr,
978                   "data_in_toc_offset already set for local sym %d to %d\n",
979                   sym, ret_val);
980 #endif
981         }
982     }
983   else
984     {
985       CHECK_EYE(h->eye_catcher);
986
987       name = h->root.root.root.string;
988
989       /* check to see if there's a toc slot allocated. If not, do it
990          here. It will be used in relocate_section */
991       if (h->toc_offset == 1)
992         {
993 #if 0
994           h->toc_offset = global_toc_size;
995 #endif
996           ret_val = global_toc_size;
997           /* We're allocating a chunk of the toc, as opposed to a slot */
998           /* FIXME: alignment? */
999           
1000           global_toc_size += 4;
1001 #ifdef TOC_DEBUG
1002           fprintf(stderr,
1003                   "Setting data_in_toc_offset for sym %d (%s) [h=%p] to %d\n",
1004                   sym, name, h, ret_val);
1005 #endif
1006         }
1007       else
1008         {
1009           ret_val = h->toc_offset;
1010 #ifdef TOC_DEBUG
1011           fprintf(stderr,
1012                   "data_in_toc_offset already set for sym %d (%s) [h=%p] to %d\n",
1013                   sym, name, h, ret_val);
1014 #endif
1015         }
1016     }
1017
1018   return ret_val;
1019 }
1020
1021 /* record a toc offset against a symbol */
1022 static void
1023 ppc_mark_symbol_as_glue(abfd, sym, rel)
1024      bfd *abfd;
1025      int sym;
1026      struct internal_reloc *rel;
1027 {
1028   struct ppc_coff_link_hash_entry *h;
1029
1030   h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
1031
1032   CHECK_EYE(h->eye_catcher);
1033
1034   h->symbol_is_glue = 1;
1035   h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
1036
1037   return;
1038 }
1039
1040 \f
1041 /* Provided the symbol, returns the value reffed */
1042 static long get_symbol_value PARAMS ((asymbol *));
1043
1044 static long
1045 get_symbol_value (symbol)       
1046      asymbol *symbol;
1047 {                                             
1048   long relocation = 0;
1049
1050   if (bfd_is_com_section (symbol->section))
1051     {
1052       relocation = 0;                           
1053     }
1054   else 
1055     {                                      
1056       relocation = symbol->value +
1057         symbol->section->output_section->vma +
1058           symbol->section->output_offset;
1059     }                                           
1060
1061   return(relocation);
1062 }
1063
1064 /* Return true if this relocation should
1065    appear in the output .reloc section. */
1066
1067 static boolean in_reloc_p(abfd, howto)
1068      bfd * abfd;
1069      reloc_howto_type *howto;
1070 {
1071   return 
1072     (! howto->pc_relative) 
1073       && (howto->type != IMAGE_REL_PPC_TOCREL16)
1074       && (howto->type != IMAGE_REL_PPC_IMGLUE);
1075 }     
1076
1077 /* this function is in charge of performing all the ppc PE relocations */
1078 /* Don't yet know if we want to do this this particular way ... (krk)  */
1079 /* FIXME: (it is not yet enabled) */
1080
1081 static bfd_reloc_status_type
1082 pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
1083               error_message)
1084      bfd *abfd;
1085      arelent *reloc_entry;
1086      asymbol *symbol_in;
1087      PTR data;
1088      asection *input_section;
1089      bfd *output_bfd;
1090      char **error_message;
1091 {
1092   /* the consth relocation comes in two parts, we have to remember
1093      the state between calls, in these variables */
1094   static boolean part1_consth_active = false;
1095   static unsigned long part1_consth_value;
1096
1097   unsigned long insn;
1098   unsigned long sym_value;
1099   unsigned long unsigned_value;
1100   unsigned short r_type;
1101   long signed_value;
1102   
1103   unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
1104   bfd_byte  *hit_data =addr + (bfd_byte *)(data);
1105         
1106   fprintf(stderr, "pe_ppc_reloc (%s)\n", TARGET_LITTLE_NAME);
1107
1108   r_type = reloc_entry->howto->type;
1109
1110   if (output_bfd) 
1111     {
1112       /* Partial linking - do nothing */
1113       reloc_entry->address += input_section->output_offset;
1114       return bfd_reloc_ok; 
1115     }
1116
1117   if (symbol_in != NULL
1118       && bfd_is_und_section (symbol_in->section))
1119     {
1120       /* Keep the state machine happy in case we're called again */
1121       if (r_type == IMAGE_REL_PPC_REFHI) 
1122         {
1123           part1_consth_active = true;
1124           part1_consth_value  = 0;
1125         }
1126       return(bfd_reloc_undefined);
1127     }
1128   
1129   if ((part1_consth_active) && (r_type != IMAGE_REL_PPC_PAIR)) 
1130     {
1131       part1_consth_active = false;
1132       *error_message = (char *) "Missing PAIR";
1133       return(bfd_reloc_dangerous);
1134     }
1135
1136
1137   sym_value = get_symbol_value(symbol_in);
1138   
1139   return(bfd_reloc_ok); 
1140 }
1141
1142 /* The reloc processing routine for the optimized COFF linker.  */
1143
1144 static boolean
1145 coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
1146                            contents, relocs, syms, sections)
1147      bfd *output_bfd;
1148      struct bfd_link_info *info;
1149      bfd *input_bfd;
1150      asection *input_section;
1151      bfd_byte *contents;
1152      struct internal_reloc *relocs;
1153      struct internal_syment *syms;
1154      asection **sections;
1155 {
1156   struct internal_reloc *rel;
1157   struct internal_reloc *relend;
1158   boolean hihalf;
1159   bfd_vma hihalf_val;
1160   asection *toc_section = 0;
1161   bfd_vma relocation;
1162   reloc_howto_type *howto = 0;
1163   
1164 #ifdef DEBUG_RELOC
1165   fprintf(stderr, 
1166           "pe_ppc_relocate_section (%s) for %s \n", 
1167           TARGET_LITTLE_NAME,
1168           input_section->name);
1169   
1170 #endif  
1171
1172   /* If we are performing a relocateable link, we don't need to do a
1173      thing.  The caller will take care of adjusting the reloc
1174      addresses and symbol indices.  */
1175   if (info->relocateable)
1176     return true;
1177   
1178   hihalf = false;
1179   hihalf_val = 0;
1180
1181   rel = relocs;
1182   relend = rel + input_section->reloc_count;
1183   for (; rel < relend; rel++)
1184     {
1185       long symndx;
1186       struct ppc_coff_link_hash_entry *h;
1187       struct internal_syment *sym;
1188       bfd_vma val;
1189
1190       asection *sec;
1191       bfd_reloc_status_type rstat;
1192       bfd_byte *loc;
1193
1194       unsigned short r_type  = EXTRACT_TYPE (rel->r_type);
1195       unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
1196       unsigned short junk    = EXTRACT_JUNK (rel->r_type);
1197   
1198 #ifdef DEBUG_RELOC
1199       /* now examine flags */
1200       if (r_flags != 0) 
1201         {
1202           fprintf (stderr, "Reloc with flags found!");
1203           if ( r_flags & IMAGE_REL_PPC_NEG ) 
1204             fprintf (stderr, " NEG");
1205           if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
1206             fprintf (stderr, " BRTAKEN");
1207           if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
1208             fprintf (stderr, " BRNTAKEN");
1209           if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
1210             fprintf (stderr, " TOCDEFN");
1211           fprintf(stderr, "\n");
1212         }
1213 #endif
1214
1215       symndx = rel->r_symndx;
1216       loc = contents + rel->r_vaddr - input_section->vma;
1217
1218       /* FIXME: check bounds on r_type */
1219       howto = ppc_coff_howto_table + r_type;
1220
1221       if (symndx == -1)
1222         {
1223           h = NULL;
1224           sym = NULL;
1225         }
1226       else
1227         {
1228           h = (struct ppc_coff_link_hash_entry *) 
1229             (obj_coff_sym_hashes (input_bfd)[symndx]);
1230           if (h != 0) 
1231             {
1232               CHECK_EYE(h->eye_catcher);
1233             }
1234
1235           sym = syms + symndx;
1236         }
1237
1238       sec = NULL;
1239       val = 0;
1240
1241       /* FIXME: PAIR unsupported in the following code */
1242       if (h == NULL)
1243         {
1244           if (symndx == -1)
1245             sec = bfd_abs_section_ptr;
1246           else
1247             {
1248               sec = sections[symndx];
1249               val = (sec->output_section->vma
1250                      + sec->output_offset
1251                      + sym->n_value
1252                      - sec->vma);
1253             }
1254         }
1255       else
1256         {
1257           CHECK_EYE(h->eye_catcher);
1258
1259           if (h->root.root.type == bfd_link_hash_defined
1260               || h->root.root.type == bfd_link_hash_defweak)
1261             {
1262               sec = h->root.root.u.def.section;
1263               val = (h->root.root.u.def.value
1264                      + sec->output_section->vma
1265                      + sec->output_offset);
1266             }
1267           else
1268             {
1269               if (! ((*info->callbacks->undefined_symbol)
1270                      (info, h->root.root.root.string, input_bfd, input_section,
1271                       rel->r_vaddr - input_section->vma)))
1272                 return false;
1273             }
1274         }
1275
1276       rstat = bfd_reloc_ok;
1277       
1278       /* Each case must do its own relocation, setting rstat appropriately */
1279       switch (r_type)
1280         {
1281         default:
1282           fprintf( stderr, 
1283                   "ERROR: during reloc processing -- unsupported reloc %s\n", 
1284                   howto->name);
1285           bfd_set_error (bfd_error_bad_value);
1286           abort();
1287           return false;
1288         case IMAGE_REL_PPC_TOCREL16:
1289           {
1290             bfd_vma our_toc_offset;
1291             int fixit;
1292
1293             DUMP_RELOC2(howto->name, rel);
1294
1295             if (toc_section == 0) 
1296               {
1297                 toc_section = bfd_get_section_by_name (bfd_of_toc_owner, 
1298                                                        TOC_SECTION_NAME);
1299 #ifdef TOC_DEBUG
1300
1301                 fprintf(stderr,
1302                         "BFD of toc owner %p, section addr of %s %p\n",
1303                          bfd_of_toc_owner, TOC_SECTION_NAME, toc_section);
1304 #endif
1305
1306                 if ( toc_section == NULL ) 
1307                   {
1308                     fprintf(stderr, "No Toc section!\n");
1309                     abort();
1310                   }
1311               }
1312
1313             /* 
1314              *  Amazing bit tricks present. As we may have seen earlier, we
1315              *  use the 1 bit to tell us whether or not a toc offset has been
1316              *  allocated. Now that they've all been allocated, we will use
1317              *  the 1 bit to tell us if we've written this particular toc
1318              *  entry out.
1319              */
1320             fixit = false;
1321             if (h == 0)
1322               { /* it is a file local symbol */
1323                 int *local_toc_table;
1324                 const char *name;
1325
1326                 sym = syms + symndx;
1327                 name = sym->_n._n_name;
1328
1329                 local_toc_table = obj_coff_local_toc_table(input_bfd);
1330                 our_toc_offset = local_toc_table[symndx];
1331
1332                 if ((our_toc_offset & 1) != 0)
1333                   {
1334                     /* if it has been written out, it is marked with the 
1335                        1 bit. Fix up our offset, but do not write it out
1336                        again.
1337                      */
1338                     our_toc_offset &= ~1;
1339 #ifdef TOC_DEBUG
1340
1341                     fprintf(stderr,
1342                             "Not writing out toc_offset of %d for %s\n", our_toc_offset, name);
1343 #endif
1344                   }
1345                 else
1346                   {
1347                     /* write out the toc entry */
1348                     record_toc(toc_section, our_toc_offset, strdup(name));
1349 #ifdef TOC_DEBUG
1350                     fprintf(stderr,
1351                             "Writing out toc_offset toc_section (%p,%p)+%d val %d for %s\n", 
1352                             toc_section,
1353                             toc_section->contents,
1354                             our_toc_offset, 
1355                             val,
1356                             name);
1357 #endif
1358
1359                     bfd_put_32(output_bfd,
1360                                val,
1361                                toc_section->contents + our_toc_offset);
1362
1363                     local_toc_table[symndx] |= 1;
1364                     fixit = true;
1365                   }
1366               }
1367             else
1368               {
1369                 const char *name = h->root.root.root.string;
1370                 our_toc_offset = h->toc_offset;
1371
1372                 if ( (r_flags & IMAGE_REL_PPC_TOCDEFN) == IMAGE_REL_PPC_TOCDEFN &&
1373                       our_toc_offset == 1)
1374                   {
1375                     /* This is unbelievable cheese. Some knowledgable asm hacker has decided to
1376                        use r2 as a base for loading a value. He/She does this by setting the
1377                        tocdefn bit, and not supplying a toc definition. The behaviour is then
1378                        to use the value of the symbol as a toc index. Good Grief.
1379                     */
1380                     our_toc_offset = val - (toc_section->output_section->vma + toc_section->output_offset);
1381                   }
1382                 else if ((our_toc_offset & 1) != 0)
1383                   {
1384                     /* if it has been written out, it is marked with the 
1385                        1 bit. Fix up our offset, but do not write it out
1386                        again.
1387                      */
1388                     our_toc_offset &= ~1;
1389 #ifdef TOC_DEBUG
1390                     fprintf(stderr,
1391                             "Not writing out toc_offset of %d for %s\n", our_toc_offset, name);
1392 #endif
1393                   }
1394                 else
1395                   {
1396                     record_toc(toc_section, our_toc_offset, strdup(name));
1397
1398 #ifdef TOC_DEBUG
1399                     /* write out the toc entry */
1400                     fprintf(stderr,
1401                             "Writing out toc_offset toc_section (%p,%p)+%d val %d for %s\n", 
1402                             toc_section,
1403                             toc_section->contents,
1404                             our_toc_offset, 
1405                             val,
1406                             name);
1407 #endif
1408
1409                     /* write out the toc entry */
1410                     bfd_put_32(output_bfd,
1411                                val,
1412                                toc_section->contents + our_toc_offset);
1413
1414                     h->toc_offset |= 1;
1415                     /* The tricky part is that this is the address that */
1416                     /* needs a .reloc entry for it */
1417                     fixit = true;
1418                   }
1419               }
1420
1421             if (fixit && info->base_file) 
1422               {
1423                 /* So if this is non pcrelative, and is referenced
1424                    to a section or a common symbol, then it needs a reloc */
1425
1426                 /* relocation to a symbol in a section which
1427                    isn't absolute - we output the address here 
1428                    to a file */
1429
1430                 bfd_vma addr =  toc_section->output_section->vma
1431                   + toc_section->output_offset + our_toc_offset;
1432                     
1433                 fprintf(stderr,
1434                         "  Toc Section reloc candidate\n");
1435                     
1436                 if (coff_data(output_bfd)->pe)
1437                   addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
1438                 fwrite (&addr, 1,4, (FILE *) info->base_file);
1439               }
1440
1441
1442             /* FIXME: this test is conservative */
1443             if ( (r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN &&
1444                 our_toc_offset > toc_section->_raw_size)
1445               {
1446                 fprintf(stderr,
1447                         "reloc offset is bigger than the toc size!\n");
1448                 abort();
1449               }
1450
1451             /* Now we know the relocation for this toc reference */
1452             relocation =  our_toc_offset + TOC_LOAD_ADJUSTMENT;
1453             rstat = _bfd_relocate_contents (howto,
1454                                             input_bfd, 
1455                                             relocation, 
1456                                             loc);
1457           }
1458           break;
1459         case IMAGE_REL_PPC_IFGLUE:
1460           {
1461             /* To solve this, we need to know whether or not the symbol */
1462             /* appearing on the call instruction is a glue function or not. */
1463             /* A glue function must announce itself via a IMGLUE reloc, and */
1464             /* the reloc contains the required toc restore instruction */
1465           
1466             bfd_vma x;
1467             const char *my_name;
1468             DUMP_RELOC2(howto->name, rel);
1469
1470             if (h != 0)
1471               {
1472                 my_name = h->root.root.root.string;
1473                 if (h->symbol_is_glue == 1) 
1474                   {
1475                     x = bfd_get_32(input_bfd, loc);
1476                     bfd_put_32(input_bfd, h->glue_insn, loc);
1477                   }
1478               }
1479           }
1480           break;
1481         case IMAGE_REL_PPC_SECREL:
1482           /* Unimplemented: codeview debugging information */
1483           /* For fast access to the header of the section 
1484              containing the item. */
1485           break;
1486         case IMAGE_REL_PPC_SECTION:
1487           /* Unimplemented: codeview debugging information */
1488           /* Is used to indicate that the value should be relative
1489              to the beginning of the section that contains the
1490              symbol */
1491           break;
1492         case IMAGE_REL_PPC_ABSOLUTE:
1493           {
1494             const char *my_name;
1495             if (h == 0)
1496                 my_name = (syms+symndx)->_n._n_name;
1497             else
1498               {
1499                 my_name = h->root.root.root.string;
1500               }
1501
1502             fprintf(stderr, 
1503                     "Warning: unsupported reloc %s <file %s, section %s>\n", 
1504                     howto->name,
1505                     bfd_get_filename(input_bfd),
1506                     input_section->name);
1507
1508             fprintf(stderr,"sym %d (%s), r_vaddr %d (%x)\n", 
1509                     rel->r_symndx, my_name, rel->r_vaddr, rel->r_vaddr);  
1510           }
1511           break;
1512         case IMAGE_REL_PPC_IMGLUE:
1513           {
1514             /* There is nothing to do now. This reloc was noted in the first
1515                pass over the relocs, and the glue instruction extracted */
1516             const char *my_name;
1517             if (h->symbol_is_glue == 1) 
1518               break;
1519             my_name = h->root.root.root.string;
1520             fprintf(stderr, 
1521                     "Warning: previously missed IMGLUE reloc %s <file %s, section %s>\n", 
1522                     howto->name,
1523                     bfd_get_filename(input_bfd),
1524                     input_section->name);
1525             break;
1526
1527           }
1528           break;
1529
1530         case IMAGE_REL_PPC_ADDR32NB:
1531           {
1532             struct coff_link_hash_entry *myh = 0;
1533             const char *name = 0;
1534             DUMP_RELOC2(howto->name, rel);
1535             if (h == 0)
1536               { /* it is a file local symbol */
1537                 sym = syms + symndx;
1538                 name = sym->_n._n_name;
1539               }
1540             else
1541               {
1542                 char *target = 0;
1543
1544                 name = h->root.root.root.string;
1545                 if (strcmp(".idata$2", name) == 0)
1546                   target = "__idata2_magic__";
1547                 else if (strcmp(".idata$4", name) == 0)
1548                   target = "__idata4_magic__";
1549                 else if (strcmp(".idata$5", name) == 0)
1550                   target = "__idata5_magic__";
1551                 else
1552                   abort();
1553
1554                 myh = 0;
1555
1556                 myh = coff_link_hash_lookup (coff_hash_table (info),
1557                                              target,
1558                                              false, false, true);
1559                 if (myh == 0) 
1560                   {
1561                     fprintf(stderr, "Missing idata magic cookies, this cannot work anyway...\n");
1562                     abort();
1563                   }
1564
1565                 val = myh->root.u.def.value + 
1566                   sec->output_section->vma + sec->output_offset;
1567                 if (first_thunk_address == 0)
1568                   {
1569                     int idata5offset;
1570                     myh = coff_link_hash_lookup (coff_hash_table (info),
1571                                                  "__idata5_magic__",
1572                                                  false, false, true);
1573                     first_thunk_address = myh->root.u.def.value + 
1574                       sec->output_section->vma + 
1575                       sec->output_offset - 
1576                         pe_data(output_bfd)->pe_opthdr.ImageBase;
1577
1578                     idata5offset = myh->root.u.def.value;
1579                     myh = coff_link_hash_lookup (coff_hash_table (info),
1580                                                  "__idata6_magic__",
1581                                                  false, false, true);
1582
1583                     thunk_size = myh->root.u.def.value - idata5offset;
1584                     myh = coff_link_hash_lookup (coff_hash_table (info),
1585                                                  "__idata4_magic__",
1586                                                  false, false, true);
1587                     import_table_size = myh->root.u.def.value;
1588                   }
1589               }
1590
1591             rstat = _bfd_relocate_contents (howto,
1592                               input_bfd, 
1593                               val - 
1594                               pe_data(output_bfd)->pe_opthdr.ImageBase,
1595                               loc);
1596           }
1597           break;
1598
1599         case IMAGE_REL_PPC_REL24:
1600           DUMP_RELOC2(howto->name, rel);
1601           val -= (input_section->output_section->vma
1602                   + input_section->output_offset);
1603
1604           rstat = _bfd_relocate_contents (howto,
1605                                           input_bfd, 
1606                                           val, 
1607                                           loc);
1608           break;
1609         case IMAGE_REL_PPC_ADDR16:
1610         case IMAGE_REL_PPC_ADDR24:
1611         case IMAGE_REL_PPC_ADDR32:
1612           DUMP_RELOC2(howto->name, rel);
1613           rstat = _bfd_relocate_contents (howto,
1614                                           input_bfd, 
1615                                           val, 
1616                                           loc);
1617           break;
1618         }
1619
1620       if ( info->base_file )
1621         {
1622           /* So if this is non pcrelative, and is referenced
1623              to a section or a common symbol, then it needs a reloc */
1624           if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
1625             {
1626               /* relocation to a symbol in a section which
1627                  isn't absolute - we output the address here 
1628                  to a file */
1629               bfd_vma addr = rel->r_vaddr 
1630                 - input_section->vma 
1631                 + input_section->output_offset 
1632                   + input_section->output_section->vma;
1633
1634               if (coff_data(output_bfd)->pe)
1635                 {
1636                   addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
1637                   fprintf(stderr,
1638                           " adjusted down to %d", addr);
1639                 }
1640               fprintf(stderr, "\n");
1641
1642               fwrite (&addr, 1,4, (FILE *) info->base_file);
1643             }
1644         }
1645
1646       switch (rstat)
1647         {
1648         default:
1649           abort ();
1650         case bfd_reloc_ok:
1651           break;
1652         case bfd_reloc_overflow:
1653           {
1654             const char *name;
1655             char buf[SYMNMLEN + 1];
1656
1657             if (symndx == -1)
1658               name = "*ABS*";
1659             else if (h != NULL)
1660               name = h->root.root.root.string;
1661             else if (sym == NULL)
1662               name = "*unknown*";
1663             else if (sym->_n._n_n._n_zeroes == 0
1664                      && sym->_n._n_n._n_offset != 0)
1665               name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
1666             else
1667               {
1668                 strncpy (buf, sym->_n._n_name, SYMNMLEN);
1669                 buf[SYMNMLEN] = '\0';
1670                 name = buf;
1671               }
1672 #if 0
1673             else
1674               {
1675                 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
1676                 if (name == NULL)
1677                   return false;
1678               }
1679 #endif
1680
1681             if (! ((*info->callbacks->reloc_overflow)
1682                    (info, name, howto->name, 
1683                     (bfd_vma) 0, input_bfd,
1684                     input_section, rel->r_vaddr - input_section->vma)))
1685               return false;
1686           }
1687         }
1688
1689     }     
1690
1691   return true;
1692 }
1693
1694 #ifdef COFF_IMAGE_WITH_PE
1695
1696 long int global_toc_size = 0;
1697
1698 bfd* bfd_of_toc_owner = 0;
1699
1700 long int import_table_size;
1701 long int first_thunk_address;
1702 long int thunk_size;
1703
1704 struct list_ele *head;
1705 struct list_ele *tail;
1706
1707 void
1708 dump_toc(vfile)
1709      void *vfile;
1710 {
1711   FILE *file = vfile;
1712   struct list_ele *t;
1713
1714   fprintf(file, 
1715           " Offset Offset   Name if present\n");
1716
1717   for(t = head; t != 0; t=t->next)
1718     {
1719       fprintf(file,
1720               " %2x  %04lx    %s\n",
1721               t->offset - 32768, t->offset, t->name);
1722     }
1723 }
1724
1725 boolean
1726 ppc_allocate_toc_section (info) 
1727      struct bfd_link_info *info;
1728 {
1729   asection *s;
1730   bfd_byte *foo;
1731   static char test_char = '1';
1732
1733   if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */
1734     return true;
1735
1736   if (bfd_of_toc_owner == 0)
1737     {
1738       fprintf(stderr,
1739               "There is no bfd that owns the toc section!\n");
1740       abort();
1741     }
1742
1743   s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME);
1744   if (s == NULL) 
1745     {
1746       fprintf(stderr, "No Toc section!\n");
1747       abort();
1748     }
1749
1750   foo = bfd_alloc(bfd_of_toc_owner, global_toc_size);
1751   memset(foo, test_char, global_toc_size);
1752
1753   s->_raw_size = s->_cooked_size = global_toc_size;
1754   s->contents = foo;
1755
1756   return true;
1757 }
1758
1759 boolean
1760 ppc_process_before_allocation (abfd, info)
1761      bfd *abfd;
1762      struct bfd_link_info *info;
1763 {
1764   asection *sec;
1765   struct internal_reloc *i, *rel;
1766
1767 #if 0
1768   fprintf(stderr, 
1769           "ppc_process_before_allocation: BFD %s\n", 
1770           bfd_get_filename(abfd));
1771 #endif
1772
1773   /* here we have a bfd that is to be included on the link. We have a hook
1774      to do reloc rummaging, before section sizes are nailed down. */
1775
1776   _bfd_coff_get_external_symbols(abfd);
1777
1778   /* rummage around all the relocs and map the toc */
1779   sec = abfd->sections;
1780
1781   if (sec == 0)
1782     {
1783       return true;
1784     }
1785
1786   for (; sec != 0; sec = sec->next)
1787   {
1788     int toc_offset;
1789 #ifdef DEBUG_RELOC
1790     fprintf(stderr, 
1791             "  section %s reloc count %d\n", 
1792             sec->name, 
1793             sec->reloc_count);
1794 #endif
1795
1796     if (sec->reloc_count == 0) 
1797       continue;
1798
1799     /* load the relocs */
1800     /* FIXME: there may be a storage leak here */
1801     i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0);
1802     
1803     if (i == 0)
1804       abort();
1805
1806     for (rel=i;rel<i+sec->reloc_count;++rel) 
1807       {
1808         unsigned short r_type  = EXTRACT_TYPE (rel->r_type);
1809         unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
1810         unsigned short junk    = EXTRACT_JUNK (rel->r_type);
1811
1812 #ifdef DEBUG_RELOC
1813         /* now examine flags */
1814         if (r_flags != 0) 
1815           {
1816             fprintf (stderr, "Reloc with flags found!");
1817             if ( r_flags & IMAGE_REL_PPC_NEG ) 
1818               fprintf (stderr, " NEG");
1819             if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
1820               fprintf (stderr, " BRTAKEN");
1821             if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
1822               fprintf (stderr, " BRNTAKEN");
1823             if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
1824                 fprintf (stderr, " TOCDEFN");
1825             fprintf(stderr, "\n");
1826           }
1827 #endif
1828         
1829         DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
1830
1831         switch(r_type) 
1832           {
1833           case IMAGE_REL_PPC_TOCREL16:
1834             if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
1835               toc_offset = ppc_record_data_in_toc_entry(abfd, info, sec, 
1836                                                         rel->r_symndx, 
1837                                                         default_toc);
1838             else
1839               toc_offset = ppc_record_toc_entry(abfd, info, sec, 
1840                                                 rel->r_symndx, default_toc);
1841             break;
1842           case IMAGE_REL_PPC_IMGLUE:
1843             ppc_mark_symbol_as_glue(abfd, rel->r_symndx, rel);
1844             break;
1845           default:
1846             break;
1847           }
1848       }
1849   }
1850 }
1851
1852 #endif
1853
1854
1855 static bfd_reloc_status_type
1856 ppc_refhi_reloc (abfd,
1857                  reloc_entry,
1858                  symbol,
1859                  data,
1860                  input_section,
1861                  output_bfd,
1862                  error_message)
1863      bfd *abfd;
1864      arelent *reloc_entry;
1865      asymbol *symbol;
1866      PTR data;
1867      asection *input_section;
1868      bfd *output_bfd;
1869      char **error_message;
1870 {
1871   UN_IMPL("REFHI");
1872   DUMP_RELOC("REFHI",reloc_entry);
1873
1874   if (output_bfd == (bfd *) NULL)
1875     return bfd_reloc_continue;
1876
1877   return bfd_reloc_undefined;
1878 }
1879
1880 static bfd_reloc_status_type
1881 ppc_reflo_reloc (abfd,
1882                  reloc_entry,
1883                  symbol,
1884                  data,
1885                  input_section,
1886                  output_bfd,
1887                  error_message)
1888      bfd *abfd;
1889      arelent *reloc_entry;
1890      asymbol *symbol;
1891      PTR data;
1892      asection *input_section;
1893      bfd *output_bfd;
1894      char **error_message;
1895 {
1896   UN_IMPL("REFLO");
1897   DUMP_RELOC("REFLO",reloc_entry);
1898
1899   if (output_bfd == (bfd *) NULL)
1900     return bfd_reloc_continue;
1901
1902   return bfd_reloc_undefined;
1903 }
1904
1905 static bfd_reloc_status_type
1906 ppc_pair_reloc (abfd,
1907                 reloc_entry,
1908                 symbol,
1909                 data,
1910                 input_section,
1911                 output_bfd,
1912                 error_message)
1913      bfd *abfd;
1914      arelent *reloc_entry;
1915      asymbol *symbol;
1916      PTR data;
1917      asection *input_section;
1918      bfd *output_bfd;
1919      char **error_message;
1920 {
1921   UN_IMPL("PAIR");
1922   DUMP_RELOC("PAIR",reloc_entry);
1923
1924   if (output_bfd == (bfd *) NULL)
1925     return bfd_reloc_continue;
1926
1927   return bfd_reloc_undefined;
1928 }
1929
1930 \f
1931 static bfd_reloc_status_type
1932 ppc_toc16_reloc (abfd,
1933                  reloc_entry,
1934                  symbol,
1935                  data,
1936                  input_section,
1937                  output_bfd,
1938                  error_message)
1939      bfd *abfd;
1940      arelent *reloc_entry;
1941      asymbol *symbol;
1942      PTR data;
1943      asection *input_section;
1944      bfd *output_bfd;
1945      char **error_message;
1946 {
1947   UN_IMPL("TOCREL16");
1948   DUMP_RELOC("TOCREL16",reloc_entry);
1949
1950   if (output_bfd == (bfd *) NULL)
1951     {
1952       return bfd_reloc_continue;
1953     }
1954
1955   return bfd_reloc_ok;
1956 }
1957
1958 /* ADDR32NB : 32 bit address relative to the virtual origin.         */
1959 /*            (On the alpha, this is always a linker generated thunk)*/
1960 /*            (i.e. 32bit addr relative to the image base)           */
1961 /*                                                                   */
1962 /*                                                                   */
1963
1964 static bfd_reloc_status_type
1965 ppc_addr32nb_reloc (abfd,
1966                     reloc_entry,
1967                     symbol,
1968                     data,
1969                     input_section,
1970                     output_bfd,
1971                     error_message)
1972      bfd *abfd;
1973      arelent *reloc_entry;
1974      asymbol *symbol;
1975      PTR data;
1976      asection *input_section;
1977      bfd *output_bfd;
1978      char **error_message;
1979 {
1980   UN_IMPL("ADDR32NB");
1981   DUMP_RELOC("ADDR32NB",reloc_entry);
1982
1983   return bfd_reloc_ok;
1984 }
1985
1986 static bfd_reloc_status_type
1987 ppc_secrel_reloc (abfd,
1988                   reloc_entry,
1989                   symbol,
1990                   data,
1991                   input_section,
1992                   output_bfd,
1993                   error_message)
1994      bfd *abfd;
1995      arelent *reloc_entry;
1996      asymbol *symbol;
1997      PTR data;
1998      asection *input_section;
1999      bfd *output_bfd;
2000      char **error_message;
2001 {
2002   UN_IMPL("SECREL");
2003   DUMP_RELOC("SECREL",reloc_entry);
2004
2005   if (output_bfd == (bfd *) NULL)
2006     return bfd_reloc_continue;
2007
2008   return bfd_reloc_ok;
2009 }
2010
2011 static bfd_reloc_status_type
2012 ppc_section_reloc (abfd,
2013                    reloc_entry,
2014                    symbol,
2015                    data,
2016                    input_section,
2017                    output_bfd,
2018                    error_message)
2019      bfd *abfd;
2020      arelent *reloc_entry;
2021      asymbol *symbol;
2022      PTR data;
2023      asection *input_section;
2024      bfd *output_bfd;
2025      char **error_message;
2026 {
2027   UN_IMPL("SECTION");
2028   DUMP_RELOC("SECTION",reloc_entry);
2029
2030   if (output_bfd == (bfd *) NULL)
2031     return bfd_reloc_continue;
2032
2033   return bfd_reloc_ok;
2034 }
2035
2036 static bfd_reloc_status_type
2037 ppc_imglue_reloc (abfd,
2038                   reloc_entry,
2039                   symbol,
2040                   data,
2041                   input_section,
2042                   output_bfd,
2043                   error_message)
2044      bfd *abfd;
2045      arelent *reloc_entry;
2046      asymbol *symbol;
2047      PTR data;
2048      asection *input_section;
2049      bfd *output_bfd;
2050      char **error_message;
2051 {
2052   UN_IMPL("IMGLUE");
2053   DUMP_RELOC("IMGLUE",reloc_entry);
2054
2055   if (output_bfd == (bfd *) NULL)
2056     return bfd_reloc_continue;
2057
2058   return bfd_reloc_ok;
2059 }
2060
2061 \f
2062
2063 #define MAX_RELOC_INDEX  \
2064       (sizeof(ppc_coff_howto_table) / sizeof(ppc_coff_howto_table[0]) - 1)
2065
2066
2067 /* FIXME: There is a possiblity that when we read in a reloc from a file,
2068           that there are some bits encoded in the upper portion of the 
2069           type field. Not yet implemented.
2070 */
2071 static void ppc_coff_rtype2howto PARAMS ((arelent *relent,
2072                                           struct internal_reloc *internal));
2073
2074 static void
2075 ppc_coff_rtype2howto (relent, internal)
2076      arelent *relent;
2077      struct internal_reloc *internal;
2078 {  
2079
2080   /* We can encode one of three things in the type field, aside from the
2081      type:
2082      1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
2083         value, rather than an addition value
2084      2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
2085         the branch is expected to be taken or not.
2086      3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
2087      For now, we just strip this stuff to find the type, and ignore it other
2088      than that.
2089   */
2090
2091   unsigned short r_type  = EXTRACT_TYPE (internal->r_type);
2092   unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
2093   unsigned short junk    = EXTRACT_JUNK (internal->r_type);
2094
2095   /* the masking process only slices off the bottom byte for r_type. */
2096   if ( r_type > MAX_RELOC_INDEX ) 
2097     {
2098       fprintf(stderr, 
2099               "ppc_coff_rtype2howto: reloc index %d out of range [%d, %d]\n",
2100               internal->r_type, 0, MAX_RELOC_INDEX);
2101       abort();
2102     }
2103
2104   /* check for absolute crap */
2105   if ( junk != 0 )
2106     {
2107       fprintf(stderr, 
2108               "ppc_coff_rtype2howto: reloc index %d contains junk %d\n",
2109               internal->r_type, junk);
2110       abort();
2111     }
2112
2113 #ifdef DEBUG_RELOC
2114   /* now examine flags */
2115   if (r_flags != 0) 
2116     {
2117       fprintf (stderr, "Reloc with flags found!");
2118       if ( r_flags & IMAGE_REL_PPC_NEG ) 
2119         fprintf (stderr, " NEG");
2120       if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
2121         fprintf (stderr, " BRTAKEN");
2122       if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
2123         fprintf (stderr, " BRNTAKEN");
2124       if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
2125         fprintf (stderr, " TOCDEFN");
2126       fprintf(stderr, "\n");
2127     }
2128 #endif
2129
2130   switch(r_type) 
2131     {
2132     case IMAGE_REL_PPC_ADDR16:
2133     case IMAGE_REL_PPC_REL24:
2134     case IMAGE_REL_PPC_ADDR24:
2135     case IMAGE_REL_PPC_TOCREL16:
2136     case IMAGE_REL_PPC_ADDR32:
2137     case IMAGE_REL_PPC_IFGLUE:
2138     case IMAGE_REL_PPC_ADDR32NB:
2139     case IMAGE_REL_PPC_SECTION:
2140     case IMAGE_REL_PPC_SECREL:
2141       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
2142       break;
2143     case IMAGE_REL_PPC_IMGLUE:
2144       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
2145       break;
2146     default:
2147       fprintf(stderr, 
2148               "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
2149               ppc_coff_howto_table[r_type].name,
2150               r_type);
2151       break;
2152     }
2153   
2154   relent->howto = ppc_coff_howto_table + r_type;
2155   
2156 }
2157
2158 static reloc_howto_type *
2159 coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
2160      bfd *abfd;
2161      asection *sec;
2162      struct internal_reloc *rel;
2163      struct coff_link_hash_entry *h;
2164      struct internal_syment *sym;
2165      bfd_vma *addendp;
2166 {
2167   reloc_howto_type *howto;
2168
2169   /* We can encode one of three things in the type field, aside from the
2170      type:
2171      1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
2172         value, rather than an addition value
2173      2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
2174         the branch is expected to be taken or not.
2175      3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
2176      For now, we just strip this stuff to find the type, and ignore it other
2177      than that.
2178   */
2179
2180   unsigned short r_type  = EXTRACT_TYPE (rel->r_type);
2181   unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
2182   unsigned short junk    = EXTRACT_JUNK (rel->r_type);
2183
2184 fprintf(stderr,
2185         "coff_ppc_rtype_to_howto\n");
2186
2187   /* the masking process only slices off the bottom byte for r_type. */
2188   if ( r_type > MAX_RELOC_INDEX ) 
2189     {
2190       fprintf(stderr, 
2191               "coff_ppc_rtype_to_howto: index %d out of range [%d, %d]\n",
2192               r_type, 0, MAX_RELOC_INDEX);
2193       abort();
2194     }
2195   
2196   /* check for absolute crap */
2197   if ( junk != 0 )
2198     {
2199       fprintf(stderr, 
2200               "coff_ppc_rtype_to_howto: reloc index %d contains junk %d\n",
2201               rel->r_type, junk);
2202       abort();
2203     }
2204   
2205 #ifdef DEBUG_RELOC
2206   /* now examine flags */
2207   if (r_flags != 0) 
2208     {
2209       fprintf (stderr, "Reloc with flags found!");
2210       if ( r_flags & IMAGE_REL_PPC_NEG ) 
2211         fprintf (stderr, " NEG");
2212       if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
2213         fprintf (stderr, " BRTAKEN");
2214       if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
2215         fprintf (stderr, " BRNTAKEN");
2216       if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
2217         fprintf (stderr, " TOCDEFN");
2218       fprintf(stderr, "\n");
2219     }
2220 #endif
2221   
2222   switch(r_type) 
2223     {
2224     case IMAGE_REL_PPC_ADDR32NB:
2225       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
2226       *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
2227       break;
2228     case IMAGE_REL_PPC_ADDR16:
2229     case IMAGE_REL_PPC_REL24:
2230     case IMAGE_REL_PPC_ADDR24:
2231     case IMAGE_REL_PPC_TOCREL16:
2232     case IMAGE_REL_PPC_ADDR32:
2233     case IMAGE_REL_PPC_IFGLUE:
2234     case IMAGE_REL_PPC_SECTION:
2235     case IMAGE_REL_PPC_SECREL:
2236       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
2237       break;
2238     case IMAGE_REL_PPC_IMGLUE:
2239       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
2240       break;
2241     default:
2242       fprintf(stderr, 
2243               "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
2244               ppc_coff_howto_table[r_type].name,
2245               r_type);
2246       break;
2247     }
2248   
2249   howto = ppc_coff_howto_table + r_type;
2250   return howto;
2251 }
2252
2253
2254 /* a cheesy little macro to make the code a little more readable */
2255 #define HOW2MAP(bfd_rtype,ppc_rtype)  \
2256  case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]
2257
2258 static reloc_howto_type *ppc_coff_reloc_type_lookup
2259 PARAMS ((bfd *, bfd_reloc_code_real_type));
2260
2261 static reloc_howto_type *
2262 ppc_coff_reloc_type_lookup (abfd, code)
2263      bfd *abfd;
2264      bfd_reloc_code_real_type code;
2265 {
2266   
2267 #ifdef DEBUG_RELOC
2268   fprintf(stderr, "ppc_coff_reloc_type_lookup for %s\n",
2269           bfd_get_reloc_code_name(code));
2270 #endif
2271   
2272   switch (code)
2273     {
2274       HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
2275       HOW2MAP(BFD_RELOC_16,           IMAGE_REL_PPC_ADDR16);
2276       HOW2MAP(BFD_RELOC_PPC_B26,      IMAGE_REL_PPC_REL24);
2277       HOW2MAP(BFD_RELOC_PPC_BA26,     IMAGE_REL_PPC_ADDR24);
2278       HOW2MAP(BFD_RELOC_PPC_TOC16,    IMAGE_REL_PPC_TOCREL16);
2279       HOW2MAP(BFD_RELOC_32,           IMAGE_REL_PPC_ADDR32);
2280       HOW2MAP(BFD_RELOC_RVA,          IMAGE_REL_PPC_ADDR32NB);
2281     default: 
2282       fprintf(stderr,
2283               "\treturning NULL\n");
2284       return NULL;
2285     }
2286   
2287   return NULL;
2288 }
2289
2290 #undef HOW2MAP
2291
2292 \f
2293 /* Tailor coffcode.h -- macro heaven. */
2294
2295 #define RTYPE2HOWTO(cache_ptr, dst)  ppc_coff_rtype2howto (cache_ptr, dst)
2296
2297 #ifndef COFF_IMAGE_WITH_PE
2298 static void
2299 ppc_coff_swap_sym_in_hook ();
2300 #endif
2301
2302 /* We use the special COFF backend linker, with our own special touch.  */
2303
2304 #define coff_bfd_reloc_type_lookup   ppc_coff_reloc_type_lookup
2305 #define coff_rtype_to_howto          coff_ppc_rtype_to_howto
2306 #define coff_relocate_section        coff_ppc_relocate_section
2307
2308 #ifndef COFF_IMAGE_WITH_PE
2309 #define coff_swap_sym_in_hook        ppc_coff_swap_sym_in_hook
2310 #endif
2311
2312 #define SELECT_RELOC(internal, howto) {internal.r_type=howto->type;}
2313
2314 #define COFF_PAGE_SIZE                       0x1000
2315
2316 #define POWERPC_LE_PE
2317
2318 #include "coffcode.h"
2319
2320 \f
2321
2322 #ifndef COFF_IMAGE_WITH_PE
2323 static void
2324 ppc_coff_swap_sym_in_hook (abfd, ext1, in1)
2325      bfd            *abfd;
2326      PTR ext1;
2327      PTR in1;
2328 {
2329   SYMENT *ext = (SYMENT *)ext1;
2330   struct internal_syment      *in = (struct internal_syment *)in1;
2331
2332 #if 0
2333   if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */
2334     return;
2335 #endif
2336
2337   if (strcmp(in->_n._n_name, ".toc") == 0)
2338     {
2339       flagword flags;
2340       register asection *s;
2341       char *foo;
2342
2343       s = bfd_get_section_by_name ( abfd , TOC_SECTION_NAME);
2344       if (s != NULL) 
2345         {
2346           return;
2347         }
2348
2349       flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
2350
2351 #ifdef TOC_DEBUG
2352       fprintf(stderr,
2353               "ppc_coff_swap_sym_in_hook: about to create the %s section\n",
2354               TOC_SECTION_NAME);
2355 #endif
2356
2357       s = bfd_make_section (abfd, TOC_SECTION_NAME);
2358
2359       if (s == NULL
2360           || !bfd_set_section_flags (abfd, s, flags)
2361           || !bfd_set_section_alignment (abfd, s, 2))
2362         {
2363           fprintf(stderr,
2364                   "toc section allocation failed!\n");
2365           abort();
2366         }
2367
2368       /* save the bfd for later allocation */
2369       bfd_of_toc_owner = abfd;
2370     }
2371
2372   return;
2373 }
2374 #endif
2375
2376 \f
2377
2378 /* The transfer vectors that lead the outside world to all of the above. */
2379
2380 #ifdef TARGET_LITTLE_SYM
2381 const bfd_target
2382 TARGET_LITTLE_SYM =
2383 {
2384   TARGET_LITTLE_NAME,           /* name or coff-arm-little */
2385   bfd_target_coff_flavour,
2386   false,                        /* data byte order is little */
2387   false,                        /* header byte order is little */
2388
2389   (HAS_RELOC | EXEC_P |         /* FIXME: object flags */
2390    HAS_LINENO | HAS_DEBUG |
2391    HAS_SYMS | HAS_LOCALS | WP_TEXT),
2392   
2393   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2394   0,                            /* leading char */
2395   '/',                          /* ar_pad_char */
2396   15,                           /* ar_max_namelen??? FIXMEmgo */
2397
2398   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2399   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2400   bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
2401
2402   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
2403   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
2404   bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
2405   
2406   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
2407      bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
2408   {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
2409      bfd_false},
2410   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
2411      _bfd_write_archive_contents, bfd_false},
2412   
2413   BFD_JUMP_TABLE_GENERIC (coff),
2414   BFD_JUMP_TABLE_COPY (coff),
2415   BFD_JUMP_TABLE_CORE (_bfd_nocore),
2416   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
2417   BFD_JUMP_TABLE_SYMBOLS (coff),
2418   BFD_JUMP_TABLE_RELOCS (coff),
2419   BFD_JUMP_TABLE_WRITE (coff),
2420   BFD_JUMP_TABLE_LINK (coff),
2421   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2422   
2423   COFF_SWAP_TABLE,
2424 };
2425 #endif
2426
2427 #ifdef TARGET_BIG_SYM
2428 const bfd_target
2429 TARGET_BIG_SYM =
2430 {
2431   TARGET_BIG_NAME,
2432   bfd_target_coff_flavour,      
2433   true,                         /* data byte order is big */
2434   true,                         /* header byte order is big */
2435
2436   (HAS_RELOC | EXEC_P |         /* FIXME: object flags */
2437    HAS_LINENO | HAS_DEBUG |
2438    HAS_SYMS | HAS_LOCALS | WP_TEXT),
2439
2440   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2441   0,                            /* leading char */
2442   '/',                          /* ar_pad_char */
2443   15,                           /* ar_max_namelen??? FIXMEmgo */
2444
2445   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2446   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2447   bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
2448
2449   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
2450   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
2451   bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
2452
2453   {_bfd_dummy_target, coff_object_p,    /* bfd_check_format */
2454      bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
2455   {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
2456      bfd_false},
2457   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
2458      _bfd_write_archive_contents, bfd_false},
2459
2460   BFD_JUMP_TABLE_GENERIC (coff),
2461   BFD_JUMP_TABLE_COPY (coff),
2462   BFD_JUMP_TABLE_CORE (_bfd_nocore),
2463   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
2464   BFD_JUMP_TABLE_SYMBOLS (coff),
2465   BFD_JUMP_TABLE_RELOCS (coff),
2466   BFD_JUMP_TABLE_WRITE (coff),
2467   BFD_JUMP_TABLE_LINK (coff),
2468   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
2469
2470   COFF_SWAP_TABLE,
2471 };
2472
2473 #endif