xref: /openbsd-src/gnu/usr.bin/binutils/bfd/m68klinux.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
1c88b1d6cSniklas /* BFD back-end for linux flavored m68k a.out binaries.
2c074d1c9Sdrahn    Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003
3f7cc78ecSespie    Free Software Foundation, Inc.
4c88b1d6cSniklas 
5c88b1d6cSniklas This file is part of BFD, the Binary File Descriptor library.
6c88b1d6cSniklas 
7c88b1d6cSniklas This program is free software; you can redistribute it and/or modify
8c88b1d6cSniklas it under the terms of the GNU General Public License as published by
9c88b1d6cSniklas the Free Software Foundation; either version 2 of the License, or
10c88b1d6cSniklas (at your option) any later version.
11c88b1d6cSniklas 
12c88b1d6cSniklas This program is distributed in the hope that it will be useful,
13c88b1d6cSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
14c88b1d6cSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c88b1d6cSniklas GNU General Public License for more details.
16c88b1d6cSniklas 
17c88b1d6cSniklas You should have received a copy of the GNU General Public License
18c88b1d6cSniklas along with this program; if not, write to the Free Software
19c88b1d6cSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20c88b1d6cSniklas 
21c88b1d6cSniklas #define	TARGET_PAGE_SIZE 4096
22c88b1d6cSniklas #define ZMAGIC_DISK_BLOCK_SIZE 1024
23c88b1d6cSniklas #define	SEGMENT_SIZE TARGET_PAGE_SIZE
24c88b1d6cSniklas #define TEXT_START_ADDR	0x0
25c88b1d6cSniklas #define N_SHARED_LIB(x) 0
26c88b1d6cSniklas 
27fddef416Sniklas #define MACHTYPE_OK(mtype) ((mtype) == M_68020 || (mtype) == M_UNKNOWN)
28fddef416Sniklas 
29c88b1d6cSniklas #include "bfd.h"
30c88b1d6cSniklas #include "sysdep.h"
31c88b1d6cSniklas #include "libbfd.h"
32c88b1d6cSniklas #include "aout/aout64.h"
33c88b1d6cSniklas #include "aout/stab_gnu.h"
34c88b1d6cSniklas #include "aout/ar.h"
35c88b1d6cSniklas #include "libaout.h"           /* BFD a.out internal data structures */
36c88b1d6cSniklas 
37c88b1d6cSniklas #define TARGET_IS_BIG_ENDIAN_P
38c88b1d6cSniklas #define DEFAULT_ARCH bfd_arch_m68k
39c074d1c9Sdrahn 
40c074d1c9Sdrahn /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
41c074d1c9Sdrahn    remove whitespace added here, and thus will fail to concatenate
42c074d1c9Sdrahn    the tokens.  */
43c074d1c9Sdrahn #define MY(OP) CONCAT2 (m68klinux_,OP)
44c88b1d6cSniklas #define TARGETNAME "a.out-m68k-linux"
45c88b1d6cSniklas 
46c88b1d6cSniklas extern const bfd_target MY(vec);
47c88b1d6cSniklas 
48c88b1d6cSniklas /* We always generate QMAGIC files in preference to ZMAGIC files.  It
49c88b1d6cSniklas    would be possible to make this a linker option, if that ever
50c88b1d6cSniklas    becomes important.  */
51c88b1d6cSniklas 
52c88b1d6cSniklas static void MY_final_link_callback
53c88b1d6cSniklas   PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
54c074d1c9Sdrahn static bfd_boolean m68klinux_bfd_final_link
55fddef416Sniklas   PARAMS ((bfd *, struct bfd_link_info *));
56c074d1c9Sdrahn static bfd_boolean m68klinux_write_object_contents PARAMS ((bfd *));
57c88b1d6cSniklas 
58c074d1c9Sdrahn static bfd_boolean
m68klinux_bfd_final_link(abfd,info)59c88b1d6cSniklas m68klinux_bfd_final_link (abfd, info)
60c88b1d6cSniklas      bfd *abfd;
61c88b1d6cSniklas      struct bfd_link_info *info;
62c88b1d6cSniklas {
63c88b1d6cSniklas   obj_aout_subformat (abfd) = q_magic_format;
64c88b1d6cSniklas   return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
65c88b1d6cSniklas }
66c88b1d6cSniklas 
67c88b1d6cSniklas #define MY_bfd_final_link m68klinux_bfd_final_link
68c88b1d6cSniklas 
69c88b1d6cSniklas /* Set the machine type correctly.  */
70c88b1d6cSniklas 
71c074d1c9Sdrahn static bfd_boolean
m68klinux_write_object_contents(abfd)72c88b1d6cSniklas m68klinux_write_object_contents (abfd)
73c88b1d6cSniklas      bfd *abfd;
74c88b1d6cSniklas {
75c88b1d6cSniklas   struct external_exec exec_bytes;
76c88b1d6cSniklas   struct internal_exec *execp = exec_hdr (abfd);
77c88b1d6cSniklas 
78c88b1d6cSniklas   N_SET_MACHTYPE (*execp, M_68020);
79c88b1d6cSniklas 
80c88b1d6cSniklas   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
81c88b1d6cSniklas 
82c88b1d6cSniklas   WRITE_HEADERS(abfd, execp);
83c88b1d6cSniklas 
84c074d1c9Sdrahn   return TRUE;
85c88b1d6cSniklas }
86c88b1d6cSniklas 
87c88b1d6cSniklas #define MY_write_object_contents m68klinux_write_object_contents
88c88b1d6cSniklas 
89c88b1d6cSniklas /* Code to link against Linux a.out shared libraries.  */
90c88b1d6cSniklas 
91c88b1d6cSniklas /* See if a symbol name is a reference to the global offset table.  */
92c88b1d6cSniklas 
93c88b1d6cSniklas #ifndef GOT_REF_PREFIX
94c88b1d6cSniklas #define	GOT_REF_PREFIX	"__GOT_"
95c88b1d6cSniklas #endif
96c88b1d6cSniklas 
97c88b1d6cSniklas #define IS_GOT_SYM(name) \
98c88b1d6cSniklas   (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0)
99c88b1d6cSniklas 
100c88b1d6cSniklas /* See if a symbol name is a reference to the procedure linkage table.  */
101c88b1d6cSniklas 
102c88b1d6cSniklas #ifndef PLT_REF_PREFIX
103c88b1d6cSniklas #define	PLT_REF_PREFIX	"__PLT_"
104c88b1d6cSniklas #endif
105c88b1d6cSniklas 
106c88b1d6cSniklas #define IS_PLT_SYM(name) \
107c88b1d6cSniklas   (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0)
108c88b1d6cSniklas 
109c88b1d6cSniklas /* This string is used to generate specialized error messages.  */
110c88b1d6cSniklas 
111c88b1d6cSniklas #ifndef NEEDS_SHRLIB
112c88b1d6cSniklas #define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
113c88b1d6cSniklas #endif
114c88b1d6cSniklas 
115c88b1d6cSniklas /* This special symbol is a set vector that contains a list of
116*007c2a45Smiod    pointers to fixup tables.  It will be present in any dynamically
117c88b1d6cSniklas    linked file.  The linker generated fixup table should also be added
118c88b1d6cSniklas    to the list, and it should always appear in the second slot (the
119c88b1d6cSniklas    first one is a dummy with a magic number that is defined in
120c88b1d6cSniklas    crt0.o).  */
121c88b1d6cSniklas 
122c88b1d6cSniklas #ifndef SHARABLE_CONFLICTS
123c88b1d6cSniklas #define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
124c88b1d6cSniklas #endif
125c88b1d6cSniklas 
126c88b1d6cSniklas /* We keep a list of fixups.  The terminology is a bit strange, but
127c88b1d6cSniklas    each fixup contains two 32 bit numbers.  A regular fixup contains
128c88b1d6cSniklas    an address and a pointer, and at runtime we should store the
129c88b1d6cSniklas    address at the location pointed to by the pointer.  A builtin fixup
130c88b1d6cSniklas    contains two pointers, and we should read the address using one
131c88b1d6cSniklas    pointer and store it at the location pointed to by the other
132c88b1d6cSniklas    pointer.  Builtin fixups come into play when we have duplicate
133c88b1d6cSniklas    __GOT__ symbols for the same variable.  The builtin fixup will copy
134c88b1d6cSniklas    the GOT pointer from one over into the other.  */
135c88b1d6cSniklas 
136c88b1d6cSniklas struct fixup
137c88b1d6cSniklas {
138c88b1d6cSniklas   struct fixup *next;
139c88b1d6cSniklas   struct linux_link_hash_entry *h;
140c88b1d6cSniklas   bfd_vma value;
141c88b1d6cSniklas 
142c88b1d6cSniklas   /* Nonzero if this is a jump instruction that needs to be fixed,
143c88b1d6cSniklas      zero if this is just a pointer */
144c88b1d6cSniklas   char jump;
145c88b1d6cSniklas 
146c88b1d6cSniklas   char builtin;
147c88b1d6cSniklas };
148c88b1d6cSniklas 
149c88b1d6cSniklas /* We don't need a special hash table entry structure, but we do need
150c88b1d6cSniklas    to keep some information between linker passes, so we use a special
151c88b1d6cSniklas    hash table.  */
152c88b1d6cSniklas 
153c88b1d6cSniklas struct linux_link_hash_entry
154c88b1d6cSniklas {
155c88b1d6cSniklas   struct aout_link_hash_entry root;
156c88b1d6cSniklas };
157c88b1d6cSniklas 
158c88b1d6cSniklas struct linux_link_hash_table
159c88b1d6cSniklas {
160c88b1d6cSniklas   struct aout_link_hash_table root;
161c88b1d6cSniklas 
162c88b1d6cSniklas   /* First dynamic object found in link.  */
163c88b1d6cSniklas   bfd *dynobj;
164c88b1d6cSniklas 
165c88b1d6cSniklas   /* Number of fixups.  */
166c88b1d6cSniklas   size_t fixup_count;
167c88b1d6cSniklas 
168c88b1d6cSniklas   /* Number of builtin fixups.  */
169c88b1d6cSniklas   size_t local_builtins;
170c88b1d6cSniklas 
171c88b1d6cSniklas   /* List of fixups.  */
172c88b1d6cSniklas   struct fixup *fixup_list;
173c88b1d6cSniklas };
174c88b1d6cSniklas 
175c88b1d6cSniklas static struct bfd_hash_entry *linux_link_hash_newfunc
176c88b1d6cSniklas   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
177c88b1d6cSniklas static struct bfd_link_hash_table *linux_link_hash_table_create
178c88b1d6cSniklas   PARAMS ((bfd *));
179c88b1d6cSniklas static struct fixup *new_fixup
180c88b1d6cSniklas   PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
181c88b1d6cSniklas 	   bfd_vma, int));
182c074d1c9Sdrahn static bfd_boolean linux_link_create_dynamic_sections
183c88b1d6cSniklas   PARAMS ((bfd *, struct bfd_link_info *));
184c074d1c9Sdrahn static bfd_boolean linux_add_one_symbol
185c88b1d6cSniklas   PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
186c074d1c9Sdrahn 	   bfd_vma, const char *, bfd_boolean, bfd_boolean,
187c88b1d6cSniklas 	   struct bfd_link_hash_entry **));
188c074d1c9Sdrahn static bfd_boolean linux_tally_symbols
189c88b1d6cSniklas   PARAMS ((struct linux_link_hash_entry *, PTR));
190c074d1c9Sdrahn static bfd_boolean linux_finish_dynamic_link
191c88b1d6cSniklas   PARAMS ((bfd *, struct bfd_link_info *));
192c88b1d6cSniklas 
193c88b1d6cSniklas /* Routine to create an entry in an Linux link hash table.  */
194c88b1d6cSniklas 
195c88b1d6cSniklas static struct bfd_hash_entry *
linux_link_hash_newfunc(entry,table,string)196c88b1d6cSniklas linux_link_hash_newfunc (entry, table, string)
197c88b1d6cSniklas      struct bfd_hash_entry *entry;
198c88b1d6cSniklas      struct bfd_hash_table *table;
199c88b1d6cSniklas      const char *string;
200c88b1d6cSniklas {
201c88b1d6cSniklas   struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
202c88b1d6cSniklas 
203c88b1d6cSniklas   /* Allocate the structure if it has not already been allocated by a
204c88b1d6cSniklas      subclass.  */
205c88b1d6cSniklas   if (ret == (struct linux_link_hash_entry *) NULL)
206c88b1d6cSniklas     ret = ((struct linux_link_hash_entry *)
207c88b1d6cSniklas 	   bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
208c88b1d6cSniklas   if (ret == NULL)
209c88b1d6cSniklas     return (struct bfd_hash_entry *) ret;
210c88b1d6cSniklas 
211c88b1d6cSniklas   /* Call the allocation method of the superclass.  */
212c88b1d6cSniklas   ret = ((struct linux_link_hash_entry *)
213c88b1d6cSniklas 	 NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
214c88b1d6cSniklas 				       table, string));
215c88b1d6cSniklas   if (ret != NULL)
216c88b1d6cSniklas     {
217c88b1d6cSniklas       /* Set local fields; there aren't any.  */
218c88b1d6cSniklas     }
219c88b1d6cSniklas 
220c88b1d6cSniklas   return (struct bfd_hash_entry *) ret;
221c88b1d6cSniklas }
222c88b1d6cSniklas 
223c88b1d6cSniklas /* Create a Linux link hash table.  */
224c88b1d6cSniklas 
225c88b1d6cSniklas static struct bfd_link_hash_table *
linux_link_hash_table_create(abfd)226c88b1d6cSniklas linux_link_hash_table_create (abfd)
227c88b1d6cSniklas      bfd *abfd;
228c88b1d6cSniklas {
229c88b1d6cSniklas   struct linux_link_hash_table *ret;
230c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct linux_link_hash_table);
231c88b1d6cSniklas 
232c074d1c9Sdrahn   ret = (struct linux_link_hash_table *) bfd_malloc (amt);
233c88b1d6cSniklas   if (ret == (struct linux_link_hash_table *) NULL)
234c88b1d6cSniklas     {
235c88b1d6cSniklas       bfd_set_error (bfd_error_no_memory);
236c88b1d6cSniklas       return (struct bfd_link_hash_table *) NULL;
237c88b1d6cSniklas     }
238c88b1d6cSniklas   if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
239c88b1d6cSniklas 					 linux_link_hash_newfunc))
240c88b1d6cSniklas     {
241c88b1d6cSniklas       free (ret);
242c88b1d6cSniklas       return (struct bfd_link_hash_table *) NULL;
243c88b1d6cSniklas     }
244c88b1d6cSniklas 
245c88b1d6cSniklas   ret->dynobj = NULL;
246c88b1d6cSniklas   ret->fixup_count = 0;
247c88b1d6cSniklas   ret->local_builtins = 0;
248c88b1d6cSniklas   ret->fixup_list = NULL;
249c88b1d6cSniklas 
250c88b1d6cSniklas   return &ret->root.root;
251c88b1d6cSniklas }
252c88b1d6cSniklas 
253c88b1d6cSniklas /* Look up an entry in a Linux link hash table.  */
254c88b1d6cSniklas 
255c88b1d6cSniklas #define linux_link_hash_lookup(table, string, create, copy, follow) \
256c88b1d6cSniklas   ((struct linux_link_hash_entry *) \
257c88b1d6cSniklas    aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
258c88b1d6cSniklas 			  (follow)))
259c88b1d6cSniklas 
260c88b1d6cSniklas /* Traverse a Linux link hash table.  */
261c88b1d6cSniklas 
262c88b1d6cSniklas #define linux_link_hash_traverse(table, func, info)			\
263c88b1d6cSniklas   (aout_link_hash_traverse						\
264c88b1d6cSniklas    (&(table)->root,							\
265c074d1c9Sdrahn     (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func),	\
266c88b1d6cSniklas     (info)))
267c88b1d6cSniklas 
268c88b1d6cSniklas /* Get the Linux link hash table from the info structure.  This is
269c88b1d6cSniklas    just a cast.  */
270c88b1d6cSniklas 
271c88b1d6cSniklas #define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
272c88b1d6cSniklas 
273c88b1d6cSniklas /* Store the information for a new fixup.  */
274c88b1d6cSniklas 
275c88b1d6cSniklas static struct fixup *
new_fixup(info,h,value,builtin)276c88b1d6cSniklas new_fixup (info, h, value, builtin)
277c88b1d6cSniklas      struct bfd_link_info *info;
278c88b1d6cSniklas      struct linux_link_hash_entry *h;
279c88b1d6cSniklas      bfd_vma value;
280c88b1d6cSniklas      int builtin;
281c88b1d6cSniklas {
282c88b1d6cSniklas   struct fixup *f;
283c88b1d6cSniklas 
284c88b1d6cSniklas   f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
285c88b1d6cSniklas 					  sizeof (struct fixup));
286c88b1d6cSniklas   if (f == NULL)
287c88b1d6cSniklas     return f;
288c88b1d6cSniklas   f->next = linux_hash_table (info)->fixup_list;
289c88b1d6cSniklas   linux_hash_table (info)->fixup_list = f;
290c88b1d6cSniklas   f->h = h;
291c88b1d6cSniklas   f->value = value;
292c88b1d6cSniklas   f->builtin = builtin;
293c88b1d6cSniklas   f->jump = 0;
294c88b1d6cSniklas   ++linux_hash_table (info)->fixup_count;
295c88b1d6cSniklas   return f;
296c88b1d6cSniklas }
297c88b1d6cSniklas 
298c88b1d6cSniklas /* We come here once we realize that we are going to link to a shared
299c88b1d6cSniklas    library.  We need to create a special section that contains the
300c88b1d6cSniklas    fixup table, and we ultimately need to add a pointer to this into
301c88b1d6cSniklas    the set vector for SHARABLE_CONFLICTS.  At this point we do not
302c88b1d6cSniklas    know the size of the section, but that's OK - we just need to
303c88b1d6cSniklas    create it for now.  */
304c88b1d6cSniklas 
305c074d1c9Sdrahn static bfd_boolean
linux_link_create_dynamic_sections(abfd,info)306c88b1d6cSniklas linux_link_create_dynamic_sections (abfd, info)
307c88b1d6cSniklas      bfd *abfd;
308f7cc78ecSespie      struct bfd_link_info *info ATTRIBUTE_UNUSED;
309c88b1d6cSniklas {
310c88b1d6cSniklas   flagword flags;
311c88b1d6cSniklas   register asection *s;
312c88b1d6cSniklas 
313c88b1d6cSniklas   /* Note that we set the SEC_IN_MEMORY flag.  */
314c88b1d6cSniklas   flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
315c88b1d6cSniklas 
316c88b1d6cSniklas   /* We choose to use the name ".linux-dynamic" for the fixup table.
317c88b1d6cSniklas      Why not? */
318c88b1d6cSniklas   s = bfd_make_section (abfd, ".linux-dynamic");
319c88b1d6cSniklas   if (s == NULL
320c88b1d6cSniklas       || ! bfd_set_section_flags (abfd, s, flags)
321c88b1d6cSniklas       || ! bfd_set_section_alignment (abfd, s, 2))
322c074d1c9Sdrahn     return FALSE;
323c88b1d6cSniklas   s->_raw_size = 0;
324c88b1d6cSniklas   s->contents = 0;
325c88b1d6cSniklas 
326c074d1c9Sdrahn   return TRUE;
327c88b1d6cSniklas }
328c88b1d6cSniklas 
329c88b1d6cSniklas /* Function to add a single symbol to the linker hash table.  This is
330c88b1d6cSniklas    a wrapper around _bfd_generic_link_add_one_symbol which handles the
331c88b1d6cSniklas    tweaking needed for dynamic linking support.  */
332c88b1d6cSniklas 
333c074d1c9Sdrahn static bfd_boolean
linux_add_one_symbol(info,abfd,name,flags,section,value,string,copy,collect,hashp)334c88b1d6cSniklas linux_add_one_symbol (info, abfd, name, flags, section, value, string,
335c88b1d6cSniklas 		      copy, collect, hashp)
336c88b1d6cSniklas      struct bfd_link_info *info;
337c88b1d6cSniklas      bfd *abfd;
338c88b1d6cSniklas      const char *name;
339c88b1d6cSniklas      flagword flags;
340c88b1d6cSniklas      asection *section;
341c88b1d6cSniklas      bfd_vma value;
342c88b1d6cSniklas      const char *string;
343c074d1c9Sdrahn      bfd_boolean copy;
344c074d1c9Sdrahn      bfd_boolean collect;
345c88b1d6cSniklas      struct bfd_link_hash_entry **hashp;
346c88b1d6cSniklas {
347c88b1d6cSniklas   struct linux_link_hash_entry *h;
348c074d1c9Sdrahn   bfd_boolean insert;
349c88b1d6cSniklas 
350c88b1d6cSniklas   /* Look up and see if we already have this symbol in the hash table.
351c88b1d6cSniklas      If we do, and the defining entry is from a shared library, we
352c88b1d6cSniklas      need to create the dynamic sections.
353c88b1d6cSniklas 
354c88b1d6cSniklas      FIXME: What if abfd->xvec != info->hash->creator?  We may want to
355c88b1d6cSniklas      be able to link Linux a.out and ELF objects together, but serious
356c88b1d6cSniklas      confusion is possible.  */
357c88b1d6cSniklas 
358c074d1c9Sdrahn   insert = FALSE;
359c88b1d6cSniklas 
360*007c2a45Smiod   if (! info->relocatable
361c88b1d6cSniklas       && linux_hash_table (info)->dynobj == NULL
362c88b1d6cSniklas       && strcmp (name, SHARABLE_CONFLICTS) == 0
363c88b1d6cSniklas       && (flags & BSF_CONSTRUCTOR) != 0
364c88b1d6cSniklas       && abfd->xvec == info->hash->creator)
365c88b1d6cSniklas     {
366c88b1d6cSniklas       if (! linux_link_create_dynamic_sections (abfd, info))
367c074d1c9Sdrahn 	return FALSE;
368c88b1d6cSniklas       linux_hash_table (info)->dynobj = abfd;
369c074d1c9Sdrahn       insert = TRUE;
370c88b1d6cSniklas     }
371c88b1d6cSniklas 
372c88b1d6cSniklas   if (bfd_is_abs_section (section)
373c88b1d6cSniklas       && abfd->xvec == info->hash->creator)
374c88b1d6cSniklas     {
375c074d1c9Sdrahn       h = linux_link_hash_lookup (linux_hash_table (info), name, FALSE,
376c074d1c9Sdrahn 				  FALSE, FALSE);
377c88b1d6cSniklas       if (h != NULL
378c88b1d6cSniklas 	  && (h->root.root.type == bfd_link_hash_defined
379c88b1d6cSniklas 	      || h->root.root.type == bfd_link_hash_defweak))
380c88b1d6cSniklas 	{
381c88b1d6cSniklas 	  struct fixup *f;
382c88b1d6cSniklas 
383c88b1d6cSniklas 	  if (hashp != NULL)
384c88b1d6cSniklas 	    *hashp = (struct bfd_link_hash_entry *) h;
385c88b1d6cSniklas 
386c88b1d6cSniklas 	  f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
387c88b1d6cSniklas 	  if (f == NULL)
388c074d1c9Sdrahn 	    return FALSE;
389c88b1d6cSniklas 	  f->jump = IS_PLT_SYM (name);
390c88b1d6cSniklas 
391c074d1c9Sdrahn 	  return TRUE;
392c88b1d6cSniklas 	}
393c88b1d6cSniklas     }
394c88b1d6cSniklas 
395c88b1d6cSniklas   /* Do the usual procedure for adding a symbol.  */
396c88b1d6cSniklas   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
397c88b1d6cSniklas 					  value, string, copy, collect,
398c88b1d6cSniklas 					  hashp))
399c074d1c9Sdrahn     return FALSE;
400c88b1d6cSniklas 
401c88b1d6cSniklas   /* Insert a pointer to our table in the set vector.  The dynamic
402c88b1d6cSniklas      linker requires this information */
403c88b1d6cSniklas   if (insert)
404c88b1d6cSniklas     {
405c88b1d6cSniklas       asection *s;
406c88b1d6cSniklas 
407c88b1d6cSniklas       /* Here we do our special thing to add the pointer to the
408c88b1d6cSniklas 	 dynamic section in the SHARABLE_CONFLICTS set vector.  */
409c88b1d6cSniklas       s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
410c88b1d6cSniklas 				   ".linux-dynamic");
411c88b1d6cSniklas       BFD_ASSERT (s != NULL);
412c88b1d6cSniklas 
413c88b1d6cSniklas       if (! (_bfd_generic_link_add_one_symbol
414c88b1d6cSniklas 	     (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
415c074d1c9Sdrahn 	      BSF_GLOBAL | BSF_CONSTRUCTOR, s, (bfd_vma) 0, NULL,
416c074d1c9Sdrahn 	      FALSE, FALSE, NULL)))
417c074d1c9Sdrahn 	return FALSE;
418c88b1d6cSniklas     }
419c88b1d6cSniklas 
420c074d1c9Sdrahn   return TRUE;
421c88b1d6cSniklas }
422c88b1d6cSniklas 
423c88b1d6cSniklas /* We will crawl the hash table and come here for every global symbol.
424c88b1d6cSniklas    We will examine each entry and see if there are indications that we
425c88b1d6cSniklas    need to add a fixup.  There are two possible cases - one is where
426c88b1d6cSniklas    you have duplicate definitions of PLT or GOT symbols - these will
427c88b1d6cSniklas    have already been caught and added as "builtin" fixups.  If we find
428c88b1d6cSniklas    that the corresponding non PLT/GOT symbol is also present, we
429c88b1d6cSniklas    convert it to a regular fixup instead.
430c88b1d6cSniklas 
431c88b1d6cSniklas    This function is called via linux_link_hash_traverse.  */
432c88b1d6cSniklas 
433c074d1c9Sdrahn static bfd_boolean
linux_tally_symbols(h,data)434c88b1d6cSniklas linux_tally_symbols (h, data)
435c88b1d6cSniklas      struct linux_link_hash_entry *h;
436c88b1d6cSniklas      PTR data;
437c88b1d6cSniklas {
438c88b1d6cSniklas   struct bfd_link_info *info = (struct bfd_link_info *) data;
439c88b1d6cSniklas   struct fixup *f, *f1;
440c88b1d6cSniklas   int is_plt;
441c88b1d6cSniklas   struct linux_link_hash_entry *h1, *h2;
442c074d1c9Sdrahn   bfd_boolean exists;
443c074d1c9Sdrahn 
444c074d1c9Sdrahn   if (h->root.root.type == bfd_link_hash_warning)
445c074d1c9Sdrahn     h = (struct linux_link_hash_entry *) h->root.root.u.i.link;
446c88b1d6cSniklas 
447c88b1d6cSniklas   if (h->root.root.type == bfd_link_hash_undefined
448c88b1d6cSniklas       && strncmp (h->root.root.root.string, NEEDS_SHRLIB,
449c88b1d6cSniklas 		  sizeof NEEDS_SHRLIB - 1) == 0)
450c88b1d6cSniklas     {
451c88b1d6cSniklas       const char *name;
452c88b1d6cSniklas       char *p;
453c88b1d6cSniklas       char *alloc = NULL;
454c88b1d6cSniklas 
455c88b1d6cSniklas       name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
456c88b1d6cSniklas       p = strrchr (name, '_');
457c88b1d6cSniklas       if (p != NULL)
458c074d1c9Sdrahn 	alloc = (char *) bfd_malloc ((bfd_size_type) strlen (name) + 1);
459c88b1d6cSniklas 
460c88b1d6cSniklas       if (p == NULL || alloc == NULL)
461f7cc78ecSespie 	(*_bfd_error_handler) (_("Output file requires shared library `%s'\n"),
462c88b1d6cSniklas 			       name);
463c88b1d6cSniklas       else
464c88b1d6cSniklas 	{
465c88b1d6cSniklas 	  strcpy (alloc, name);
466c88b1d6cSniklas 	  p = strrchr (alloc, '_');
467c88b1d6cSniklas 	  *p++ = '\0';
468c88b1d6cSniklas 	  (*_bfd_error_handler)
469f7cc78ecSespie 	    (_("Output file requires shared library `%s.so.%s'\n"),
470c88b1d6cSniklas 	     alloc, p);
471c88b1d6cSniklas 	  free (alloc);
472c88b1d6cSniklas 	}
473c88b1d6cSniklas 
474c88b1d6cSniklas       abort ();
475c88b1d6cSniklas     }
476c88b1d6cSniklas 
477c88b1d6cSniklas   /* If this symbol is not a PLT/GOT, we do not even need to look at it */
478c88b1d6cSniklas   is_plt = IS_PLT_SYM (h->root.root.root.string);
479c88b1d6cSniklas 
480c88b1d6cSniklas   if (is_plt || IS_GOT_SYM (h->root.root.root.string))
481c88b1d6cSniklas     {
482c88b1d6cSniklas       /* Look up this symbol twice.  Once just as a regular lookup,
483c88b1d6cSniklas 	 and then again following all of the indirect links until we
484c88b1d6cSniklas 	 reach a real symbol.  */
485c88b1d6cSniklas       h1 = linux_link_hash_lookup (linux_hash_table (info),
486c88b1d6cSniklas 				   (h->root.root.root.string
487c88b1d6cSniklas 				    + sizeof PLT_REF_PREFIX - 1),
488c074d1c9Sdrahn 				   FALSE, FALSE, TRUE);
489c88b1d6cSniklas       /* h2 does not follow indirect symbols.  */
490c88b1d6cSniklas       h2 = linux_link_hash_lookup (linux_hash_table (info),
491c88b1d6cSniklas 				   (h->root.root.root.string
492c88b1d6cSniklas 				    + sizeof PLT_REF_PREFIX - 1),
493c074d1c9Sdrahn 				   FALSE, FALSE, FALSE);
494c88b1d6cSniklas 
495c88b1d6cSniklas       /* The real symbol must exist but if it is also an ABS symbol,
496c88b1d6cSniklas 	 there is no need to have a fixup.  This is because they both
497c88b1d6cSniklas 	 came from the same library.  If on the other hand, we had to
498c88b1d6cSniklas 	 use an indirect symbol to get to the real symbol, we add the
499c88b1d6cSniklas 	 fixup anyway, since there are cases where these symbols come
500c88b1d6cSniklas 	 from different shared libraries */
501c88b1d6cSniklas       if (h1 != NULL
502c88b1d6cSniklas 	  && (((h1->root.root.type == bfd_link_hash_defined
503c88b1d6cSniklas 		|| h1->root.root.type == bfd_link_hash_defweak)
504c88b1d6cSniklas 	       && ! bfd_is_abs_section (h1->root.root.u.def.section))
505c88b1d6cSniklas 	      || h2->root.root.type == bfd_link_hash_indirect))
506c88b1d6cSniklas 	{
507c88b1d6cSniklas 	  /* See if there is a "builtin" fixup already present
508c88b1d6cSniklas 	     involving this symbol.  If so, convert it to a regular
509c88b1d6cSniklas 	     fixup.  In the end, this relaxes some of the requirements
510c88b1d6cSniklas 	     about the order of performing fixups.  */
511c074d1c9Sdrahn 	  exists = FALSE;
512c88b1d6cSniklas 	  for (f1 = linux_hash_table (info)->fixup_list;
513c88b1d6cSniklas 	       f1 != NULL;
514c88b1d6cSniklas 	       f1 = f1->next)
515c88b1d6cSniklas 	    {
516c88b1d6cSniklas 	      if ((f1->h != h && f1->h != h1)
517c88b1d6cSniklas 		  || (! f1->builtin && ! f1->jump))
518c88b1d6cSniklas 		continue;
519c88b1d6cSniklas 	      if (f1->h == h1)
520c074d1c9Sdrahn 		exists = TRUE;
521c88b1d6cSniklas 	      if (! exists
522c88b1d6cSniklas 		  && bfd_is_abs_section (h->root.root.u.def.section))
523c88b1d6cSniklas 		{
524c88b1d6cSniklas 		  f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
525c88b1d6cSniklas 		  f->jump = is_plt;
526c88b1d6cSniklas 		}
527c88b1d6cSniklas 	      f1->h = h1;
528c88b1d6cSniklas 	      f1->jump = is_plt;
529c88b1d6cSniklas 	      f1->builtin = 0;
530c074d1c9Sdrahn 	      exists = TRUE;
531c88b1d6cSniklas 	    }
532c88b1d6cSniklas 	  if (! exists
533c88b1d6cSniklas 	      && bfd_is_abs_section (h->root.root.u.def.section))
534c88b1d6cSniklas 	    {
535c88b1d6cSniklas 	      f = new_fixup (info, h1, h->root.root.u.def.value, 0);
536c88b1d6cSniklas 	      if (f == NULL)
537c88b1d6cSniklas 		{
538c88b1d6cSniklas 		  /* FIXME: No way to return error.  */
539c88b1d6cSniklas 		  abort ();
540c88b1d6cSniklas 		}
541c88b1d6cSniklas 	      f->jump = is_plt;
542c88b1d6cSniklas 	    }
543c88b1d6cSniklas 	}
544c88b1d6cSniklas 
545c88b1d6cSniklas       /* Quick and dirty way of stripping these symbols from the
546c88b1d6cSniklas 	 symtab.  */
547c88b1d6cSniklas       if (bfd_is_abs_section (h->root.root.u.def.section))
548c074d1c9Sdrahn 	h->root.written = TRUE;
549c88b1d6cSniklas     }
550c88b1d6cSniklas 
551c074d1c9Sdrahn   return TRUE;
552c88b1d6cSniklas }
553c88b1d6cSniklas 
554c88b1d6cSniklas /* This is called to set the size of the .linux-dynamic section is.
555c88b1d6cSniklas    It is called by the Linux linker emulation before_allocation
556c88b1d6cSniklas    routine.  We have finished reading all of the input files, and now
557c88b1d6cSniklas    we just scan the hash tables to find out how many additional fixups
558c88b1d6cSniklas    are required.  */
559c88b1d6cSniklas 
560c074d1c9Sdrahn bfd_boolean
bfd_m68klinux_size_dynamic_sections(output_bfd,info)561c88b1d6cSniklas bfd_m68klinux_size_dynamic_sections (output_bfd, info)
562c88b1d6cSniklas      bfd *output_bfd;
563c88b1d6cSniklas      struct bfd_link_info *info;
564c88b1d6cSniklas {
565c88b1d6cSniklas   struct fixup *f;
566c88b1d6cSniklas   asection *s;
567c88b1d6cSniklas 
568c88b1d6cSniklas   if (output_bfd->xvec != &MY(vec))
569c074d1c9Sdrahn     return TRUE;
570c88b1d6cSniklas 
571c88b1d6cSniklas   /* First find the fixups...  */
572c88b1d6cSniklas   linux_link_hash_traverse (linux_hash_table (info),
573c88b1d6cSniklas 			    linux_tally_symbols,
574c88b1d6cSniklas 			    (PTR) info);
575c88b1d6cSniklas 
576c88b1d6cSniklas   /* If there are builtin fixups, leave room for a marker.  This is
577c88b1d6cSniklas      used by the dynamic linker so that it knows that all that follow
578c88b1d6cSniklas      are builtin fixups instead of regular fixups.  */
579c88b1d6cSniklas   for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
580c88b1d6cSniklas     {
581c88b1d6cSniklas       if (f->builtin)
582c88b1d6cSniklas 	{
583c88b1d6cSniklas 	  ++linux_hash_table (info)->fixup_count;
584c88b1d6cSniklas 	  ++linux_hash_table (info)->local_builtins;
585c88b1d6cSniklas 	  break;
586c88b1d6cSniklas 	}
587c88b1d6cSniklas     }
588c88b1d6cSniklas 
589c88b1d6cSniklas   if (linux_hash_table (info)->dynobj == NULL)
590c88b1d6cSniklas     {
591c88b1d6cSniklas       if (linux_hash_table (info)->fixup_count > 0)
592c88b1d6cSniklas 	abort ();
593c074d1c9Sdrahn       return TRUE;
594c88b1d6cSniklas     }
595c88b1d6cSniklas 
596c88b1d6cSniklas   /* Allocate memory for our fixup table.  We will fill it in later.  */
597c88b1d6cSniklas   s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
598c88b1d6cSniklas 			       ".linux-dynamic");
599c88b1d6cSniklas   if (s != NULL)
600c88b1d6cSniklas     {
601c074d1c9Sdrahn       s->_raw_size = linux_hash_table (info)->fixup_count + 1;
602c074d1c9Sdrahn       s->_raw_size *= 8;
603c074d1c9Sdrahn       s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size);
604c88b1d6cSniklas       if (s->contents == NULL)
605c88b1d6cSniklas 	{
606c88b1d6cSniklas 	  bfd_set_error (bfd_error_no_memory);
607c074d1c9Sdrahn 	  return FALSE;
608c88b1d6cSniklas 	}
609c88b1d6cSniklas     }
610c88b1d6cSniklas 
611c074d1c9Sdrahn   return TRUE;
612c88b1d6cSniklas }
613c88b1d6cSniklas 
614c88b1d6cSniklas /* We come here once we are ready to actually write the fixup table to
615c88b1d6cSniklas    the output file.  Scan the fixup tables and so forth and generate
616c88b1d6cSniklas    the stuff we need.  */
617c88b1d6cSniklas 
618c074d1c9Sdrahn static bfd_boolean
linux_finish_dynamic_link(output_bfd,info)619c88b1d6cSniklas linux_finish_dynamic_link (output_bfd, info)
620c88b1d6cSniklas      bfd *output_bfd;
621c88b1d6cSniklas      struct bfd_link_info *info;
622c88b1d6cSniklas {
623c88b1d6cSniklas   asection *s, *os, *is;
624c88b1d6cSniklas   bfd_byte *fixup_table;
625c88b1d6cSniklas   struct linux_link_hash_entry *h;
626c88b1d6cSniklas   struct fixup *f;
627c88b1d6cSniklas   unsigned int new_addr;
628c88b1d6cSniklas   int section_offset;
629c88b1d6cSniklas   unsigned int fixups_written;
630c88b1d6cSniklas 
631c88b1d6cSniklas   if (linux_hash_table (info)->dynobj == NULL)
632c074d1c9Sdrahn     return TRUE;
633c88b1d6cSniklas 
634c88b1d6cSniklas   s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
635c88b1d6cSniklas 			       ".linux-dynamic");
636c88b1d6cSniklas   BFD_ASSERT (s != NULL);
637c88b1d6cSniklas   os = s->output_section;
638c88b1d6cSniklas   fixups_written = 0;
639c88b1d6cSniklas 
640c88b1d6cSniklas #ifdef LINUX_LINK_DEBUG
641c88b1d6cSniklas   printf ("Fixup table file offset: %x  VMA: %x\n",
642c88b1d6cSniklas 	  os->filepos + s->output_offset,
643c88b1d6cSniklas 	  os->vma + s->output_offset);
644c88b1d6cSniklas #endif
645c88b1d6cSniklas 
646c88b1d6cSniklas   fixup_table = s->contents;
647c074d1c9Sdrahn   bfd_put_32 (output_bfd, (bfd_vma) linux_hash_table (info)->fixup_count,
648c074d1c9Sdrahn 	      fixup_table);
649c88b1d6cSniklas   fixup_table += 4;
650c88b1d6cSniklas 
651c88b1d6cSniklas   /* Fill in fixup table.  */
652c88b1d6cSniklas   for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
653c88b1d6cSniklas     {
654c88b1d6cSniklas       if (f->builtin)
655c88b1d6cSniklas 	continue;
656c88b1d6cSniklas 
657c88b1d6cSniklas       if (f->h->root.root.type != bfd_link_hash_defined
658c88b1d6cSniklas 	  && f->h->root.root.type != bfd_link_hash_defweak)
659c88b1d6cSniklas 	{
660c88b1d6cSniklas 	  (*_bfd_error_handler)
661f7cc78ecSespie 	    (_("Symbol %s not defined for fixups\n"),
662c88b1d6cSniklas 	     f->h->root.root.root.string);
663c88b1d6cSniklas 	  continue;
664c88b1d6cSniklas 	}
665c88b1d6cSniklas 
666c88b1d6cSniklas       is = f->h->root.root.u.def.section;
667c88b1d6cSniklas       section_offset = is->output_section->vma + is->output_offset;
668c88b1d6cSniklas       new_addr = f->h->root.root.u.def.value + section_offset;
669c88b1d6cSniklas 
670c88b1d6cSniklas #ifdef LINUX_LINK_DEBUG
671c88b1d6cSniklas       printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
672c88b1d6cSniklas 	      new_addr, f->value);
673c88b1d6cSniklas #endif
674c88b1d6cSniklas 
675c88b1d6cSniklas       if (f->jump)
676c88b1d6cSniklas 	{
677c074d1c9Sdrahn 	  bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
678c88b1d6cSniklas 	  fixup_table += 4;
679c88b1d6cSniklas 	  bfd_put_32 (output_bfd, f->value + 2, fixup_table);
680c88b1d6cSniklas 	  fixup_table += 4;
681c88b1d6cSniklas 	}
682c88b1d6cSniklas       else
683c88b1d6cSniklas 	{
684c074d1c9Sdrahn 	  bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
685c88b1d6cSniklas 	  fixup_table += 4;
686c88b1d6cSniklas 	  bfd_put_32 (output_bfd, f->value, fixup_table);
687c88b1d6cSniklas 	  fixup_table += 4;
688c88b1d6cSniklas 	}
689c88b1d6cSniklas       ++fixups_written;
690c88b1d6cSniklas     }
691c88b1d6cSniklas 
692c88b1d6cSniklas   if (linux_hash_table (info)->local_builtins != 0)
693c88b1d6cSniklas     {
694c88b1d6cSniklas       /* Special marker so we know to switch to the other type of fixup */
695c074d1c9Sdrahn       bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
696c88b1d6cSniklas       fixup_table += 4;
697c074d1c9Sdrahn       bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
698c88b1d6cSniklas       fixup_table += 4;
699c88b1d6cSniklas       ++fixups_written;
700c88b1d6cSniklas       for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
701c88b1d6cSniklas 	{
702c88b1d6cSniklas 	  if (! f->builtin)
703c88b1d6cSniklas 	    continue;
704c88b1d6cSniklas 
705c88b1d6cSniklas 	  if (f->h->root.root.type != bfd_link_hash_defined
706c88b1d6cSniklas 	      && f->h->root.root.type != bfd_link_hash_defweak)
707c88b1d6cSniklas 	    {
708c88b1d6cSniklas 	      (*_bfd_error_handler)
709f7cc78ecSespie 		(_("Symbol %s not defined for fixups\n"),
710c88b1d6cSniklas 		 f->h->root.root.root.string);
711c88b1d6cSniklas 	      continue;
712c88b1d6cSniklas 	    }
713c88b1d6cSniklas 
714c88b1d6cSniklas 	  is = f->h->root.root.u.def.section;
715c88b1d6cSniklas 	  section_offset = is->output_section->vma + is->output_offset;
716c88b1d6cSniklas 	  new_addr = f->h->root.root.u.def.value + section_offset;
717c88b1d6cSniklas 
718c88b1d6cSniklas #ifdef LINUX_LINK_DEBUG
719c88b1d6cSniklas 	  printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
720c88b1d6cSniklas 		  new_addr, f->value);
721c88b1d6cSniklas #endif
722c88b1d6cSniklas 
723c074d1c9Sdrahn 	  bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
724c88b1d6cSniklas 	  fixup_table += 4;
725c88b1d6cSniklas 	  bfd_put_32 (output_bfd, f->value, fixup_table);
726c88b1d6cSniklas 	  fixup_table += 4;
727c88b1d6cSniklas 	  ++fixups_written;
728c88b1d6cSniklas 	}
729c88b1d6cSniklas   }
730c88b1d6cSniklas 
731c88b1d6cSniklas   if (linux_hash_table (info)->fixup_count != fixups_written)
732c88b1d6cSniklas     {
733f7cc78ecSespie       (*_bfd_error_handler) (_("Warning: fixup count mismatch\n"));
734c88b1d6cSniklas       while (linux_hash_table (info)->fixup_count > fixups_written)
735c88b1d6cSniklas 	{
736c074d1c9Sdrahn 	  bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
737c88b1d6cSniklas 	  fixup_table += 4;
738c074d1c9Sdrahn 	  bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
739c88b1d6cSniklas 	  fixup_table += 4;
740c88b1d6cSniklas 	  ++fixups_written;
741c88b1d6cSniklas 	}
742c88b1d6cSniklas     }
743c88b1d6cSniklas 
744c88b1d6cSniklas   h = linux_link_hash_lookup (linux_hash_table (info),
745c88b1d6cSniklas 			      "__BUILTIN_FIXUPS__",
746c074d1c9Sdrahn 			      FALSE, FALSE, FALSE);
747c88b1d6cSniklas 
748c88b1d6cSniklas   if (h != NULL
749c88b1d6cSniklas       && (h->root.root.type == bfd_link_hash_defined
750c88b1d6cSniklas 	  || h->root.root.type == bfd_link_hash_defweak))
751c88b1d6cSniklas     {
752c88b1d6cSniklas       is = h->root.root.u.def.section;
753c88b1d6cSniklas       section_offset = is->output_section->vma + is->output_offset;
754c88b1d6cSniklas       new_addr = h->root.root.u.def.value + section_offset;
755c88b1d6cSniklas 
756c88b1d6cSniklas #ifdef LINUX_LINK_DEBUG
757c88b1d6cSniklas       printf ("Builtin fixup table at %x\n", new_addr);
758c88b1d6cSniklas #endif
759c88b1d6cSniklas 
760c074d1c9Sdrahn       bfd_put_32 (output_bfd, (bfd_vma) new_addr, fixup_table);
761c88b1d6cSniklas     }
762c88b1d6cSniklas   else
763c074d1c9Sdrahn     bfd_put_32 (output_bfd, (bfd_vma) 0, fixup_table);
764c88b1d6cSniklas 
765c074d1c9Sdrahn   if (bfd_seek (output_bfd, (file_ptr) (os->filepos + s->output_offset),
766c074d1c9Sdrahn 		SEEK_SET) != 0)
767c074d1c9Sdrahn     return FALSE;
768c88b1d6cSniklas 
769c074d1c9Sdrahn   if (bfd_bwrite ((PTR) s->contents, s->_raw_size, output_bfd) != s->_raw_size)
770c074d1c9Sdrahn     return FALSE;
771c88b1d6cSniklas 
772c074d1c9Sdrahn   return TRUE;
773c88b1d6cSniklas }
774c88b1d6cSniklas 
775c88b1d6cSniklas #define MY_bfd_link_hash_table_create linux_link_hash_table_create
776c88b1d6cSniklas #define MY_add_one_symbol linux_add_one_symbol
777c88b1d6cSniklas #define MY_finish_dynamic_link linux_finish_dynamic_link
778c88b1d6cSniklas 
779c88b1d6cSniklas #define MY_zmagic_contiguous 1
780c88b1d6cSniklas 
781c88b1d6cSniklas #include "aout-target.h"
782