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