* libbfd.c (bfd_read): Set bfd_error as appropriate for a short
[external/binutils.git] / bfd / hp300hpux.c
1 /* BFD backend for hp-ux 9000/300
2    Copyright (C) 1990, 1991, 1994 Free Software Foundation, Inc.
3    Written by Glenn Engel.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22
23     hpux native  ------------> |               |
24                                | hp300hpux bfd | ----------> hpux w/gnu ext
25     hpux w/gnu extension ----> |               |
26
27
28     Support for the 9000/[34]00 has several limitations.
29       1. Shared libraries are not supported.
30       2. The output format from this bfd is not usable by native tools.
31
32     The primary motivation for writing this bfd was to allow use of
33     gdb and gcc for host based debugging and not to mimic the hp-ux tools
34     in every detail.  This leads to a significant simplification of the
35     code and a leap in performance.  The decision to not output hp native
36     compatible objects was further strengthened by the fact that the richness
37     of the gcc compiled objects could not be represented without loss of
38     information.  For example, while the hp format supports the concept of
39     secondary symbols, it does not support indirect symbols.  Another
40     reason is to maintain backwards compatibility with older implementations
41     of gcc on hpux which used 'hpxt' to translate .a and .o files into a
42     format which could be readily understood by the gnu linker and gdb.
43     This allows reading hp secondary symbols and converting them into
44     indirect symbols but the reverse it not always possible.
45
46     Another example of differences is that the hp format stores symbol offsets
47     in the object code while the gnu utilities use a field in the
48     relocation record for this.  To support the hp native format, the object
49     code would need to be patched with the offsets when producing .o files.
50
51     The basic technique taken in this implementation is to #include the code
52     from aoutx.h and aout-target.h with appropriate #defines to override
53     code where a unique implementation is needed:
54
55     {
56         #define a bunch of stuff
57         #include <aoutx.h>
58
59         implement a bunch of functions
60
61         #include "aout-target.h"
62     }
63
64     The hp symbol table is a bit different than other a.out targets.  Instead
65     of having an array of nlist items and an array of strings, hp's format
66     has them mixed together in one structure.  In addition, the strings are
67     not null terminated.  It looks something like this:
68
69     nlist element 1
70     string1
71     nlist element 2
72     string2
73     ...
74
75     The whole symbol table is read as one chunk and then we march thru it
76     and convert it to canonical form.  As we march thru the table, we copy
77     the nlist data into the internal form and we compact the strings and null
78     terminate them, using storage from the already allocated symbol table:
79
80     string1
81     null
82     string2
83     null
84  */
85
86 /* @@ Is this really so different from normal a.out that it needs to include
87    aoutx.h?  We should go through this file sometime and see what can be made
88    more dependent on aout32.o and what might need to be broken off and accessed
89    through the backend_data field.  Or, maybe we really do need such a
90    completely separate implementation.  I don't have time to investigate this
91    much further right now.  [raeburn:19930428.2124EST] */
92 /* @@ Also, note that there wind up being two versions of some routines, with
93    different names, only one of which actually gets used.  For example:
94         slurp_symbol_table
95         swap_std_reloc_in
96         slurp_reloc_table
97         get_symtab
98         get_symtab_upper_bound
99         canonicalize_reloc
100         mkobject
101    This should also be fixed.  */
102
103 #define ARCH 32
104 #define TARGETNAME "a.out-hp300hpux"
105 #define MY(OP) CAT(hp300hpux_,OP)
106
107 #define external_exec hp300hpux_exec_bytes
108 #define external_nlist hp300hpux_nlist_bytes
109
110 #include "aout/hp300hpux.h"
111
112 /* define these so we can compile unused routines in aoutx.h */
113 #define e_strx  e_shlib
114 #define e_other e_length
115 #define e_desc  e_almod
116
117 #define AR_PAD_CHAR '/'
118 #define TARGET_IS_BIG_ENDIAN_P
119 #define DEFAULT_ARCH bfd_arch_m68k
120
121 #define MY_get_section_contents aout_32_get_section_contents
122 #define MY_close_and_cleanup aout_32_close_and_cleanup
123 #define MY_slurp_armap bfd_slurp_bsd_armap_f2
124
125 /***********************************************/
126 /* provide overrides for routines in this file */
127 /***********************************************/
128 /* these don't use MY because that causes problems within JUMP_TABLE
129    (CAT winds up being expanded recursively, which ANSI C compilers
130    will not do).  */
131 #define MY_get_symtab hp300hpux_get_symtab
132 #define MY_get_symtab_upper_bound hp300hpux_get_symtab_upper_bound
133 #define MY_canonicalize_reloc hp300hpux_canonicalize_reloc
134 #define MY_write_object_contents hp300hpux_write_object_contents
135
136 #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
137 #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
138 #define MY_bfd_final_link _bfd_generic_final_link
139
140 #define hp300hpux_write_syms aout_32_write_syms
141
142 #define MY_callback MY(callback)
143
144 #define NAME_swap_exec_header_in NAME(hp300hpux_32_,swap_exec_header_in)
145
146 #define HP_SYMTYPE_UNDEFINED    0x00
147 #define HP_SYMTYPE_ABSOLUTE     0x01
148 #define HP_SYMTYPE_TEXT         0x02
149 #define HP_SYMTYPE_DATA         0x03
150 #define HP_SYMTYPE_BSS          0x04
151 #define HP_SYMTYPE_COMMON       0x05
152
153 #define HP_SYMTYPE_TYPE         0x0F
154 #define HP_SYMTYPE_FILENAME     0x1F
155
156 #define HP_SYMTYPE_ALIGN        0x10
157 #define HP_SYMTYPE_EXTERNAL     0x20
158 #define HP_SECONDARY_SYMBOL     0x40
159
160 /* RELOCATION DEFINITIONS */
161 #define HP_RSEGMENT_TEXT        0x00
162 #define HP_RSEGMENT_DATA        0x01
163 #define HP_RSEGMENT_BSS         0x02
164 #define HP_RSEGMENT_EXTERNAL    0x03
165 #define HP_RSEGMENT_PCREL       0x04
166 #define HP_RSEGMENT_RDLT        0x05
167 #define HP_RSEGMENT_RPLT        0x06
168 #define HP_RSEGMENT_NOOP        0x3F
169
170 #define HP_RLENGTH_BYTE         0x00
171 #define HP_RLENGTH_WORD         0x01
172 #define HP_RLENGTH_LONG         0x02
173 #define HP_RLENGTH_ALIGN        0x03
174
175 #define NAME(x,y) CAT3(hp300hpux,_32_,y)
176 #define ARCH_SIZE 32
177 #include "aoutx.h"
178
179 /* Since the hpux symbol table has nlist elements interspersed with
180    strings and we need to insert som strings for secondary symbols, we
181    give ourselves a little extra padding up front to account for
182    this.  Note that for each non-secondary symbol we process, we gain
183    9 bytes of space for the discarded nlist element (one byte used for
184    null).  SYM_EXTRA_BYTES is the extra space.  */
185 #define SYM_EXTRA_BYTES   1024
186
187 /* Set parameters about this a.out file that are machine-dependent.
188    This routine is called from some_aout_object_p just before it returns.  */
189 static bfd_target *
190 MY (callback) (abfd)
191      bfd *abfd;
192 {
193   struct internal_exec *execp = exec_hdr (abfd);
194
195   /* Calculate the file positions of the parts of a newly read aout header */
196   obj_textsec (abfd)->_raw_size = N_TXTSIZE (*execp);
197
198   /* The virtual memory addresses of the sections */
199   obj_textsec (abfd)->vma = N_TXTADDR (*execp);
200   obj_datasec (abfd)->vma = N_DATADDR (*execp);
201   obj_bsssec (abfd)->vma = N_BSSADDR (*execp);
202
203   /* The file offsets of the sections */
204   obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
205   obj_datasec (abfd)->filepos = N_DATOFF (*execp);
206
207   /* The file offsets of the relocation info */
208   obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
209   obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);
210
211   /* The file offsets of the string table and symbol table.  */
212   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
213   obj_str_filepos (abfd) = N_STROFF (*execp);
214
215   /* Determine the architecture and machine type of the object file.  */
216 #ifdef SET_ARCH_MACH
217   SET_ARCH_MACH (abfd, *execp);
218 #else
219   bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0);
220 #endif
221
222
223   if (obj_aout_subformat (abfd) == gnu_encap_format)
224     {
225       /* The file offsets of the relocation info */
226       obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp);
227       obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp);
228
229       /* The file offsets of the string table and symbol table.  */
230       obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp);
231       obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms);
232
233       abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
234       bfd_get_symcount (abfd) = execp->a_syms / 12;
235       obj_symbol_entry_size (abfd) = 12;
236       obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
237     }
238
239   return abfd->xvec;
240 }
241
242 extern boolean aout_32_write_syms PARAMS ((bfd * abfd));
243
244 static boolean
245 MY (write_object_contents) (abfd)
246      bfd *abfd;
247 {
248   struct external_exec exec_bytes;
249   struct internal_exec *execp = exec_hdr (abfd);
250   bfd_size_type text_size;      /* dummy vars */
251   file_ptr text_end;
252
253   memset (&exec_bytes, 0, sizeof (exec_bytes));
254 #if CHOOSE_RELOC_SIZE
255   CHOOSE_RELOC_SIZE (abfd);
256 #else
257   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
258 #endif
259
260   if (adata (abfd).magic == undecided_magic)
261     NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
262   execp->a_syms = 0;
263
264   execp->a_entry = bfd_get_start_address (abfd);
265
266   execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
267                      obj_reloc_entry_size (abfd));
268   execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
269                      obj_reloc_entry_size (abfd));
270
271   N_SET_MACHTYPE (*execp, 0xc);
272   N_SET_FLAGS (*execp, 0x2);
273
274   NAME (aout, swap_exec_header_out) (abfd, execp, &exec_bytes);
275
276   /* update fields not covered by default swap_exec_header_out */
277
278   /* this is really the sym table size but we store it in drelocs */
279   bfd_h_put_32 (abfd, bfd_get_symcount (abfd) * 12, exec_bytes.e_drelocs);
280
281   bfd_seek (abfd, 0L, false);
282   bfd_write ((PTR) & exec_bytes, 1, EXEC_BYTES_SIZE, abfd);
283
284   /* Write out the symbols, and then the relocs.  We must write out
285        the symbols first so that we know the symbol indices.  */
286
287   if (bfd_get_symcount (abfd) != 0)
288     {
289       /* Skip the relocs to where we want to put the symbols.  */
290       if (bfd_seek (abfd, (file_ptr) N_DRELOFF (*execp) + execp->a_drsize,
291                     SEEK_SET) != 0)
292         return false;
293     }
294
295   if (!MY (write_syms) (abfd))
296     return false;
297
298   if (bfd_get_symcount (abfd) != 0)
299     {
300       bfd_seek (abfd, (long) (N_TRELOFF (*execp)), false);
301
302       if (!NAME (aout, squirt_out_relocs) (abfd, obj_textsec (abfd)))
303         return false;
304       bfd_seek (abfd, (long) (N_DRELOFF (*execp)), false);
305
306       if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))
307         return false;
308     }
309
310   return true;
311 }
312
313 /* convert the hp symbol type to be the same as aout64.h usage so we */
314 /* can piggyback routines in aoutx.h.                                */
315
316 static void
317 convert_sym_type (sym_pointer, cache_ptr, abfd)
318      struct external_nlist *sym_pointer;
319      aout_symbol_type *cache_ptr;
320      bfd *abfd;
321 {
322   int name_type;
323   int new_type;
324
325   name_type = (cache_ptr->type);
326   new_type = 0;
327
328   if ((name_type & HP_SYMTYPE_ALIGN) != 0)
329     {
330       /* iou_error ("aligned symbol encountered: %s", name);*/
331       name_type = 0;
332     }
333
334   if (name_type == HP_SYMTYPE_FILENAME)
335     new_type = N_FN;
336   else
337     {
338       switch (name_type & HP_SYMTYPE_TYPE)
339         {
340         case HP_SYMTYPE_UNDEFINED:
341           new_type = N_UNDF;
342           break;
343
344         case HP_SYMTYPE_ABSOLUTE:
345           new_type = N_ABS;
346           break;
347
348         case HP_SYMTYPE_TEXT:
349           new_type = N_TEXT;
350           break;
351
352         case HP_SYMTYPE_DATA:
353           new_type = N_DATA;
354           break;
355
356         case HP_SYMTYPE_BSS:
357           new_type = N_BSS;
358           break;
359
360         case HP_SYMTYPE_COMMON:
361           new_type = N_COMM;
362           break;
363
364         default:
365           fprintf (stderr, "unknown symbol type encountered: %x", name_type);
366         }
367       if (name_type & HP_SYMTYPE_EXTERNAL)
368         new_type |= N_EXT;
369
370       if (name_type & HP_SECONDARY_SYMBOL)
371         new_type = (new_type & ~N_TYPE) | N_INDR;
372     }
373   cache_ptr->type = new_type;
374
375 }
376
377
378 /*
379 DESCRIPTION
380         Swaps the information in an executable header taken from a raw
381         byte stream memory image, into the internal exec_header
382         structure.
383 */
384
385 void
386   NAME (aout, swap_exec_header_in) (abfd, raw_bytes, execp)
387      bfd *abfd;
388      struct external_exec *raw_bytes;
389      struct internal_exec *execp;
390 {
391   struct external_exec *bytes = (struct external_exec *) raw_bytes;
392
393   /* The internal_exec structure has some fields that are unused in this
394      configuration (IE for i960), so ensure that all such uninitialized
395      fields are zero'd out.  There are places where two of these structs
396      are memcmp'd, and thus the contents do matter. */
397   memset (execp, 0, sizeof (struct internal_exec));
398   /* Now fill in fields in the execp, from the bytes in the raw data.  */
399   execp->a_info = bfd_h_get_32 (abfd, bytes->e_info);
400   execp->a_text = GET_WORD (abfd, bytes->e_text);
401   execp->a_data = GET_WORD (abfd, bytes->e_data);
402   execp->a_bss = GET_WORD (abfd, bytes->e_bss);
403   execp->a_syms = GET_WORD (abfd, bytes->e_syms);
404   execp->a_entry = GET_WORD (abfd, bytes->e_entry);
405   execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
406   execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
407
408   /***************************************************************/
409   /* check the header to see if it was generated by a bfd output */
410   /* this is detected rather bizarely by requiring a bunch of    */
411   /* header fields to be zero and an old unused field (now used) */
412   /* to be set.                                                  */
413   /***************************************************************/
414   do
415     {
416       long syms;
417       struct aout_data_struct *rawptr;
418       if (bfd_h_get_32 (abfd, bytes->e_passize) != 0)
419         break;
420       if (bfd_h_get_32 (abfd, bytes->e_syms) != 0)
421         break;
422       if (bfd_h_get_32 (abfd, bytes->e_supsize) != 0)
423         break;
424
425       syms = bfd_h_get_32 (abfd, bytes->e_drelocs);
426       if (syms == 0)
427         break;
428
429       /* OK, we've passed the test as best as we can determine */
430       execp->a_syms = syms;
431
432       /* allocate storage for where we will store this result */
433       rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (*rawptr));
434
435       if (rawptr == NULL)
436         {
437           bfd_set_error (bfd_error_no_memory);
438           return;
439         }
440       abfd->tdata.aout_data = rawptr;
441       obj_aout_subformat (abfd) = gnu_encap_format;
442     }
443   while (0);
444 }
445
446
447 /* The hp symbol table is a bit different than other a.out targets.  Instead
448    of having an array of nlist items and an array of strings, hp's format
449    has them mixed together in one structure.  In addition, the strings are
450    not null terminated.  It looks something like this:
451
452    nlist element 1
453    string1
454    nlist element 2
455    string2
456    ...
457
458    The whole symbol table is read as one chunk and then we march thru it
459    and convert it to canonical form.  As we march thru the table, we copy
460    the nlist data into the internal form and we compact the strings and null
461    terminate them, using storage from the already allocated symbol table:
462
463    string1
464    null
465    string2
466    null
467    ...
468 */
469
470 boolean
471 MY (slurp_symbol_table) (abfd)
472      bfd *abfd;
473 {
474   bfd_size_type symbol_bytes;
475   struct external_nlist *syms;
476   struct external_nlist *sym_pointer;
477   struct external_nlist *sym_end;
478   char *strings;
479   aout_symbol_type *cached;
480   unsigned num_syms = 0;
481   unsigned num_secondary = 0;
482
483   /* If there's no work to be done, don't do any */
484   if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
485     return true;
486   symbol_bytes = exec_hdr (abfd)->a_syms;
487   if (symbol_bytes == 0)
488     {
489       bfd_set_error (bfd_error_no_symbols);
490       return false;
491     }
492
493   strings = (char *) bfd_alloc (abfd,
494                                 symbol_bytes + SYM_EXTRA_BYTES);
495   if (!strings)
496     {
497       bfd_set_error (bfd_error_no_memory);
498       return false;
499     }
500   syms = (struct external_nlist *) (strings + SYM_EXTRA_BYTES);
501   bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
502   if (bfd_read ((PTR) syms, symbol_bytes, 1, abfd) != symbol_bytes)
503     {
504       bfd_release (abfd, syms);
505       return false;
506     }
507
508
509   sym_end = (struct external_nlist *) (((char *) syms) + symbol_bytes);
510
511   /* first, march thru the table and figure out how many symbols there are */
512   for (sym_pointer = syms; sym_pointer < sym_end; sym_pointer++, num_syms++)
513     {
514       if (bfd_get_8 (abfd, sym_pointer->e_type) & HP_SECONDARY_SYMBOL)
515         num_secondary++;
516       /* skip over the embedded symbol. */
517       sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
518                                                sym_pointer->e_length[0]);
519     }
520
521   /* now that we know the symbol count, update the bfd header */
522   bfd_get_symcount (abfd) = num_syms + num_secondary;
523
524   cached = (aout_symbol_type *)
525     bfd_zalloc (abfd, (bfd_size_type) (bfd_get_symcount (abfd) *
526                                        sizeof (aout_symbol_type)));
527   if (!cached)
528     {
529       bfd_set_error (bfd_error_no_memory);
530       return false;
531     }
532
533   /* as we march thru the hp symbol table, convert it into a list of
534      null terminated strings to hold the symbol names.  Make sure any
535      assignment to the strings pointer is done after we're thru using
536      the nlist so we don't overwrite anything important. */
537   num_secondary = 0;
538
539   /* OK, now walk the new symtable, cacheing symbol properties */
540   {
541     aout_symbol_type *cache_ptr = cached;
542     aout_symbol_type cache_save;
543     /* Run through table and copy values */
544     for (sym_pointer = syms, cache_ptr = cached;
545          sym_pointer < sym_end; sym_pointer++, cache_ptr++)
546       {
547         unsigned int length;
548         cache_ptr->symbol.the_bfd = abfd;
549         cache_ptr->symbol.value = GET_SWORD (abfd, sym_pointer->e_value);
550         cache_ptr->desc = bfd_get_16 (abfd, sym_pointer->e_almod);
551         cache_ptr->type = bfd_get_8 (abfd, sym_pointer->e_type);
552         cache_ptr->symbol.udata = 0;
553         length = bfd_get_8 (abfd, sym_pointer->e_length);
554         cache_ptr->other = length;      /* other not used, save length here */
555
556         cache_save = *cache_ptr;
557         convert_sym_type (sym_pointer, cache_ptr, abfd);
558         if (!translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd))
559           return false;
560
561         /********************************************************/
562         /* for hpux, the 'lenght' value indicates the length of */
563         /* the symbol name which follows the nlist entry.       */
564         /********************************************************/
565         if (length)
566           {
567             /**************************************************************/
568             /* the hp string is not null terminated so we create a new one*/
569             /* by copying the string to overlap the just vacated nlist    */
570             /* structure before it in memory.                             */
571             /**************************************************************/
572             cache_ptr->symbol.name = strings;
573             memcpy (strings, sym_pointer + 1, length);
574             strings[length] = '\0';
575             strings += length + 1;
576           }
577         else
578           cache_ptr->symbol.name = (char *) NULL;
579
580         /**********************************************************/
581         /* this is a bit of a kludge, but a secondary hp symbol   */
582         /* gets translated into a gnu indirect symbol.  When this */
583         /* happens, we need to create a "dummy" record to which   */
584         /* we can point the indirect symbol to.                   */
585         /**********************************************************/
586         if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT))
587           {
588             aout_symbol_type *cache_ptr2 = cached + num_syms + num_secondary;
589
590             num_secondary++;
591
592             /* aoutx.h assumes the "next" value is the indirect sym  */
593             /* since we don't want to disturb the order by inserting */
594             /* a new symbol, we tack on the created secondary syms   */
595             /* at the end.                                           */
596             cache_ptr->symbol.value = (bfd_vma) (cache_ptr2);
597             *cache_ptr2 = cache_save;
598             cache_ptr2->symbol.name = strings;
599             memcpy (strings, cache_ptr->symbol.name, length);
600             strcpy (strings + length, ":secondry");     /* 9 max chars + null */
601             strings += length + 10;
602             cache_ptr2->type &= ~HP_SECONDARY_SYMBOL;   /* clear secondary */
603             convert_sym_type (sym_pointer, cache_ptr2, abfd);
604             if (!translate_from_native_sym_flags (sym_pointer, cache_ptr2,
605                                                   abfd))
606               return false;
607           }
608
609         /* skip over the embedded symbol. */
610         sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
611                                                  length);
612       }
613   }
614
615   obj_aout_symbols (abfd) = cached;
616
617   return true;
618 }
619
620
621
622 void
623 MY (swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols)
624      bfd *abfd;
625      struct hp300hpux_reloc *bytes;
626      arelent *cache_ptr;
627      asymbol **symbols;
628 {
629   int r_index;
630   int r_extern = 0;
631   unsigned int r_length;
632   int r_pcrel = 0;
633   struct aoutdata *su = &(abfd->tdata.aout_data->a);
634
635   cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
636   r_index = bfd_h_get_16 (abfd, bytes->r_index);
637
638   switch (bytes->r_type[0])
639     {
640     case HP_RSEGMENT_TEXT:
641       r_index = N_TEXT;
642       break;
643     case HP_RSEGMENT_DATA:
644       r_index = N_DATA;
645       break;
646     case HP_RSEGMENT_BSS:
647       r_index = N_BSS;
648       break;
649     case HP_RSEGMENT_EXTERNAL:
650       r_extern = 1;
651       break;
652     case HP_RSEGMENT_PCREL:
653       r_extern = 1;
654       r_pcrel = 1;
655       break;
656     case HP_RSEGMENT_RDLT:
657       break;
658     case HP_RSEGMENT_RPLT:
659       break;
660     case HP_RSEGMENT_NOOP:
661       break;
662     default:
663       fprintf (stderr, "illegal relocation segment type: %x\n",
664                (bytes->r_type[0]));
665     }
666
667   switch (bytes->r_length[0])
668     {
669     case HP_RLENGTH_BYTE:
670       r_length = 0;
671       break;
672     case HP_RLENGTH_WORD:
673       r_length = 1;
674       break;
675     case HP_RLENGTH_LONG:
676       r_length = 2;
677       break;
678     default:
679       fprintf (stderr, "illegal relocation length: %x\n", bytes->r_length[0]);
680       r_length = 0;
681     }
682
683   cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
684   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
685
686   /* This macro uses the r_index value computed above */
687   if (r_pcrel && r_extern)
688     {
689       /* The GNU linker assumes any offset from beginning of section */
690       /* is already incorporated into the image while the HP linker  */
691       /* adds this in later.  Add it in now...                       */
692       MOVE_ADDRESS (-cache_ptr->address);
693     }
694   else
695     {
696       MOVE_ADDRESS (0);
697     }
698 }
699
700 boolean
701 MY (slurp_reloc_table) (abfd, asect, symbols)
702      bfd *abfd;
703      sec_ptr asect;
704      asymbol **symbols;
705 {
706   unsigned int count;
707   bfd_size_type reloc_size;
708   PTR relocs;
709   arelent *reloc_cache;
710   size_t each_size;
711   struct hp300hpux_reloc *rptr;
712   unsigned int counter;
713   arelent *cache_ptr;
714
715   if (asect->relocation)
716     return true;
717
718   if (asect->flags & SEC_CONSTRUCTOR)
719     return true;
720
721   if (asect == obj_datasec (abfd))
722     {
723       reloc_size = exec_hdr (abfd)->a_drsize;
724       goto doit;
725     }
726
727   if (asect == obj_textsec (abfd))
728     {
729       reloc_size = exec_hdr (abfd)->a_trsize;
730       goto doit;
731     }
732
733   bfd_set_error (bfd_error_invalid_operation);
734   return false;
735
736 doit:
737   bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
738   each_size = obj_reloc_entry_size (abfd);
739
740   count = reloc_size / each_size;
741
742
743   reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t) (count * sizeof
744                                                         (arelent)));
745   if (!reloc_cache)
746     {
747     nomem:
748       bfd_set_error (bfd_error_no_memory);
749       return false;
750     }
751
752   relocs = (PTR) bfd_alloc (abfd, reloc_size);
753   if (!relocs)
754     {
755       bfd_release (abfd, reloc_cache);
756       goto nomem;
757     }
758
759   if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
760     {
761       bfd_release (abfd, relocs);
762       bfd_release (abfd, reloc_cache);
763       return false;
764     }
765
766   rptr = (struct hp300hpux_reloc *) relocs;
767   counter = 0;
768   cache_ptr = reloc_cache;
769
770   for (; counter < count; counter++, rptr++, cache_ptr++)
771     {
772       MY (swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols);
773     }
774
775
776   bfd_release (abfd, relocs);
777   asect->relocation = reloc_cache;
778   asect->reloc_count = count;
779   return true;
780 }
781
782
783 /************************************************************************/
784 /* The following functions are identical to functions in aoutx.h except */
785 /* they refer to MY(func) rather than NAME(aout,func) and they also     */
786 /* call aout_32 versions if the input file was generated by gcc         */
787 /************************************************************************/
788
789 unsigned int aout_32_get_symtab PARAMS ((bfd * abfd, asymbol ** location));
790 unsigned int aout_32_get_symtab_upper_bound PARAMS ((bfd * abfd));
791
792 unsigned int aout_32_canonicalize_reloc PARAMS ((bfd * abfd, sec_ptr section,
793                                                  arelent ** relptr,
794                                                  asymbol ** symbols));
795
796 unsigned int
797 MY (get_symtab) (abfd, location)
798      bfd *abfd;
799      asymbol **location;
800 {
801   unsigned int counter = 0;
802   aout_symbol_type *symbase;
803
804   if (obj_aout_subformat (abfd) == gnu_encap_format)
805     return aout_32_get_symtab (abfd, location);
806
807   if (!MY (slurp_symbol_table) (abfd))
808     return 0;
809
810   for (symbase = obj_aout_symbols (abfd); counter++ < bfd_get_symcount (abfd);)
811     *(location++) = (asymbol *) (symbase++);
812   *location++ = 0;
813   return bfd_get_symcount (abfd);
814 }
815
816 unsigned int
817 MY (get_symtab_upper_bound) (abfd)
818      bfd *abfd;
819 {
820   if (obj_aout_subformat (abfd) == gnu_encap_format)
821     return aout_32_get_symtab_upper_bound (abfd);
822   if (!MY (slurp_symbol_table) (abfd))
823     return 0;
824
825   return (bfd_get_symcount (abfd) + 1) * (sizeof (aout_symbol_type *));
826 }
827
828
829
830
831 unsigned int
832 MY (canonicalize_reloc) (abfd, section, relptr, symbols)
833      bfd *abfd;
834      sec_ptr section;
835      arelent **relptr;
836      asymbol **symbols;
837 {
838   arelent *tblptr = section->relocation;
839   unsigned int count;
840   if (obj_aout_subformat (abfd) == gnu_encap_format)
841     return aout_32_canonicalize_reloc (abfd, section, relptr, symbols);
842
843   if (!(tblptr || MY (slurp_reloc_table) (abfd, section, symbols)))
844     return 0;
845
846   if (section->flags & SEC_CONSTRUCTOR)
847     {
848       arelent_chain *chain = section->constructor_chain;
849       for (count = 0; count < section->reloc_count; count++)
850         {
851           *relptr++ = &chain->relent;
852           chain = chain->next;
853         }
854     }
855   else
856     {
857       tblptr = section->relocation;
858       if (!tblptr)
859         return 0;
860
861       for (count = 0; count++ < section->reloc_count;)
862         {
863           *relptr++ = tblptr++;
864         }
865     }
866   *relptr = 0;
867
868   return section->reloc_count;
869 }
870
871
872 #include "aout-target.h"