1179404Sobrien/* MIPS-specific support for ELF
2179404Sobrien   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3218822Sdim   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4179404Sobrien
5179404Sobrien   Most of the information added by Ian Lance Taylor, Cygnus Support,
6179404Sobrien   <ian@cygnus.com>.
7179404Sobrien   N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC.
8179404Sobrien   <mark@codesourcery.com>
9179404Sobrien   Traditional MIPS targets support added by Koundinya.K, Dansk Data
10179404Sobrien   Elektronik & Operations Research Group. <kk@ddeorg.soft.net>
11179404Sobrien
12179404Sobrien   This file is part of BFD, the Binary File Descriptor library.
13179404Sobrien
14179404Sobrien   This program is free software; you can redistribute it and/or modify
15179404Sobrien   it under the terms of the GNU General Public License as published by
16179404Sobrien   the Free Software Foundation; either version 2 of the License, or
17179404Sobrien   (at your option) any later version.
18179404Sobrien
19179404Sobrien   This program is distributed in the hope that it will be useful,
20179404Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
21179404Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22179404Sobrien   GNU General Public License for more details.
23179404Sobrien
24179404Sobrien   You should have received a copy of the GNU General Public License
25179404Sobrien   along with this program; if not, write to the Free Software
26208737Sjmallett   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
27179404Sobrien
28179404Sobrien/* This file handles functionality common to the different MIPS ABI's.  */
29179404Sobrien
30218822Sdim#include "sysdep.h"
31179404Sobrien#include "bfd.h"
32179404Sobrien#include "libbfd.h"
33179404Sobrien#include "libiberty.h"
34179404Sobrien#include "elf-bfd.h"
35179404Sobrien#include "elfxx-mips.h"
36179404Sobrien#include "elf/mips.h"
37218822Sdim#include "elf-vxworks.h"
38179404Sobrien
39179404Sobrien/* Get the ECOFF swapping routines.  */
40179404Sobrien#include "coff/sym.h"
41179404Sobrien#include "coff/symconst.h"
42179404Sobrien#include "coff/ecoff.h"
43179404Sobrien#include "coff/mips.h"
44179404Sobrien
45179404Sobrien#include "hashtab.h"
46179404Sobrien
47218822Sdim/* This structure is used to hold information about one GOT entry.
48218822Sdim   There are three types of entry:
49218822Sdim
50218822Sdim      (1) absolute addresses
51218822Sdim	    (abfd == NULL)
52218822Sdim      (2) SYMBOL + OFFSET addresses, where SYMBOL is local to an input bfd
53218822Sdim	    (abfd != NULL, symndx >= 0)
54218822Sdim      (3) global and forced-local symbols
55218822Sdim	    (abfd != NULL, symndx == -1)
56218822Sdim
57218822Sdim   Type (3) entries are treated differently for different types of GOT.
58218822Sdim   In the "master" GOT -- i.e.  the one that describes every GOT
59218822Sdim   reference needed in the link -- the mips_got_entry is keyed on both
60218822Sdim   the symbol and the input bfd that references it.  If it turns out
61218822Sdim   that we need multiple GOTs, we can then use this information to
62218822Sdim   create separate GOTs for each input bfd.
63218822Sdim
64218822Sdim   However, we want each of these separate GOTs to have at most one
65218822Sdim   entry for a given symbol, so their type (3) entries are keyed only
66218822Sdim   on the symbol.  The input bfd given by the "abfd" field is somewhat
67218822Sdim   arbitrary in this case.
68218822Sdim
69218822Sdim   This means that when there are multiple GOTs, each GOT has a unique
70218822Sdim   mips_got_entry for every symbol within it.  We can therefore use the
71218822Sdim   mips_got_entry fields (tls_type and gotidx) to track the symbol's
72218822Sdim   GOT index.
73218822Sdim
74218822Sdim   However, if it turns out that we need only a single GOT, we continue
75218822Sdim   to use the master GOT to describe it.  There may therefore be several
76218822Sdim   mips_got_entries for the same symbol, each with a different input bfd.
77218822Sdim   We want to make sure that each symbol gets a unique GOT entry, so when
78218822Sdim   there's a single GOT, we use the symbol's hash entry, not the
79218822Sdim   mips_got_entry fields, to track a symbol's GOT index.  */
80179404Sobrienstruct mips_got_entry
81179404Sobrien{
82179404Sobrien  /* The input bfd in which the symbol is defined.  */
83179404Sobrien  bfd *abfd;
84179404Sobrien  /* The index of the symbol, as stored in the relocation r_info, if
85179404Sobrien     we have a local symbol; -1 otherwise.  */
86179404Sobrien  long symndx;
87179404Sobrien  union
88179404Sobrien  {
89179404Sobrien    /* If abfd == NULL, an address that must be stored in the got.  */
90179404Sobrien    bfd_vma address;
91179404Sobrien    /* If abfd != NULL && symndx != -1, the addend of the relocation
92179404Sobrien       that should be added to the symbol value.  */
93179404Sobrien    bfd_vma addend;
94179404Sobrien    /* If abfd != NULL && symndx == -1, the hash table entry
95179404Sobrien       corresponding to a global symbol in the got (or, local, if
96179404Sobrien       h->forced_local).  */
97179404Sobrien    struct mips_elf_link_hash_entry *h;
98179404Sobrien  } d;
99218822Sdim
100218822Sdim  /* The TLS types included in this GOT entry (specifically, GD and
101218822Sdim     IE).  The GD and IE flags can be added as we encounter new
102218822Sdim     relocations.  LDM can also be set; it will always be alone, not
103218822Sdim     combined with any GD or IE flags.  An LDM GOT entry will be
104218822Sdim     a local symbol entry with r_symndx == 0.  */
105218822Sdim  unsigned char tls_type;
106218822Sdim
107179404Sobrien  /* The offset from the beginning of the .got section to the entry
108179404Sobrien     corresponding to this symbol+addend.  If it's a global symbol
109179404Sobrien     whose offset is yet to be decided, it's going to be -1.  */
110179404Sobrien  long gotidx;
111179404Sobrien};
112179404Sobrien
113179404Sobrien/* This structure is used to hold .got information when linking.  */
114179404Sobrien
115179404Sobrienstruct mips_got_info
116179404Sobrien{
117179404Sobrien  /* The global symbol in the GOT with the lowest index in the dynamic
118179404Sobrien     symbol table.  */
119179404Sobrien  struct elf_link_hash_entry *global_gotsym;
120179404Sobrien  /* The number of global .got entries.  */
121179404Sobrien  unsigned int global_gotno;
122218822Sdim  /* The number of .got slots used for TLS.  */
123218822Sdim  unsigned int tls_gotno;
124218822Sdim  /* The first unused TLS .got entry.  Used only during
125218822Sdim     mips_elf_initialize_tls_index.  */
126218822Sdim  unsigned int tls_assigned_gotno;
127179404Sobrien  /* The number of local .got entries.  */
128179404Sobrien  unsigned int local_gotno;
129179404Sobrien  /* The number of local .got entries we have used.  */
130179404Sobrien  unsigned int assigned_gotno;
131179404Sobrien  /* A hash table holding members of the got.  */
132179404Sobrien  struct htab *got_entries;
133179404Sobrien  /* A hash table mapping input bfds to other mips_got_info.  NULL
134179404Sobrien     unless multi-got was necessary.  */
135179404Sobrien  struct htab *bfd2got;
136179404Sobrien  /* In multi-got links, a pointer to the next got (err, rather, most
137179404Sobrien     of the time, it points to the previous got).  */
138179404Sobrien  struct mips_got_info *next;
139218822Sdim  /* This is the GOT index of the TLS LDM entry for the GOT, MINUS_ONE
140218822Sdim     for none, or MINUS_TWO for not yet assigned.  This is needed
141218822Sdim     because a single-GOT link may have multiple hash table entries
142218822Sdim     for the LDM.  It does not get initialized in multi-GOT mode.  */
143218822Sdim  bfd_vma tls_ldm_offset;
144179404Sobrien};
145179404Sobrien
146179404Sobrien/* Map an input bfd to a got in a multi-got link.  */
147179404Sobrien
148179404Sobrienstruct mips_elf_bfd2got_hash {
149179404Sobrien  bfd *bfd;
150179404Sobrien  struct mips_got_info *g;
151179404Sobrien};
152179404Sobrien
153179404Sobrien/* Structure passed when traversing the bfd2got hash table, used to
154179404Sobrien   create and merge bfd's gots.  */
155179404Sobrien
156179404Sobrienstruct mips_elf_got_per_bfd_arg
157179404Sobrien{
158179404Sobrien  /* A hashtable that maps bfds to gots.  */
159179404Sobrien  htab_t bfd2got;
160179404Sobrien  /* The output bfd.  */
161179404Sobrien  bfd *obfd;
162179404Sobrien  /* The link information.  */
163179404Sobrien  struct bfd_link_info *info;
164179404Sobrien  /* A pointer to the primary got, i.e., the one that's going to get
165179404Sobrien     the implicit relocations from DT_MIPS_LOCAL_GOTNO and
166179404Sobrien     DT_MIPS_GOTSYM.  */
167179404Sobrien  struct mips_got_info *primary;
168179404Sobrien  /* A non-primary got we're trying to merge with other input bfd's
169179404Sobrien     gots.  */
170179404Sobrien  struct mips_got_info *current;
171179404Sobrien  /* The maximum number of got entries that can be addressed with a
172179404Sobrien     16-bit offset.  */
173179404Sobrien  unsigned int max_count;
174179404Sobrien  /* The number of local and global entries in the primary got.  */
175179404Sobrien  unsigned int primary_count;
176179404Sobrien  /* The number of local and global entries in the current got.  */
177179404Sobrien  unsigned int current_count;
178218822Sdim  /* The total number of global entries which will live in the
179218822Sdim     primary got and be automatically relocated.  This includes
180218822Sdim     those not referenced by the primary GOT but included in
181218822Sdim     the "master" GOT.  */
182218822Sdim  unsigned int global_count;
183179404Sobrien};
184179404Sobrien
185179404Sobrien/* Another structure used to pass arguments for got entries traversal.  */
186179404Sobrien
187179404Sobrienstruct mips_elf_set_global_got_offset_arg
188179404Sobrien{
189179404Sobrien  struct mips_got_info *g;
190179404Sobrien  int value;
191179404Sobrien  unsigned int needed_relocs;
192179404Sobrien  struct bfd_link_info *info;
193179404Sobrien};
194179404Sobrien
195218822Sdim/* A structure used to count TLS relocations or GOT entries, for GOT
196218822Sdim   entry or ELF symbol table traversal.  */
197218822Sdim
198218822Sdimstruct mips_elf_count_tls_arg
199218822Sdim{
200218822Sdim  struct bfd_link_info *info;
201218822Sdim  unsigned int needed;
202218822Sdim};
203218822Sdim
204179404Sobrienstruct _mips_elf_section_data
205179404Sobrien{
206179404Sobrien  struct bfd_elf_section_data elf;
207179404Sobrien  union
208179404Sobrien  {
209179404Sobrien    struct mips_got_info *got_info;
210179404Sobrien    bfd_byte *tdata;
211179404Sobrien  } u;
212179404Sobrien};
213179404Sobrien
214179404Sobrien#define mips_elf_section_data(sec) \
215179404Sobrien  ((struct _mips_elf_section_data *) elf_section_data (sec))
216179404Sobrien
217179404Sobrien/* This structure is passed to mips_elf_sort_hash_table_f when sorting
218179404Sobrien   the dynamic symbols.  */
219179404Sobrien
220179404Sobrienstruct mips_elf_hash_sort_data
221179404Sobrien{
222179404Sobrien  /* The symbol in the global GOT with the lowest dynamic symbol table
223179404Sobrien     index.  */
224179404Sobrien  struct elf_link_hash_entry *low;
225218822Sdim  /* The least dynamic symbol table index corresponding to a non-TLS
226218822Sdim     symbol with a GOT entry.  */
227179404Sobrien  long min_got_dynindx;
228179404Sobrien  /* The greatest dynamic symbol table index corresponding to a symbol
229179404Sobrien     with a GOT entry that is not referenced (e.g., a dynamic symbol
230179404Sobrien     with dynamic relocations pointing to it from non-primary GOTs).  */
231179404Sobrien  long max_unref_got_dynindx;
232179404Sobrien  /* The greatest dynamic symbol table index not corresponding to a
233179404Sobrien     symbol without a GOT entry.  */
234179404Sobrien  long max_non_got_dynindx;
235179404Sobrien};
236179404Sobrien
237179404Sobrien/* The MIPS ELF linker needs additional information for each symbol in
238179404Sobrien   the global hash table.  */
239179404Sobrien
240179404Sobrienstruct mips_elf_link_hash_entry
241179404Sobrien{
242179404Sobrien  struct elf_link_hash_entry root;
243179404Sobrien
244179404Sobrien  /* External symbol information.  */
245179404Sobrien  EXTR esym;
246179404Sobrien
247179404Sobrien  /* Number of R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 relocs against
248179404Sobrien     this symbol.  */
249179404Sobrien  unsigned int possibly_dynamic_relocs;
250179404Sobrien
251179404Sobrien  /* If the R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 reloc is against
252179404Sobrien     a readonly section.  */
253179404Sobrien  bfd_boolean readonly_reloc;
254179404Sobrien
255179404Sobrien  /* We must not create a stub for a symbol that has relocations
256179404Sobrien     related to taking the function's address, i.e. any but
257179404Sobrien     R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
258179404Sobrien     p. 4-20.  */
259179404Sobrien  bfd_boolean no_fn_stub;
260179404Sobrien
261179404Sobrien  /* If there is a stub that 32 bit functions should use to call this
262179404Sobrien     16 bit function, this points to the section containing the stub.  */
263179404Sobrien  asection *fn_stub;
264179404Sobrien
265179404Sobrien  /* Whether we need the fn_stub; this is set if this symbol appears
266179404Sobrien     in any relocs other than a 16 bit call.  */
267179404Sobrien  bfd_boolean need_fn_stub;
268179404Sobrien
269179404Sobrien  /* If there is a stub that 16 bit functions should use to call this
270179404Sobrien     32 bit function, this points to the section containing the stub.  */
271179404Sobrien  asection *call_stub;
272179404Sobrien
273179404Sobrien  /* This is like the call_stub field, but it is used if the function
274179404Sobrien     being called returns a floating point value.  */
275179404Sobrien  asection *call_fp_stub;
276179404Sobrien
277218822Sdim  /* Are we forced local?  This will only be set if we have converted
278218822Sdim     the initial global GOT entry to a local GOT entry.  */
279179404Sobrien  bfd_boolean forced_local;
280218822Sdim
281218822Sdim  /* Are we referenced by some kind of relocation?  */
282218822Sdim  bfd_boolean is_relocation_target;
283218822Sdim
284218822Sdim  /* Are we referenced by branch relocations?  */
285218822Sdim  bfd_boolean is_branch_target;
286218822Sdim
287218822Sdim#define GOT_NORMAL	0
288218822Sdim#define GOT_TLS_GD	1
289218822Sdim#define GOT_TLS_LDM	2
290218822Sdim#define GOT_TLS_IE	4
291218822Sdim#define GOT_TLS_OFFSET_DONE    0x40
292218822Sdim#define GOT_TLS_DONE    0x80
293218822Sdim  unsigned char tls_type;
294218822Sdim  /* This is only used in single-GOT mode; in multi-GOT mode there
295218822Sdim     is one mips_got_entry per GOT entry, so the offset is stored
296218822Sdim     there.  In single-GOT mode there may be many mips_got_entry
297218822Sdim     structures all referring to the same GOT slot.  It might be
298218822Sdim     possible to use root.got.offset instead, but that field is
299218822Sdim     overloaded already.  */
300218822Sdim  bfd_vma tls_got_offset;
301179404Sobrien};
302179404Sobrien
303179404Sobrien/* MIPS ELF linker hash table.  */
304179404Sobrien
305179404Sobrienstruct mips_elf_link_hash_table
306179404Sobrien{
307179404Sobrien  struct elf_link_hash_table root;
308179404Sobrien#if 0
309179404Sobrien  /* We no longer use this.  */
310179404Sobrien  /* String section indices for the dynamic section symbols.  */
311179404Sobrien  bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
312179404Sobrien#endif
313179404Sobrien  /* The number of .rtproc entries.  */
314179404Sobrien  bfd_size_type procedure_count;
315179404Sobrien  /* The size of the .compact_rel section (if SGI_COMPAT).  */
316179404Sobrien  bfd_size_type compact_rel_size;
317179404Sobrien  /* This flag indicates that the value of DT_MIPS_RLD_MAP dynamic
318179404Sobrien     entry is set to the address of __rld_obj_head as in IRIX5.  */
319179404Sobrien  bfd_boolean use_rld_obj_head;
320179404Sobrien  /* This is the value of the __rld_map or __rld_obj_head symbol.  */
321179404Sobrien  bfd_vma rld_value;
322179404Sobrien  /* This is set if we see any mips16 stub sections.  */
323179404Sobrien  bfd_boolean mips16_stubs_seen;
324218822Sdim  /* True if we're generating code for VxWorks.  */
325218822Sdim  bfd_boolean is_vxworks;
326218822Sdim  /* Shortcuts to some dynamic sections, or NULL if they are not
327218822Sdim     being used.  */
328218822Sdim  asection *srelbss;
329218822Sdim  asection *sdynbss;
330218822Sdim  asection *srelplt;
331218822Sdim  asection *srelplt2;
332218822Sdim  asection *sgotplt;
333218822Sdim  asection *splt;
334218822Sdim  /* The size of the PLT header in bytes (VxWorks only).  */
335218822Sdim  bfd_vma plt_header_size;
336218822Sdim  /* The size of a PLT entry in bytes (VxWorks only).  */
337218822Sdim  bfd_vma plt_entry_size;
338218822Sdim  /* The size of a function stub entry in bytes.  */
339218822Sdim  bfd_vma function_stub_size;
340179404Sobrien};
341179404Sobrien
342218822Sdim#define TLS_RELOC_P(r_type) \
343218822Sdim  (r_type == R_MIPS_TLS_DTPMOD32		\
344218822Sdim   || r_type == R_MIPS_TLS_DTPMOD64		\
345218822Sdim   || r_type == R_MIPS_TLS_DTPREL32		\
346218822Sdim   || r_type == R_MIPS_TLS_DTPREL64		\
347218822Sdim   || r_type == R_MIPS_TLS_GD			\
348218822Sdim   || r_type == R_MIPS_TLS_LDM			\
349218822Sdim   || r_type == R_MIPS_TLS_DTPREL_HI16		\
350218822Sdim   || r_type == R_MIPS_TLS_DTPREL_LO16		\
351218822Sdim   || r_type == R_MIPS_TLS_GOTTPREL		\
352218822Sdim   || r_type == R_MIPS_TLS_TPREL32		\
353218822Sdim   || r_type == R_MIPS_TLS_TPREL64		\
354218822Sdim   || r_type == R_MIPS_TLS_TPREL_HI16		\
355218822Sdim   || r_type == R_MIPS_TLS_TPREL_LO16)
356218822Sdim
357179404Sobrien/* Structure used to pass information to mips_elf_output_extsym.  */
358179404Sobrien
359179404Sobrienstruct extsym_info
360179404Sobrien{
361179404Sobrien  bfd *abfd;
362179404Sobrien  struct bfd_link_info *info;
363179404Sobrien  struct ecoff_debug_info *debug;
364179404Sobrien  const struct ecoff_debug_swap *swap;
365179404Sobrien  bfd_boolean failed;
366179404Sobrien};
367179404Sobrien
368179404Sobrien/* The names of the runtime procedure table symbols used on IRIX5.  */
369179404Sobrien
370179404Sobrienstatic const char * const mips_elf_dynsym_rtproc_names[] =
371179404Sobrien{
372179404Sobrien  "_procedure_table",
373179404Sobrien  "_procedure_string_table",
374179404Sobrien  "_procedure_table_size",
375179404Sobrien  NULL
376179404Sobrien};
377179404Sobrien
378179404Sobrien/* These structures are used to generate the .compact_rel section on
379179404Sobrien   IRIX5.  */
380179404Sobrien
381179404Sobrientypedef struct
382179404Sobrien{
383179404Sobrien  unsigned long id1;		/* Always one?  */
384179404Sobrien  unsigned long num;		/* Number of compact relocation entries.  */
385179404Sobrien  unsigned long id2;		/* Always two?  */
386179404Sobrien  unsigned long offset;		/* The file offset of the first relocation.  */
387179404Sobrien  unsigned long reserved0;	/* Zero?  */
388179404Sobrien  unsigned long reserved1;	/* Zero?  */
389179404Sobrien} Elf32_compact_rel;
390179404Sobrien
391179404Sobrientypedef struct
392179404Sobrien{
393179404Sobrien  bfd_byte id1[4];
394179404Sobrien  bfd_byte num[4];
395179404Sobrien  bfd_byte id2[4];
396179404Sobrien  bfd_byte offset[4];
397179404Sobrien  bfd_byte reserved0[4];
398179404Sobrien  bfd_byte reserved1[4];
399179404Sobrien} Elf32_External_compact_rel;
400179404Sobrien
401179404Sobrientypedef struct
402179404Sobrien{
403179404Sobrien  unsigned int ctype : 1;	/* 1: long 0: short format. See below.  */
404179404Sobrien  unsigned int rtype : 4;	/* Relocation types. See below.  */
405179404Sobrien  unsigned int dist2to : 8;
406179404Sobrien  unsigned int relvaddr : 19;	/* (VADDR - vaddr of the previous entry)/ 4 */
407179404Sobrien  unsigned long konst;		/* KONST field. See below.  */
408179404Sobrien  unsigned long vaddr;		/* VADDR to be relocated.  */
409179404Sobrien} Elf32_crinfo;
410179404Sobrien
411179404Sobrientypedef struct
412179404Sobrien{
413179404Sobrien  unsigned int ctype : 1;	/* 1: long 0: short format. See below.  */
414179404Sobrien  unsigned int rtype : 4;	/* Relocation types. See below.  */
415179404Sobrien  unsigned int dist2to : 8;
416179404Sobrien  unsigned int relvaddr : 19;	/* (VADDR - vaddr of the previous entry)/ 4 */
417179404Sobrien  unsigned long konst;		/* KONST field. See below.  */
418179404Sobrien} Elf32_crinfo2;
419179404Sobrien
420179404Sobrientypedef struct
421179404Sobrien{
422179404Sobrien  bfd_byte info[4];
423179404Sobrien  bfd_byte konst[4];
424179404Sobrien  bfd_byte vaddr[4];
425179404Sobrien} Elf32_External_crinfo;
426179404Sobrien
427179404Sobrientypedef struct
428179404Sobrien{
429179404Sobrien  bfd_byte info[4];
430179404Sobrien  bfd_byte konst[4];
431179404Sobrien} Elf32_External_crinfo2;
432179404Sobrien
433179404Sobrien/* These are the constants used to swap the bitfields in a crinfo.  */
434179404Sobrien
435179404Sobrien#define CRINFO_CTYPE (0x1)
436179404Sobrien#define CRINFO_CTYPE_SH (31)
437179404Sobrien#define CRINFO_RTYPE (0xf)
438179404Sobrien#define CRINFO_RTYPE_SH (27)
439179404Sobrien#define CRINFO_DIST2TO (0xff)
440179404Sobrien#define CRINFO_DIST2TO_SH (19)
441179404Sobrien#define CRINFO_RELVADDR (0x7ffff)
442179404Sobrien#define CRINFO_RELVADDR_SH (0)
443179404Sobrien
444179404Sobrien/* A compact relocation info has long (3 words) or short (2 words)
445179404Sobrien   formats.  A short format doesn't have VADDR field and relvaddr
446179404Sobrien   fields contains ((VADDR - vaddr of the previous entry) >> 2).  */
447179404Sobrien#define CRF_MIPS_LONG			1
448179404Sobrien#define CRF_MIPS_SHORT			0
449179404Sobrien
450179404Sobrien/* There are 4 types of compact relocation at least. The value KONST
451179404Sobrien   has different meaning for each type:
452179404Sobrien
453179404Sobrien   (type)		(konst)
454179404Sobrien   CT_MIPS_REL32	Address in data
455179404Sobrien   CT_MIPS_WORD		Address in word (XXX)
456179404Sobrien   CT_MIPS_GPHI_LO	GP - vaddr
457179404Sobrien   CT_MIPS_JMPAD	Address to jump
458179404Sobrien   */
459179404Sobrien
460179404Sobrien#define CRT_MIPS_REL32			0xa
461179404Sobrien#define CRT_MIPS_WORD			0xb
462179404Sobrien#define CRT_MIPS_GPHI_LO		0xc
463179404Sobrien#define CRT_MIPS_JMPAD			0xd
464179404Sobrien
465179404Sobrien#define mips_elf_set_cr_format(x,format)	((x).ctype = (format))
466179404Sobrien#define mips_elf_set_cr_type(x,type)		((x).rtype = (type))
467179404Sobrien#define mips_elf_set_cr_dist2to(x,v)		((x).dist2to = (v))
468179404Sobrien#define mips_elf_set_cr_relvaddr(x,d)		((x).relvaddr = (d)<<2)
469179404Sobrien
470179404Sobrien/* The structure of the runtime procedure descriptor created by the
471179404Sobrien   loader for use by the static exception system.  */
472179404Sobrien
473179404Sobrientypedef struct runtime_pdr {
474179404Sobrien	bfd_vma	adr;		/* Memory address of start of procedure.  */
475179404Sobrien	long	regmask;	/* Save register mask.  */
476179404Sobrien	long	regoffset;	/* Save register offset.  */
477179404Sobrien	long	fregmask;	/* Save floating point register mask.  */
478179404Sobrien	long	fregoffset;	/* Save floating point register offset.  */
479179404Sobrien	long	frameoffset;	/* Frame size.  */
480179404Sobrien	short	framereg;	/* Frame pointer register.  */
481179404Sobrien	short	pcreg;		/* Offset or reg of return pc.  */
482179404Sobrien	long	irpss;		/* Index into the runtime string table.  */
483179404Sobrien	long	reserved;
484179404Sobrien	struct exception_info *exception_info;/* Pointer to exception array.  */
485179404Sobrien} RPDR, *pRPDR;
486179404Sobrien#define cbRPDR sizeof (RPDR)
487179404Sobrien#define rpdNil ((pRPDR) 0)
488179404Sobrien
489179404Sobrienstatic struct mips_got_entry *mips_elf_create_local_got_entry
490218822Sdim  (bfd *, struct bfd_link_info *, bfd *, struct mips_got_info *, asection *,
491218822Sdim   bfd_vma, unsigned long, struct mips_elf_link_hash_entry *, int);
492179404Sobrienstatic bfd_boolean mips_elf_sort_hash_table_f
493179404Sobrien  (struct mips_elf_link_hash_entry *, void *);
494179404Sobrienstatic bfd_vma mips_elf_high
495179404Sobrien  (bfd_vma);
496218822Sdimstatic bfd_boolean mips16_stub_section_p
497179404Sobrien  (bfd *, asection *);
498179404Sobrienstatic bfd_boolean mips_elf_create_dynamic_relocation
499179404Sobrien  (bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
500179404Sobrien   struct mips_elf_link_hash_entry *, asection *, bfd_vma,
501179404Sobrien   bfd_vma *, asection *);
502179404Sobrienstatic hashval_t mips_elf_got_entry_hash
503179404Sobrien  (const void *);
504179404Sobrienstatic bfd_vma mips_elf_adjust_gp
505179404Sobrien  (bfd *, struct mips_got_info *, bfd *);
506179404Sobrienstatic struct mips_got_info *mips_elf_got_for_ibfd
507179404Sobrien  (struct mips_got_info *, bfd *);
508179404Sobrien
509179404Sobrien/* This will be used when we sort the dynamic relocation records.  */
510179404Sobrienstatic bfd *reldyn_sorting_bfd;
511179404Sobrien
512179404Sobrien/* Nonzero if ABFD is using the N32 ABI.  */
513179404Sobrien#define ABI_N32_P(abfd) \
514179404Sobrien  ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
515179404Sobrien
516179404Sobrien/* Nonzero if ABFD is using the N64 ABI.  */
517179404Sobrien#define ABI_64_P(abfd) \
518179404Sobrien  (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64)
519179404Sobrien
520179404Sobrien/* Nonzero if ABFD is using NewABI conventions.  */
521179404Sobrien#define NEWABI_P(abfd) (ABI_N32_P (abfd) || ABI_64_P (abfd))
522179404Sobrien
523179404Sobrien/* The IRIX compatibility level we are striving for.  */
524179404Sobrien#define IRIX_COMPAT(abfd) \
525179404Sobrien  (get_elf_backend_data (abfd)->elf_backend_mips_irix_compat (abfd))
526179404Sobrien
527179404Sobrien/* Whether we are trying to be compatible with IRIX at all.  */
528179404Sobrien#define SGI_COMPAT(abfd) \
529179404Sobrien  (IRIX_COMPAT (abfd) != ict_none)
530179404Sobrien
531179404Sobrien/* The name of the options section.  */
532179404Sobrien#define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \
533179404Sobrien  (NEWABI_P (abfd) ? ".MIPS.options" : ".options")
534179404Sobrien
535218822Sdim/* True if NAME is the recognized name of any SHT_MIPS_OPTIONS section.
536218822Sdim   Some IRIX system files do not use MIPS_ELF_OPTIONS_SECTION_NAME.  */
537218822Sdim#define MIPS_ELF_OPTIONS_SECTION_NAME_P(NAME) \
538218822Sdim  (strcmp (NAME, ".MIPS.options") == 0 || strcmp (NAME, ".options") == 0)
539218822Sdim
540218822Sdim/* Whether the section is readonly.  */
541218822Sdim#define MIPS_ELF_READONLY_SECTION(sec) \
542218822Sdim  ((sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))		\
543218822Sdim   == (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
544218822Sdim
545179404Sobrien/* The name of the stub section.  */
546179404Sobrien#define MIPS_ELF_STUB_SECTION_NAME(abfd) ".MIPS.stubs"
547179404Sobrien
548179404Sobrien/* The size of an external REL relocation.  */
549179404Sobrien#define MIPS_ELF_REL_SIZE(abfd) \
550179404Sobrien  (get_elf_backend_data (abfd)->s->sizeof_rel)
551179404Sobrien
552218822Sdim/* The size of an external RELA relocation.  */
553218822Sdim#define MIPS_ELF_RELA_SIZE(abfd) \
554218822Sdim  (get_elf_backend_data (abfd)->s->sizeof_rela)
555218822Sdim
556179404Sobrien/* The size of an external dynamic table entry.  */
557179404Sobrien#define MIPS_ELF_DYN_SIZE(abfd) \
558179404Sobrien  (get_elf_backend_data (abfd)->s->sizeof_dyn)
559179404Sobrien
560255982Semaste/* The size of the rld_map pointer.  */
561255982Semaste#define MIPS_ELF_RLD_MAP_SIZE(abfd) \
562255982Semaste  (get_elf_backend_data (abfd)->s->arch_size / 8)
563255982Semaste
564179404Sobrien/* The size of a GOT entry.  */
565179404Sobrien#define MIPS_ELF_GOT_SIZE(abfd) \
566179404Sobrien  (get_elf_backend_data (abfd)->s->arch_size / 8)
567179404Sobrien
568179404Sobrien/* The size of a symbol-table entry.  */
569179404Sobrien#define MIPS_ELF_SYM_SIZE(abfd) \
570179404Sobrien  (get_elf_backend_data (abfd)->s->sizeof_sym)
571179404Sobrien
572179404Sobrien/* The default alignment for sections, as a power of two.  */
573179404Sobrien#define MIPS_ELF_LOG_FILE_ALIGN(abfd)				\
574179404Sobrien  (get_elf_backend_data (abfd)->s->log_file_align)
575179404Sobrien
576179404Sobrien/* Get word-sized data.  */
577179404Sobrien#define MIPS_ELF_GET_WORD(abfd, ptr) \
578179404Sobrien  (ABI_64_P (abfd) ? bfd_get_64 (abfd, ptr) : bfd_get_32 (abfd, ptr))
579179404Sobrien
580179404Sobrien/* Put out word-sized data.  */
581179404Sobrien#define MIPS_ELF_PUT_WORD(abfd, val, ptr)	\
582179404Sobrien  (ABI_64_P (abfd) 				\
583179404Sobrien   ? bfd_put_64 (abfd, val, ptr) 		\
584179404Sobrien   : bfd_put_32 (abfd, val, ptr))
585179404Sobrien
586179404Sobrien/* Add a dynamic symbol table-entry.  */
587179404Sobrien#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)	\
588179404Sobrien  _bfd_elf_add_dynamic_entry (info, tag, val)
589179404Sobrien
590179404Sobrien#define MIPS_ELF_RTYPE_TO_HOWTO(abfd, rtype, rela)			\
591179404Sobrien  (get_elf_backend_data (abfd)->elf_backend_mips_rtype_to_howto (rtype, rela))
592179404Sobrien
593179404Sobrien/* Determine whether the internal relocation of index REL_IDX is REL
594179404Sobrien   (zero) or RELA (non-zero).  The assumption is that, if there are
595179404Sobrien   two relocation sections for this section, one of them is REL and
596179404Sobrien   the other is RELA.  If the index of the relocation we're testing is
597179404Sobrien   in range for the first relocation section, check that the external
598179404Sobrien   relocation size is that for RELA.  It is also assumed that, if
599179404Sobrien   rel_idx is not in range for the first section, and this first
600179404Sobrien   section contains REL relocs, then the relocation is in the second
601179404Sobrien   section, that is RELA.  */
602179404Sobrien#define MIPS_RELOC_RELA_P(abfd, sec, rel_idx)				\
603179404Sobrien  ((NUM_SHDR_ENTRIES (&elf_section_data (sec)->rel_hdr)			\
604179404Sobrien    * get_elf_backend_data (abfd)->s->int_rels_per_ext_rel		\
605179404Sobrien    > (bfd_vma)(rel_idx))						\
606179404Sobrien   == (elf_section_data (sec)->rel_hdr.sh_entsize			\
607179404Sobrien       == (ABI_64_P (abfd) ? sizeof (Elf64_External_Rela)		\
608179404Sobrien	   : sizeof (Elf32_External_Rela))))
609179404Sobrien
610218822Sdim/* The name of the dynamic relocation section.  */
611218822Sdim#define MIPS_ELF_REL_DYN_NAME(INFO) \
612218822Sdim  (mips_elf_hash_table (INFO)->is_vxworks ? ".rela.dyn" : ".rel.dyn")
613218822Sdim
614179404Sobrien/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
615179404Sobrien   from smaller values.  Start with zero, widen, *then* decrement.  */
616179404Sobrien#define MINUS_ONE	(((bfd_vma)0) - 1)
617218822Sdim#define MINUS_TWO	(((bfd_vma)0) - 2)
618179404Sobrien
619179404Sobrien/* The number of local .got entries we reserve.  */
620218822Sdim#define MIPS_RESERVED_GOTNO(INFO) \
621218822Sdim  (mips_elf_hash_table (INFO)->is_vxworks ? 3 : 2)
622179404Sobrien
623179404Sobrien/* The offset of $gp from the beginning of the .got section.  */
624218822Sdim#define ELF_MIPS_GP_OFFSET(INFO) \
625218822Sdim  (mips_elf_hash_table (INFO)->is_vxworks ? 0x0 : 0x7ff0)
626179404Sobrien
627179404Sobrien/* The maximum size of the GOT for it to be addressable using 16-bit
628179404Sobrien   offsets from $gp.  */
629218822Sdim#define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff)
630179404Sobrien
631179404Sobrien/* Instructions which appear in a stub.  */
632218822Sdim#define STUB_LW(abfd)							\
633218822Sdim  ((ABI_64_P (abfd)							\
634218822Sdim    ? 0xdf998010				/* ld t9,0x8010(gp) */	\
635218822Sdim    : 0x8f998010))              		/* lw t9,0x8010(gp) */
636218822Sdim#define STUB_MOVE(abfd)							\
637218822Sdim   ((ABI_64_P (abfd)							\
638218822Sdim     ? 0x03e0782d				/* daddu t7,ra */	\
639218822Sdim     : 0x03e07821))				/* addu t7,ra */
640218822Sdim#define STUB_LUI(VAL) (0x3c180000 + (VAL))	/* lui t8,VAL */
641218822Sdim#define STUB_JALR 0x0320f809			/* jalr t9,ra */
642218822Sdim#define STUB_ORI(VAL) (0x37180000 + (VAL))	/* ori t8,t8,VAL */
643218822Sdim#define STUB_LI16U(VAL) (0x34180000 + (VAL))	/* ori t8,zero,VAL unsigned */
644218822Sdim#define STUB_LI16S(abfd, VAL)						\
645218822Sdim   ((ABI_64_P (abfd)							\
646218822Sdim    ? (0x64180000 + (VAL))	/* daddiu t8,zero,VAL sign extended */	\
647218822Sdim    : (0x24180000 + (VAL))))	/* addiu t8,zero,VAL sign extended */
648179404Sobrien
649218822Sdim#define MIPS_FUNCTION_STUB_NORMAL_SIZE 16
650218822Sdim#define MIPS_FUNCTION_STUB_BIG_SIZE 20
651218822Sdim
652179404Sobrien/* The name of the dynamic interpreter.  This is put in the .interp
653179404Sobrien   section.  */
654179404Sobrien
655179404Sobrien#define ELF_DYNAMIC_INTERPRETER(abfd) 		\
656179404Sobrien   (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" 	\
657179404Sobrien    : ABI_64_P (abfd) ? "/usr/lib64/libc.so.1" 	\
658179404Sobrien    : "/usr/lib/libc.so.1")
659179404Sobrien
660179404Sobrien#ifdef BFD64
661179404Sobrien#define MNAME(bfd,pre,pos) \
662179404Sobrien  (ABI_64_P (bfd) ? CONCAT4 (pre,64,_,pos) : CONCAT4 (pre,32,_,pos))
663179404Sobrien#define ELF_R_SYM(bfd, i)					\
664179404Sobrien  (ABI_64_P (bfd) ? ELF64_R_SYM (i) : ELF32_R_SYM (i))
665179404Sobrien#define ELF_R_TYPE(bfd, i)					\
666179404Sobrien  (ABI_64_P (bfd) ? ELF64_MIPS_R_TYPE (i) : ELF32_R_TYPE (i))
667179404Sobrien#define ELF_R_INFO(bfd, s, t)					\
668179404Sobrien  (ABI_64_P (bfd) ? ELF64_R_INFO (s, t) : ELF32_R_INFO (s, t))
669179404Sobrien#else
670179404Sobrien#define MNAME(bfd,pre,pos) CONCAT4 (pre,32,_,pos)
671179404Sobrien#define ELF_R_SYM(bfd, i)					\
672179404Sobrien  (ELF32_R_SYM (i))
673179404Sobrien#define ELF_R_TYPE(bfd, i)					\
674179404Sobrien  (ELF32_R_TYPE (i))
675179404Sobrien#define ELF_R_INFO(bfd, s, t)					\
676179404Sobrien  (ELF32_R_INFO (s, t))
677179404Sobrien#endif
678179404Sobrien
679179404Sobrien  /* The mips16 compiler uses a couple of special sections to handle
680179404Sobrien     floating point arguments.
681179404Sobrien
682179404Sobrien     Section names that look like .mips16.fn.FNNAME contain stubs that
683179404Sobrien     copy floating point arguments from the fp regs to the gp regs and
684179404Sobrien     then jump to FNNAME.  If any 32 bit function calls FNNAME, the
685179404Sobrien     call should be redirected to the stub instead.  If no 32 bit
686179404Sobrien     function calls FNNAME, the stub should be discarded.  We need to
687179404Sobrien     consider any reference to the function, not just a call, because
688179404Sobrien     if the address of the function is taken we will need the stub,
689179404Sobrien     since the address might be passed to a 32 bit function.
690179404Sobrien
691179404Sobrien     Section names that look like .mips16.call.FNNAME contain stubs
692179404Sobrien     that copy floating point arguments from the gp regs to the fp
693179404Sobrien     regs and then jump to FNNAME.  If FNNAME is a 32 bit function,
694179404Sobrien     then any 16 bit function that calls FNNAME should be redirected
695179404Sobrien     to the stub instead.  If FNNAME is not a 32 bit function, the
696179404Sobrien     stub should be discarded.
697179404Sobrien
698179404Sobrien     .mips16.call.fp.FNNAME sections are similar, but contain stubs
699179404Sobrien     which call FNNAME and then copy the return value from the fp regs
700179404Sobrien     to the gp regs.  These stubs store the return value in $18 while
701179404Sobrien     calling FNNAME; any function which might call one of these stubs
702179404Sobrien     must arrange to save $18 around the call.  (This case is not
703179404Sobrien     needed for 32 bit functions that call 16 bit functions, because
704179404Sobrien     16 bit functions always return floating point values in both
705179404Sobrien     $f0/$f1 and $2/$3.)
706179404Sobrien
707179404Sobrien     Note that in all cases FNNAME might be defined statically.
708179404Sobrien     Therefore, FNNAME is not used literally.  Instead, the relocation
709179404Sobrien     information will indicate which symbol the section is for.
710179404Sobrien
711179404Sobrien     We record any stubs that we find in the symbol table.  */
712179404Sobrien
713179404Sobrien#define FN_STUB ".mips16.fn."
714179404Sobrien#define CALL_STUB ".mips16.call."
715179404Sobrien#define CALL_FP_STUB ".mips16.call.fp."
716218822Sdim
717218822Sdim#define FN_STUB_P(name) CONST_STRNEQ (name, FN_STUB)
718218822Sdim#define CALL_STUB_P(name) CONST_STRNEQ (name, CALL_STUB)
719218822Sdim#define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB)
720179404Sobrien
721218822Sdim/* The format of the first PLT entry in a VxWorks executable.  */
722218822Sdimstatic const bfd_vma mips_vxworks_exec_plt0_entry[] = {
723218822Sdim  0x3c190000,	/* lui t9, %hi(_GLOBAL_OFFSET_TABLE_)		*/
724218822Sdim  0x27390000,	/* addiu t9, t9, %lo(_GLOBAL_OFFSET_TABLE_)	*/
725218822Sdim  0x8f390008,	/* lw t9, 8(t9)					*/
726218822Sdim  0x00000000,	/* nop						*/
727218822Sdim  0x03200008,	/* jr t9					*/
728218822Sdim  0x00000000	/* nop						*/
729218822Sdim};
730218822Sdim
731218822Sdim/* The format of subsequent PLT entries.  */
732218822Sdimstatic const bfd_vma mips_vxworks_exec_plt_entry[] = {
733218822Sdim  0x10000000,	/* b .PLT_resolver			*/
734218822Sdim  0x24180000,	/* li t8, <pltindex>			*/
735218822Sdim  0x3c190000,	/* lui t9, %hi(<.got.plt slot>)		*/
736218822Sdim  0x27390000,	/* addiu t9, t9, %lo(<.got.plt slot>)	*/
737218822Sdim  0x8f390000,	/* lw t9, 0(t9)				*/
738218822Sdim  0x00000000,	/* nop					*/
739218822Sdim  0x03200008,	/* jr t9				*/
740218822Sdim  0x00000000	/* nop					*/
741218822Sdim};
742218822Sdim
743218822Sdim/* The format of the first PLT entry in a VxWorks shared object.  */
744218822Sdimstatic const bfd_vma mips_vxworks_shared_plt0_entry[] = {
745218822Sdim  0x8f990008,	/* lw t9, 8(gp)		*/
746218822Sdim  0x00000000,	/* nop			*/
747218822Sdim  0x03200008,	/* jr t9		*/
748218822Sdim  0x00000000,	/* nop			*/
749218822Sdim  0x00000000,	/* nop			*/
750218822Sdim  0x00000000	/* nop			*/
751218822Sdim};
752218822Sdim
753218822Sdim/* The format of subsequent PLT entries.  */
754218822Sdimstatic const bfd_vma mips_vxworks_shared_plt_entry[] = {
755218822Sdim  0x10000000,	/* b .PLT_resolver	*/
756218822Sdim  0x24180000	/* li t8, <pltindex>	*/
757218822Sdim};
758218822Sdim
759179404Sobrien/* Look up an entry in a MIPS ELF linker hash table.  */
760179404Sobrien
761179404Sobrien#define mips_elf_link_hash_lookup(table, string, create, copy, follow)	\
762179404Sobrien  ((struct mips_elf_link_hash_entry *)					\
763179404Sobrien   elf_link_hash_lookup (&(table)->root, (string), (create),		\
764179404Sobrien			 (copy), (follow)))
765179404Sobrien
766179404Sobrien/* Traverse a MIPS ELF linker hash table.  */
767179404Sobrien
768179404Sobrien#define mips_elf_link_hash_traverse(table, func, info)			\
769179404Sobrien  (elf_link_hash_traverse						\
770179404Sobrien   (&(table)->root,							\
771179404Sobrien    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),	\
772179404Sobrien    (info)))
773179404Sobrien
774179404Sobrien/* Get the MIPS ELF linker hash table from a link_info structure.  */
775179404Sobrien
776179404Sobrien#define mips_elf_hash_table(p) \
777179404Sobrien  ((struct mips_elf_link_hash_table *) ((p)->hash))
778179404Sobrien
779218822Sdim/* Find the base offsets for thread-local storage in this object,
780218822Sdim   for GD/LD and IE/LE respectively.  */
781218822Sdim
782218822Sdim#define TP_OFFSET 0x7000
783218822Sdim#define DTP_OFFSET 0x8000
784218822Sdim
785218822Sdimstatic bfd_vma
786218822Sdimdtprel_base (struct bfd_link_info *info)
787218822Sdim{
788218822Sdim  /* If tls_sec is NULL, we should have signalled an error already.  */
789218822Sdim  if (elf_hash_table (info)->tls_sec == NULL)
790218822Sdim    return 0;
791218822Sdim  return elf_hash_table (info)->tls_sec->vma + DTP_OFFSET;
792218822Sdim}
793218822Sdim
794218822Sdimstatic bfd_vma
795218822Sdimtprel_base (struct bfd_link_info *info)
796218822Sdim{
797218822Sdim  /* If tls_sec is NULL, we should have signalled an error already.  */
798218822Sdim  if (elf_hash_table (info)->tls_sec == NULL)
799218822Sdim    return 0;
800218822Sdim  return elf_hash_table (info)->tls_sec->vma + TP_OFFSET;
801218822Sdim}
802218822Sdim
803179404Sobrien/* Create an entry in a MIPS ELF linker hash table.  */
804179404Sobrien
805179404Sobrienstatic struct bfd_hash_entry *
806179404Sobrienmips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
807179404Sobrien			    struct bfd_hash_table *table, const char *string)
808179404Sobrien{
809179404Sobrien  struct mips_elf_link_hash_entry *ret =
810179404Sobrien    (struct mips_elf_link_hash_entry *) entry;
811179404Sobrien
812179404Sobrien  /* Allocate the structure if it has not already been allocated by a
813179404Sobrien     subclass.  */
814179404Sobrien  if (ret == NULL)
815179404Sobrien    ret = bfd_hash_allocate (table, sizeof (struct mips_elf_link_hash_entry));
816179404Sobrien  if (ret == NULL)
817179404Sobrien    return (struct bfd_hash_entry *) ret;
818179404Sobrien
819179404Sobrien  /* Call the allocation method of the superclass.  */
820179404Sobrien  ret = ((struct mips_elf_link_hash_entry *)
821179404Sobrien	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
822179404Sobrien				     table, string));
823179404Sobrien  if (ret != NULL)
824179404Sobrien    {
825179404Sobrien      /* Set local fields.  */
826179404Sobrien      memset (&ret->esym, 0, sizeof (EXTR));
827179404Sobrien      /* We use -2 as a marker to indicate that the information has
828179404Sobrien	 not been set.  -1 means there is no associated ifd.  */
829179404Sobrien      ret->esym.ifd = -2;
830179404Sobrien      ret->possibly_dynamic_relocs = 0;
831179404Sobrien      ret->readonly_reloc = FALSE;
832179404Sobrien      ret->no_fn_stub = FALSE;
833179404Sobrien      ret->fn_stub = NULL;
834179404Sobrien      ret->need_fn_stub = FALSE;
835179404Sobrien      ret->call_stub = NULL;
836179404Sobrien      ret->call_fp_stub = NULL;
837179404Sobrien      ret->forced_local = FALSE;
838218822Sdim      ret->is_branch_target = FALSE;
839218822Sdim      ret->is_relocation_target = FALSE;
840218822Sdim      ret->tls_type = GOT_NORMAL;
841179404Sobrien    }
842179404Sobrien
843179404Sobrien  return (struct bfd_hash_entry *) ret;
844179404Sobrien}
845179404Sobrien
846179404Sobrienbfd_boolean
847179404Sobrien_bfd_mips_elf_new_section_hook (bfd *abfd, asection *sec)
848179404Sobrien{
849218822Sdim  if (!sec->used_by_bfd)
850218822Sdim    {
851218822Sdim      struct _mips_elf_section_data *sdata;
852218822Sdim      bfd_size_type amt = sizeof (*sdata);
853179404Sobrien
854218822Sdim      sdata = bfd_zalloc (abfd, amt);
855218822Sdim      if (sdata == NULL)
856218822Sdim	return FALSE;
857218822Sdim      sec->used_by_bfd = sdata;
858218822Sdim    }
859179404Sobrien
860179404Sobrien  return _bfd_elf_new_section_hook (abfd, sec);
861179404Sobrien}
862179404Sobrien
863179404Sobrien/* Read ECOFF debugging information from a .mdebug section into a
864179404Sobrien   ecoff_debug_info structure.  */
865179404Sobrien
866179404Sobrienbfd_boolean
867179404Sobrien_bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
868179404Sobrien			       struct ecoff_debug_info *debug)
869179404Sobrien{
870179404Sobrien  HDRR *symhdr;
871179404Sobrien  const struct ecoff_debug_swap *swap;
872179404Sobrien  char *ext_hdr;
873179404Sobrien
874179404Sobrien  swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
875179404Sobrien  memset (debug, 0, sizeof (*debug));
876179404Sobrien
877179404Sobrien  ext_hdr = bfd_malloc (swap->external_hdr_size);
878179404Sobrien  if (ext_hdr == NULL && swap->external_hdr_size != 0)
879179404Sobrien    goto error_return;
880179404Sobrien
881179404Sobrien  if (! bfd_get_section_contents (abfd, section, ext_hdr, 0,
882179404Sobrien				  swap->external_hdr_size))
883179404Sobrien    goto error_return;
884179404Sobrien
885179404Sobrien  symhdr = &debug->symbolic_header;
886179404Sobrien  (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
887179404Sobrien
888179404Sobrien  /* The symbolic header contains absolute file offsets and sizes to
889179404Sobrien     read.  */
890179404Sobrien#define READ(ptr, offset, count, size, type)				\
891179404Sobrien  if (symhdr->count == 0)						\
892179404Sobrien    debug->ptr = NULL;							\
893179404Sobrien  else									\
894179404Sobrien    {									\
895179404Sobrien      bfd_size_type amt = (bfd_size_type) size * symhdr->count;		\
896179404Sobrien      debug->ptr = bfd_malloc (amt);					\
897179404Sobrien      if (debug->ptr == NULL)						\
898179404Sobrien	goto error_return;						\
899179404Sobrien      if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0		\
900179404Sobrien	  || bfd_bread (debug->ptr, amt, abfd) != amt)			\
901179404Sobrien	goto error_return;						\
902179404Sobrien    }
903179404Sobrien
904179404Sobrien  READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
905179404Sobrien  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
906179404Sobrien  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
907179404Sobrien  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
908179404Sobrien  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
909179404Sobrien  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
910179404Sobrien	union aux_ext *);
911179404Sobrien  READ (ss, cbSsOffset, issMax, sizeof (char), char *);
912179404Sobrien  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
913179404Sobrien  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
914179404Sobrien  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
915179404Sobrien  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
916179404Sobrien#undef READ
917179404Sobrien
918179404Sobrien  debug->fdr = NULL;
919179404Sobrien
920179404Sobrien  return TRUE;
921179404Sobrien
922179404Sobrien error_return:
923179404Sobrien  if (ext_hdr != NULL)
924179404Sobrien    free (ext_hdr);
925179404Sobrien  if (debug->line != NULL)
926179404Sobrien    free (debug->line);
927179404Sobrien  if (debug->external_dnr != NULL)
928179404Sobrien    free (debug->external_dnr);
929179404Sobrien  if (debug->external_pdr != NULL)
930179404Sobrien    free (debug->external_pdr);
931179404Sobrien  if (debug->external_sym != NULL)
932179404Sobrien    free (debug->external_sym);
933179404Sobrien  if (debug->external_opt != NULL)
934179404Sobrien    free (debug->external_opt);
935179404Sobrien  if (debug->external_aux != NULL)
936179404Sobrien    free (debug->external_aux);
937179404Sobrien  if (debug->ss != NULL)
938179404Sobrien    free (debug->ss);
939179404Sobrien  if (debug->ssext != NULL)
940179404Sobrien    free (debug->ssext);
941179404Sobrien  if (debug->external_fdr != NULL)
942179404Sobrien    free (debug->external_fdr);
943179404Sobrien  if (debug->external_rfd != NULL)
944179404Sobrien    free (debug->external_rfd);
945179404Sobrien  if (debug->external_ext != NULL)
946179404Sobrien    free (debug->external_ext);
947179404Sobrien  return FALSE;
948179404Sobrien}
949179404Sobrien
950179404Sobrien/* Swap RPDR (runtime procedure table entry) for output.  */
951179404Sobrien
952179404Sobrienstatic void
953179404Sobrienecoff_swap_rpdr_out (bfd *abfd, const RPDR *in, struct rpdr_ext *ex)
954179404Sobrien{
955179404Sobrien  H_PUT_S32 (abfd, in->adr, ex->p_adr);
956179404Sobrien  H_PUT_32 (abfd, in->regmask, ex->p_regmask);
957179404Sobrien  H_PUT_32 (abfd, in->regoffset, ex->p_regoffset);
958179404Sobrien  H_PUT_32 (abfd, in->fregmask, ex->p_fregmask);
959179404Sobrien  H_PUT_32 (abfd, in->fregoffset, ex->p_fregoffset);
960179404Sobrien  H_PUT_32 (abfd, in->frameoffset, ex->p_frameoffset);
961179404Sobrien
962179404Sobrien  H_PUT_16 (abfd, in->framereg, ex->p_framereg);
963179404Sobrien  H_PUT_16 (abfd, in->pcreg, ex->p_pcreg);
964179404Sobrien
965179404Sobrien  H_PUT_32 (abfd, in->irpss, ex->p_irpss);
966179404Sobrien}
967179404Sobrien
968179404Sobrien/* Create a runtime procedure table from the .mdebug section.  */
969179404Sobrien
970179404Sobrienstatic bfd_boolean
971179404Sobrienmips_elf_create_procedure_table (void *handle, bfd *abfd,
972179404Sobrien				 struct bfd_link_info *info, asection *s,
973179404Sobrien				 struct ecoff_debug_info *debug)
974179404Sobrien{
975179404Sobrien  const struct ecoff_debug_swap *swap;
976179404Sobrien  HDRR *hdr = &debug->symbolic_header;
977179404Sobrien  RPDR *rpdr, *rp;
978179404Sobrien  struct rpdr_ext *erp;
979179404Sobrien  void *rtproc;
980179404Sobrien  struct pdr_ext *epdr;
981179404Sobrien  struct sym_ext *esym;
982179404Sobrien  char *ss, **sv;
983179404Sobrien  char *str;
984179404Sobrien  bfd_size_type size;
985179404Sobrien  bfd_size_type count;
986179404Sobrien  unsigned long sindex;
987179404Sobrien  unsigned long i;
988179404Sobrien  PDR pdr;
989179404Sobrien  SYMR sym;
990179404Sobrien  const char *no_name_func = _("static procedure (no name)");
991179404Sobrien
992179404Sobrien  epdr = NULL;
993179404Sobrien  rpdr = NULL;
994179404Sobrien  esym = NULL;
995179404Sobrien  ss = NULL;
996179404Sobrien  sv = NULL;
997179404Sobrien
998179404Sobrien  swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
999179404Sobrien
1000179404Sobrien  sindex = strlen (no_name_func) + 1;
1001179404Sobrien  count = hdr->ipdMax;
1002179404Sobrien  if (count > 0)
1003179404Sobrien    {
1004179404Sobrien      size = swap->external_pdr_size;
1005179404Sobrien
1006179404Sobrien      epdr = bfd_malloc (size * count);
1007179404Sobrien      if (epdr == NULL)
1008179404Sobrien	goto error_return;
1009179404Sobrien
1010179404Sobrien      if (! _bfd_ecoff_get_accumulated_pdr (handle, (bfd_byte *) epdr))
1011179404Sobrien	goto error_return;
1012179404Sobrien
1013179404Sobrien      size = sizeof (RPDR);
1014179404Sobrien      rp = rpdr = bfd_malloc (size * count);
1015179404Sobrien      if (rpdr == NULL)
1016179404Sobrien	goto error_return;
1017179404Sobrien
1018179404Sobrien      size = sizeof (char *);
1019179404Sobrien      sv = bfd_malloc (size * count);
1020179404Sobrien      if (sv == NULL)
1021179404Sobrien	goto error_return;
1022179404Sobrien
1023179404Sobrien      count = hdr->isymMax;
1024179404Sobrien      size = swap->external_sym_size;
1025179404Sobrien      esym = bfd_malloc (size * count);
1026179404Sobrien      if (esym == NULL)
1027179404Sobrien	goto error_return;
1028179404Sobrien
1029179404Sobrien      if (! _bfd_ecoff_get_accumulated_sym (handle, (bfd_byte *) esym))
1030179404Sobrien	goto error_return;
1031179404Sobrien
1032179404Sobrien      count = hdr->issMax;
1033179404Sobrien      ss = bfd_malloc (count);
1034179404Sobrien      if (ss == NULL)
1035179404Sobrien	goto error_return;
1036218822Sdim      if (! _bfd_ecoff_get_accumulated_ss (handle, (bfd_byte *) ss))
1037179404Sobrien	goto error_return;
1038179404Sobrien
1039179404Sobrien      count = hdr->ipdMax;
1040179404Sobrien      for (i = 0; i < (unsigned long) count; i++, rp++)
1041179404Sobrien	{
1042179404Sobrien	  (*swap->swap_pdr_in) (abfd, epdr + i, &pdr);
1043179404Sobrien	  (*swap->swap_sym_in) (abfd, &esym[pdr.isym], &sym);
1044179404Sobrien	  rp->adr = sym.value;
1045179404Sobrien	  rp->regmask = pdr.regmask;
1046179404Sobrien	  rp->regoffset = pdr.regoffset;
1047179404Sobrien	  rp->fregmask = pdr.fregmask;
1048179404Sobrien	  rp->fregoffset = pdr.fregoffset;
1049179404Sobrien	  rp->frameoffset = pdr.frameoffset;
1050179404Sobrien	  rp->framereg = pdr.framereg;
1051179404Sobrien	  rp->pcreg = pdr.pcreg;
1052179404Sobrien	  rp->irpss = sindex;
1053179404Sobrien	  sv[i] = ss + sym.iss;
1054179404Sobrien	  sindex += strlen (sv[i]) + 1;
1055179404Sobrien	}
1056179404Sobrien    }
1057179404Sobrien
1058179404Sobrien  size = sizeof (struct rpdr_ext) * (count + 2) + sindex;
1059179404Sobrien  size = BFD_ALIGN (size, 16);
1060179404Sobrien  rtproc = bfd_alloc (abfd, size);
1061179404Sobrien  if (rtproc == NULL)
1062179404Sobrien    {
1063179404Sobrien      mips_elf_hash_table (info)->procedure_count = 0;
1064179404Sobrien      goto error_return;
1065179404Sobrien    }
1066179404Sobrien
1067179404Sobrien  mips_elf_hash_table (info)->procedure_count = count + 2;
1068179404Sobrien
1069179404Sobrien  erp = rtproc;
1070179404Sobrien  memset (erp, 0, sizeof (struct rpdr_ext));
1071179404Sobrien  erp++;
1072179404Sobrien  str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
1073179404Sobrien  strcpy (str, no_name_func);
1074179404Sobrien  str += strlen (no_name_func) + 1;
1075179404Sobrien  for (i = 0; i < count; i++)
1076179404Sobrien    {
1077179404Sobrien      ecoff_swap_rpdr_out (abfd, rpdr + i, erp + i);
1078179404Sobrien      strcpy (str, sv[i]);
1079179404Sobrien      str += strlen (sv[i]) + 1;
1080179404Sobrien    }
1081179404Sobrien  H_PUT_S32 (abfd, -1, (erp + count)->p_adr);
1082179404Sobrien
1083179404Sobrien  /* Set the size and contents of .rtproc section.  */
1084218822Sdim  s->size = size;
1085179404Sobrien  s->contents = rtproc;
1086179404Sobrien
1087179404Sobrien  /* Skip this section later on (I don't think this currently
1088179404Sobrien     matters, but someday it might).  */
1089218822Sdim  s->map_head.link_order = NULL;
1090179404Sobrien
1091179404Sobrien  if (epdr != NULL)
1092179404Sobrien    free (epdr);
1093179404Sobrien  if (rpdr != NULL)
1094179404Sobrien    free (rpdr);
1095179404Sobrien  if (esym != NULL)
1096179404Sobrien    free (esym);
1097179404Sobrien  if (ss != NULL)
1098179404Sobrien    free (ss);
1099179404Sobrien  if (sv != NULL)
1100179404Sobrien    free (sv);
1101179404Sobrien
1102179404Sobrien  return TRUE;
1103179404Sobrien
1104179404Sobrien error_return:
1105179404Sobrien  if (epdr != NULL)
1106179404Sobrien    free (epdr);
1107179404Sobrien  if (rpdr != NULL)
1108179404Sobrien    free (rpdr);
1109179404Sobrien  if (esym != NULL)
1110179404Sobrien    free (esym);
1111179404Sobrien  if (ss != NULL)
1112179404Sobrien    free (ss);
1113179404Sobrien  if (sv != NULL)
1114179404Sobrien    free (sv);
1115179404Sobrien  return FALSE;
1116179404Sobrien}
1117179404Sobrien
1118179404Sobrien/* Check the mips16 stubs for a particular symbol, and see if we can
1119179404Sobrien   discard them.  */
1120179404Sobrien
1121179404Sobrienstatic bfd_boolean
1122179404Sobrienmips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h,
1123179404Sobrien			     void *data ATTRIBUTE_UNUSED)
1124179404Sobrien{
1125179404Sobrien  if (h->root.root.type == bfd_link_hash_warning)
1126179404Sobrien    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
1127179404Sobrien
1128179404Sobrien  if (h->fn_stub != NULL
1129179404Sobrien      && ! h->need_fn_stub)
1130179404Sobrien    {
1131179404Sobrien      /* We don't need the fn_stub; the only references to this symbol
1132179404Sobrien         are 16 bit calls.  Clobber the size to 0 to prevent it from
1133179404Sobrien         being included in the link.  */
1134218822Sdim      h->fn_stub->size = 0;
1135179404Sobrien      h->fn_stub->flags &= ~SEC_RELOC;
1136179404Sobrien      h->fn_stub->reloc_count = 0;
1137179404Sobrien      h->fn_stub->flags |= SEC_EXCLUDE;
1138179404Sobrien    }
1139179404Sobrien
1140179404Sobrien  if (h->call_stub != NULL
1141179404Sobrien      && h->root.other == STO_MIPS16)
1142179404Sobrien    {
1143179404Sobrien      /* We don't need the call_stub; this is a 16 bit function, so
1144179404Sobrien         calls from other 16 bit functions are OK.  Clobber the size
1145179404Sobrien         to 0 to prevent it from being included in the link.  */
1146218822Sdim      h->call_stub->size = 0;
1147179404Sobrien      h->call_stub->flags &= ~SEC_RELOC;
1148179404Sobrien      h->call_stub->reloc_count = 0;
1149179404Sobrien      h->call_stub->flags |= SEC_EXCLUDE;
1150179404Sobrien    }
1151179404Sobrien
1152179404Sobrien  if (h->call_fp_stub != NULL
1153179404Sobrien      && h->root.other == STO_MIPS16)
1154179404Sobrien    {
1155179404Sobrien      /* We don't need the call_stub; this is a 16 bit function, so
1156179404Sobrien         calls from other 16 bit functions are OK.  Clobber the size
1157179404Sobrien         to 0 to prevent it from being included in the link.  */
1158218822Sdim      h->call_fp_stub->size = 0;
1159179404Sobrien      h->call_fp_stub->flags &= ~SEC_RELOC;
1160179404Sobrien      h->call_fp_stub->reloc_count = 0;
1161179404Sobrien      h->call_fp_stub->flags |= SEC_EXCLUDE;
1162179404Sobrien    }
1163179404Sobrien
1164179404Sobrien  return TRUE;
1165179404Sobrien}
1166179404Sobrien
1167218822Sdim/* R_MIPS16_26 is used for the mips16 jal and jalx instructions.
1168218822Sdim   Most mips16 instructions are 16 bits, but these instructions
1169218822Sdim   are 32 bits.
1170218822Sdim
1171218822Sdim   The format of these instructions is:
1172218822Sdim
1173218822Sdim   +--------------+--------------------------------+
1174218822Sdim   |     JALX     | X|   Imm 20:16  |   Imm 25:21  |
1175218822Sdim   +--------------+--------------------------------+
1176218822Sdim   |                Immediate  15:0                |
1177218822Sdim   +-----------------------------------------------+
1178218822Sdim
1179218822Sdim   JALX is the 5-bit value 00011.  X is 0 for jal, 1 for jalx.
1180218822Sdim   Note that the immediate value in the first word is swapped.
1181218822Sdim
1182218822Sdim   When producing a relocatable object file, R_MIPS16_26 is
1183218822Sdim   handled mostly like R_MIPS_26.  In particular, the addend is
1184218822Sdim   stored as a straight 26-bit value in a 32-bit instruction.
1185218822Sdim   (gas makes life simpler for itself by never adjusting a
1186218822Sdim   R_MIPS16_26 reloc to be against a section, so the addend is
1187218822Sdim   always zero).  However, the 32 bit instruction is stored as 2
1188218822Sdim   16-bit values, rather than a single 32-bit value.  In a
1189218822Sdim   big-endian file, the result is the same; in a little-endian
1190218822Sdim   file, the two 16-bit halves of the 32 bit value are swapped.
1191218822Sdim   This is so that a disassembler can recognize the jal
1192218822Sdim   instruction.
1193218822Sdim
1194218822Sdim   When doing a final link, R_MIPS16_26 is treated as a 32 bit
1195218822Sdim   instruction stored as two 16-bit values.  The addend A is the
1196218822Sdim   contents of the targ26 field.  The calculation is the same as
1197218822Sdim   R_MIPS_26.  When storing the calculated value, reorder the
1198218822Sdim   immediate value as shown above, and don't forget to store the
1199218822Sdim   value as two 16-bit values.
1200218822Sdim
1201218822Sdim   To put it in MIPS ABI terms, the relocation field is T-targ26-16,
1202218822Sdim   defined as
1203218822Sdim
1204218822Sdim   big-endian:
1205218822Sdim   +--------+----------------------+
1206218822Sdim   |        |                      |
1207218822Sdim   |        |    targ26-16         |
1208218822Sdim   |31    26|25                   0|
1209218822Sdim   +--------+----------------------+
1210218822Sdim
1211218822Sdim   little-endian:
1212218822Sdim   +----------+------+-------------+
1213218822Sdim   |          |      |             |
1214218822Sdim   |  sub1    |      |     sub2    |
1215218822Sdim   |0        9|10  15|16         31|
1216218822Sdim   +----------+--------------------+
1217218822Sdim   where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
1218218822Sdim   ((sub1 << 16) | sub2)).
1219218822Sdim
1220218822Sdim   When producing a relocatable object file, the calculation is
1221218822Sdim   (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
1222218822Sdim   When producing a fully linked file, the calculation is
1223218822Sdim   let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
1224218822Sdim   ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)
1225218822Sdim
1226218822Sdim   R_MIPS16_GPREL is used for GP-relative addressing in mips16
1227218822Sdim   mode.  A typical instruction will have a format like this:
1228218822Sdim
1229218822Sdim   +--------------+--------------------------------+
1230218822Sdim   |    EXTEND    |     Imm 10:5    |   Imm 15:11  |
1231218822Sdim   +--------------+--------------------------------+
1232218822Sdim   |    Major     |   rx   |   ry   |   Imm  4:0   |
1233218822Sdim   +--------------+--------------------------------+
1234218822Sdim
1235218822Sdim   EXTEND is the five bit value 11110.  Major is the instruction
1236218822Sdim   opcode.
1237218822Sdim
1238218822Sdim   This is handled exactly like R_MIPS_GPREL16, except that the
1239218822Sdim   addend is retrieved and stored as shown in this diagram; that
1240218822Sdim   is, the Imm fields above replace the V-rel16 field.
1241218822Sdim
1242218822Sdim   All we need to do here is shuffle the bits appropriately.  As
1243218822Sdim   above, the two 16-bit halves must be swapped on a
1244218822Sdim   little-endian system.
1245218822Sdim
1246218822Sdim   R_MIPS16_HI16 and R_MIPS16_LO16 are used in mips16 mode to
1247218822Sdim   access data when neither GP-relative nor PC-relative addressing
1248218822Sdim   can be used.  They are handled like R_MIPS_HI16 and R_MIPS_LO16,
1249218822Sdim   except that the addend is retrieved and stored as shown above
1250218822Sdim   for R_MIPS16_GPREL.
1251218822Sdim  */
1252218822Sdimvoid
1253218822Sdim_bfd_mips16_elf_reloc_unshuffle (bfd *abfd, int r_type,
1254218822Sdim				 bfd_boolean jal_shuffle, bfd_byte *data)
1255218822Sdim{
1256218822Sdim  bfd_vma extend, insn, val;
1257218822Sdim
1258218822Sdim  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
1259218822Sdim      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
1260218822Sdim    return;
1261218822Sdim
1262218822Sdim  /* Pick up the mips16 extend instruction and the real instruction.  */
1263218822Sdim  extend = bfd_get_16 (abfd, data);
1264218822Sdim  insn = bfd_get_16 (abfd, data + 2);
1265218822Sdim  if (r_type == R_MIPS16_26)
1266218822Sdim    {
1267218822Sdim      if (jal_shuffle)
1268218822Sdim	val = ((extend & 0xfc00) << 16) | ((extend & 0x3e0) << 11)
1269218822Sdim	      | ((extend & 0x1f) << 21) | insn;
1270218822Sdim      else
1271218822Sdim	val = extend << 16 | insn;
1272218822Sdim    }
1273218822Sdim  else
1274218822Sdim    val = ((extend & 0xf800) << 16) | ((insn & 0xffe0) << 11)
1275218822Sdim	  | ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
1276218822Sdim  bfd_put_32 (abfd, val, data);
1277218822Sdim}
1278218822Sdim
1279218822Sdimvoid
1280218822Sdim_bfd_mips16_elf_reloc_shuffle (bfd *abfd, int r_type,
1281218822Sdim			       bfd_boolean jal_shuffle, bfd_byte *data)
1282218822Sdim{
1283218822Sdim  bfd_vma extend, insn, val;
1284218822Sdim
1285218822Sdim  if (r_type != R_MIPS16_26 && r_type != R_MIPS16_GPREL
1286218822Sdim      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
1287218822Sdim    return;
1288218822Sdim
1289218822Sdim  val = bfd_get_32 (abfd, data);
1290218822Sdim  if (r_type == R_MIPS16_26)
1291218822Sdim    {
1292218822Sdim      if (jal_shuffle)
1293218822Sdim	{
1294218822Sdim	  insn = val & 0xffff;
1295218822Sdim	  extend = ((val >> 16) & 0xfc00) | ((val >> 11) & 0x3e0)
1296218822Sdim		   | ((val >> 21) & 0x1f);
1297218822Sdim	}
1298218822Sdim      else
1299218822Sdim	{
1300218822Sdim	  insn = val & 0xffff;
1301218822Sdim	  extend = val >> 16;
1302218822Sdim	}
1303218822Sdim    }
1304218822Sdim  else
1305218822Sdim    {
1306218822Sdim      insn = ((val >> 11) & 0xffe0) | (val & 0x1f);
1307218822Sdim      extend = ((val >> 16) & 0xf800) | ((val >> 11) & 0x1f) | (val & 0x7e0);
1308218822Sdim    }
1309218822Sdim  bfd_put_16 (abfd, insn, data + 2);
1310218822Sdim  bfd_put_16 (abfd, extend, data);
1311218822Sdim}
1312218822Sdim
1313179404Sobrienbfd_reloc_status_type
1314179404Sobrien_bfd_mips_elf_gprel16_with_gp (bfd *abfd, asymbol *symbol,
1315179404Sobrien			       arelent *reloc_entry, asection *input_section,
1316179404Sobrien			       bfd_boolean relocatable, void *data, bfd_vma gp)
1317179404Sobrien{
1318179404Sobrien  bfd_vma relocation;
1319179404Sobrien  bfd_signed_vma val;
1320179404Sobrien  bfd_reloc_status_type status;
1321179404Sobrien
1322179404Sobrien  if (bfd_is_com_section (symbol->section))
1323179404Sobrien    relocation = 0;
1324179404Sobrien  else
1325179404Sobrien    relocation = symbol->value;
1326179404Sobrien
1327179404Sobrien  relocation += symbol->section->output_section->vma;
1328179404Sobrien  relocation += symbol->section->output_offset;
1329179404Sobrien
1330218822Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
1331179404Sobrien    return bfd_reloc_outofrange;
1332179404Sobrien
1333179404Sobrien  /* Set val to the offset into the section or symbol.  */
1334179404Sobrien  val = reloc_entry->addend;
1335179404Sobrien
1336179404Sobrien  _bfd_mips_elf_sign_extend (val, 16);
1337179404Sobrien
1338179404Sobrien  /* Adjust val for the final section location and GP value.  If we
1339179404Sobrien     are producing relocatable output, we don't want to do this for
1340179404Sobrien     an external symbol.  */
1341179404Sobrien  if (! relocatable
1342179404Sobrien      || (symbol->flags & BSF_SECTION_SYM) != 0)
1343179404Sobrien    val += relocation - gp;
1344179404Sobrien
1345179404Sobrien  if (reloc_entry->howto->partial_inplace)
1346179404Sobrien    {
1347179404Sobrien      status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
1348179404Sobrien				       (bfd_byte *) data
1349179404Sobrien				       + reloc_entry->address);
1350179404Sobrien      if (status != bfd_reloc_ok)
1351179404Sobrien	return status;
1352179404Sobrien    }
1353179404Sobrien  else
1354179404Sobrien    reloc_entry->addend = val;
1355179404Sobrien
1356179404Sobrien  if (relocatable)
1357179404Sobrien    reloc_entry->address += input_section->output_offset;
1358179404Sobrien
1359179404Sobrien  return bfd_reloc_ok;
1360179404Sobrien}
1361179404Sobrien
1362179404Sobrien/* Used to store a REL high-part relocation such as R_MIPS_HI16 or
1363179404Sobrien   R_MIPS_GOT16.  REL is the relocation, INPUT_SECTION is the section
1364179404Sobrien   that contains the relocation field and DATA points to the start of
1365179404Sobrien   INPUT_SECTION.  */
1366179404Sobrien
1367179404Sobrienstruct mips_hi16
1368179404Sobrien{
1369179404Sobrien  struct mips_hi16 *next;
1370179404Sobrien  bfd_byte *data;
1371179404Sobrien  asection *input_section;
1372179404Sobrien  arelent rel;
1373179404Sobrien};
1374179404Sobrien
1375179404Sobrien/* FIXME: This should not be a static variable.  */
1376179404Sobrien
1377179404Sobrienstatic struct mips_hi16 *mips_hi16_list;
1378179404Sobrien
1379179404Sobrien/* A howto special_function for REL *HI16 relocations.  We can only
1380179404Sobrien   calculate the correct value once we've seen the partnering
1381179404Sobrien   *LO16 relocation, so just save the information for later.
1382179404Sobrien
1383179404Sobrien   The ABI requires that the *LO16 immediately follow the *HI16.
1384179404Sobrien   However, as a GNU extension, we permit an arbitrary number of
1385179404Sobrien   *HI16s to be associated with a single *LO16.  This significantly
1386179404Sobrien   simplies the relocation handling in gcc.  */
1387179404Sobrien
1388179404Sobrienbfd_reloc_status_type
1389179404Sobrien_bfd_mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
1390179404Sobrien			  asymbol *symbol ATTRIBUTE_UNUSED, void *data,
1391179404Sobrien			  asection *input_section, bfd *output_bfd,
1392179404Sobrien			  char **error_message ATTRIBUTE_UNUSED)
1393179404Sobrien{
1394179404Sobrien  struct mips_hi16 *n;
1395179404Sobrien
1396218822Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
1397179404Sobrien    return bfd_reloc_outofrange;
1398179404Sobrien
1399179404Sobrien  n = bfd_malloc (sizeof *n);
1400179404Sobrien  if (n == NULL)
1401179404Sobrien    return bfd_reloc_outofrange;
1402179404Sobrien
1403179404Sobrien  n->next = mips_hi16_list;
1404179404Sobrien  n->data = data;
1405179404Sobrien  n->input_section = input_section;
1406179404Sobrien  n->rel = *reloc_entry;
1407179404Sobrien  mips_hi16_list = n;
1408179404Sobrien
1409179404Sobrien  if (output_bfd != NULL)
1410179404Sobrien    reloc_entry->address += input_section->output_offset;
1411179404Sobrien
1412179404Sobrien  return bfd_reloc_ok;
1413179404Sobrien}
1414179404Sobrien
1415179404Sobrien/* A howto special_function for REL R_MIPS_GOT16 relocations.  This is just
1416179404Sobrien   like any other 16-bit relocation when applied to global symbols, but is
1417179404Sobrien   treated in the same as R_MIPS_HI16 when applied to local symbols.  */
1418179404Sobrien
1419179404Sobrienbfd_reloc_status_type
1420179404Sobrien_bfd_mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
1421179404Sobrien			   void *data, asection *input_section,
1422179404Sobrien			   bfd *output_bfd, char **error_message)
1423179404Sobrien{
1424179404Sobrien  if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
1425179404Sobrien      || bfd_is_und_section (bfd_get_section (symbol))
1426179404Sobrien      || bfd_is_com_section (bfd_get_section (symbol)))
1427179404Sobrien    /* The relocation is against a global symbol.  */
1428179404Sobrien    return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
1429179404Sobrien					input_section, output_bfd,
1430179404Sobrien					error_message);
1431179404Sobrien
1432179404Sobrien  return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
1433179404Sobrien				   input_section, output_bfd, error_message);
1434179404Sobrien}
1435179404Sobrien
1436179404Sobrien/* A howto special_function for REL *LO16 relocations.  The *LO16 itself
1437179404Sobrien   is a straightforward 16 bit inplace relocation, but we must deal with
1438179404Sobrien   any partnering high-part relocations as well.  */
1439179404Sobrien
1440179404Sobrienbfd_reloc_status_type
1441179404Sobrien_bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
1442179404Sobrien			  void *data, asection *input_section,
1443179404Sobrien			  bfd *output_bfd, char **error_message)
1444179404Sobrien{
1445179404Sobrien  bfd_vma vallo;
1446218822Sdim  bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
1447179404Sobrien
1448218822Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
1449179404Sobrien    return bfd_reloc_outofrange;
1450179404Sobrien
1451218822Sdim  _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
1452218822Sdim				   location);
1453218822Sdim  vallo = bfd_get_32 (abfd, location);
1454218822Sdim  _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, FALSE,
1455218822Sdim				 location);
1456218822Sdim
1457179404Sobrien  while (mips_hi16_list != NULL)
1458179404Sobrien    {
1459179404Sobrien      bfd_reloc_status_type ret;
1460179404Sobrien      struct mips_hi16 *hi;
1461179404Sobrien
1462179404Sobrien      hi = mips_hi16_list;
1463179404Sobrien
1464179404Sobrien      /* R_MIPS_GOT16 relocations are something of a special case.  We
1465179404Sobrien	 want to install the addend in the same way as for a R_MIPS_HI16
1466179404Sobrien	 relocation (with a rightshift of 16).  However, since GOT16
1467179404Sobrien	 relocations can also be used with global symbols, their howto
1468179404Sobrien	 has a rightshift of 0.  */
1469179404Sobrien      if (hi->rel.howto->type == R_MIPS_GOT16)
1470179404Sobrien	hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, FALSE);
1471179404Sobrien
1472179404Sobrien      /* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that any
1473179404Sobrien	 carry or borrow will induce a change of +1 or -1 in the high part.  */
1474179404Sobrien      hi->rel.addend += (vallo + 0x8000) & 0xffff;
1475179404Sobrien
1476179404Sobrien      ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
1477179404Sobrien					 hi->input_section, output_bfd,
1478179404Sobrien					 error_message);
1479179404Sobrien      if (ret != bfd_reloc_ok)
1480179404Sobrien	return ret;
1481179404Sobrien
1482179404Sobrien      mips_hi16_list = hi->next;
1483179404Sobrien      free (hi);
1484179404Sobrien    }
1485179404Sobrien
1486179404Sobrien  return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
1487179404Sobrien				      input_section, output_bfd,
1488179404Sobrien				      error_message);
1489179404Sobrien}
1490179404Sobrien
1491179404Sobrien/* A generic howto special_function.  This calculates and installs the
1492179404Sobrien   relocation itself, thus avoiding the oft-discussed problems in
1493179404Sobrien   bfd_perform_relocation and bfd_install_relocation.  */
1494179404Sobrien
1495179404Sobrienbfd_reloc_status_type
1496179404Sobrien_bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
1497179404Sobrien			     asymbol *symbol, void *data ATTRIBUTE_UNUSED,
1498179404Sobrien			     asection *input_section, bfd *output_bfd,
1499179404Sobrien			     char **error_message ATTRIBUTE_UNUSED)
1500179404Sobrien{
1501179404Sobrien  bfd_signed_vma val;
1502179404Sobrien  bfd_reloc_status_type status;
1503179404Sobrien  bfd_boolean relocatable;
1504179404Sobrien
1505179404Sobrien  relocatable = (output_bfd != NULL);
1506179404Sobrien
1507218822Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
1508179404Sobrien    return bfd_reloc_outofrange;
1509179404Sobrien
1510179404Sobrien  /* Build up the field adjustment in VAL.  */
1511179404Sobrien  val = 0;
1512179404Sobrien  if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
1513179404Sobrien    {
1514179404Sobrien      /* Either we're calculating the final field value or we have a
1515179404Sobrien	 relocation against a section symbol.  Add in the section's
1516179404Sobrien	 offset or address.  */
1517179404Sobrien      val += symbol->section->output_section->vma;
1518179404Sobrien      val += symbol->section->output_offset;
1519179404Sobrien    }
1520179404Sobrien
1521179404Sobrien  if (!relocatable)
1522179404Sobrien    {
1523179404Sobrien      /* We're calculating the final field value.  Add in the symbol's value
1524179404Sobrien	 and, if pc-relative, subtract the address of the field itself.  */
1525179404Sobrien      val += symbol->value;
1526179404Sobrien      if (reloc_entry->howto->pc_relative)
1527179404Sobrien	{
1528179404Sobrien	  val -= input_section->output_section->vma;
1529179404Sobrien	  val -= input_section->output_offset;
1530179404Sobrien	  val -= reloc_entry->address;
1531179404Sobrien	}
1532179404Sobrien    }
1533179404Sobrien
1534179404Sobrien  /* VAL is now the final adjustment.  If we're keeping this relocation
1535179404Sobrien     in the output file, and if the relocation uses a separate addend,
1536179404Sobrien     we just need to add VAL to that addend.  Otherwise we need to add
1537179404Sobrien     VAL to the relocation field itself.  */
1538179404Sobrien  if (relocatable && !reloc_entry->howto->partial_inplace)
1539179404Sobrien    reloc_entry->addend += val;
1540179404Sobrien  else
1541179404Sobrien    {
1542218822Sdim      bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
1543218822Sdim
1544179404Sobrien      /* Add in the separate addend, if any.  */
1545179404Sobrien      val += reloc_entry->addend;
1546179404Sobrien
1547179404Sobrien      /* Add VAL to the relocation field.  */
1548218822Sdim      _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
1549218822Sdim				       location);
1550179404Sobrien      status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
1551218822Sdim				       location);
1552218822Sdim      _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, FALSE,
1553218822Sdim				     location);
1554218822Sdim
1555179404Sobrien      if (status != bfd_reloc_ok)
1556179404Sobrien	return status;
1557179404Sobrien    }
1558179404Sobrien
1559179404Sobrien  if (relocatable)
1560179404Sobrien    reloc_entry->address += input_section->output_offset;
1561179404Sobrien
1562179404Sobrien  return bfd_reloc_ok;
1563179404Sobrien}
1564179404Sobrien
1565179404Sobrien/* Swap an entry in a .gptab section.  Note that these routines rely
1566179404Sobrien   on the equivalence of the two elements of the union.  */
1567179404Sobrien
1568179404Sobrienstatic void
1569179404Sobrienbfd_mips_elf32_swap_gptab_in (bfd *abfd, const Elf32_External_gptab *ex,
1570179404Sobrien			      Elf32_gptab *in)
1571179404Sobrien{
1572179404Sobrien  in->gt_entry.gt_g_value = H_GET_32 (abfd, ex->gt_entry.gt_g_value);
1573179404Sobrien  in->gt_entry.gt_bytes = H_GET_32 (abfd, ex->gt_entry.gt_bytes);
1574179404Sobrien}
1575179404Sobrien
1576179404Sobrienstatic void
1577179404Sobrienbfd_mips_elf32_swap_gptab_out (bfd *abfd, const Elf32_gptab *in,
1578179404Sobrien			       Elf32_External_gptab *ex)
1579179404Sobrien{
1580179404Sobrien  H_PUT_32 (abfd, in->gt_entry.gt_g_value, ex->gt_entry.gt_g_value);
1581179404Sobrien  H_PUT_32 (abfd, in->gt_entry.gt_bytes, ex->gt_entry.gt_bytes);
1582179404Sobrien}
1583179404Sobrien
1584179404Sobrienstatic void
1585179404Sobrienbfd_elf32_swap_compact_rel_out (bfd *abfd, const Elf32_compact_rel *in,
1586179404Sobrien				Elf32_External_compact_rel *ex)
1587179404Sobrien{
1588179404Sobrien  H_PUT_32 (abfd, in->id1, ex->id1);
1589179404Sobrien  H_PUT_32 (abfd, in->num, ex->num);
1590179404Sobrien  H_PUT_32 (abfd, in->id2, ex->id2);
1591179404Sobrien  H_PUT_32 (abfd, in->offset, ex->offset);
1592179404Sobrien  H_PUT_32 (abfd, in->reserved0, ex->reserved0);
1593179404Sobrien  H_PUT_32 (abfd, in->reserved1, ex->reserved1);
1594179404Sobrien}
1595179404Sobrien
1596179404Sobrienstatic void
1597179404Sobrienbfd_elf32_swap_crinfo_out (bfd *abfd, const Elf32_crinfo *in,
1598179404Sobrien			   Elf32_External_crinfo *ex)
1599179404Sobrien{
1600179404Sobrien  unsigned long l;
1601179404Sobrien
1602179404Sobrien  l = (((in->ctype & CRINFO_CTYPE) << CRINFO_CTYPE_SH)
1603179404Sobrien       | ((in->rtype & CRINFO_RTYPE) << CRINFO_RTYPE_SH)
1604179404Sobrien       | ((in->dist2to & CRINFO_DIST2TO) << CRINFO_DIST2TO_SH)
1605179404Sobrien       | ((in->relvaddr & CRINFO_RELVADDR) << CRINFO_RELVADDR_SH));
1606179404Sobrien  H_PUT_32 (abfd, l, ex->info);
1607179404Sobrien  H_PUT_32 (abfd, in->konst, ex->konst);
1608179404Sobrien  H_PUT_32 (abfd, in->vaddr, ex->vaddr);
1609179404Sobrien}
1610179404Sobrien
1611179404Sobrien/* A .reginfo section holds a single Elf32_RegInfo structure.  These
1612179404Sobrien   routines swap this structure in and out.  They are used outside of
1613179404Sobrien   BFD, so they are globally visible.  */
1614179404Sobrien
1615179404Sobrienvoid
1616179404Sobrienbfd_mips_elf32_swap_reginfo_in (bfd *abfd, const Elf32_External_RegInfo *ex,
1617179404Sobrien				Elf32_RegInfo *in)
1618179404Sobrien{
1619179404Sobrien  in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
1620179404Sobrien  in->ri_cprmask[0] = H_GET_32 (abfd, ex->ri_cprmask[0]);
1621179404Sobrien  in->ri_cprmask[1] = H_GET_32 (abfd, ex->ri_cprmask[1]);
1622179404Sobrien  in->ri_cprmask[2] = H_GET_32 (abfd, ex->ri_cprmask[2]);
1623179404Sobrien  in->ri_cprmask[3] = H_GET_32 (abfd, ex->ri_cprmask[3]);
1624179404Sobrien  in->ri_gp_value = H_GET_32 (abfd, ex->ri_gp_value);
1625179404Sobrien}
1626179404Sobrien
1627179404Sobrienvoid
1628179404Sobrienbfd_mips_elf32_swap_reginfo_out (bfd *abfd, const Elf32_RegInfo *in,
1629179404Sobrien				 Elf32_External_RegInfo *ex)
1630179404Sobrien{
1631179404Sobrien  H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
1632179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[0], ex->ri_cprmask[0]);
1633179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[1], ex->ri_cprmask[1]);
1634179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[2], ex->ri_cprmask[2]);
1635179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[3], ex->ri_cprmask[3]);
1636179404Sobrien  H_PUT_32 (abfd, in->ri_gp_value, ex->ri_gp_value);
1637179404Sobrien}
1638179404Sobrien
1639179404Sobrien/* In the 64 bit ABI, the .MIPS.options section holds register
1640179404Sobrien   information in an Elf64_Reginfo structure.  These routines swap
1641179404Sobrien   them in and out.  They are globally visible because they are used
1642179404Sobrien   outside of BFD.  These routines are here so that gas can call them
1643179404Sobrien   without worrying about whether the 64 bit ABI has been included.  */
1644179404Sobrien
1645179404Sobrienvoid
1646179404Sobrienbfd_mips_elf64_swap_reginfo_in (bfd *abfd, const Elf64_External_RegInfo *ex,
1647179404Sobrien				Elf64_Internal_RegInfo *in)
1648179404Sobrien{
1649179404Sobrien  in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
1650179404Sobrien  in->ri_pad = H_GET_32 (abfd, ex->ri_pad);
1651179404Sobrien  in->ri_cprmask[0] = H_GET_32 (abfd, ex->ri_cprmask[0]);
1652179404Sobrien  in->ri_cprmask[1] = H_GET_32 (abfd, ex->ri_cprmask[1]);
1653179404Sobrien  in->ri_cprmask[2] = H_GET_32 (abfd, ex->ri_cprmask[2]);
1654179404Sobrien  in->ri_cprmask[3] = H_GET_32 (abfd, ex->ri_cprmask[3]);
1655179404Sobrien  in->ri_gp_value = H_GET_64 (abfd, ex->ri_gp_value);
1656179404Sobrien}
1657179404Sobrien
1658179404Sobrienvoid
1659179404Sobrienbfd_mips_elf64_swap_reginfo_out (bfd *abfd, const Elf64_Internal_RegInfo *in,
1660179404Sobrien				 Elf64_External_RegInfo *ex)
1661179404Sobrien{
1662179404Sobrien  H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
1663179404Sobrien  H_PUT_32 (abfd, in->ri_pad, ex->ri_pad);
1664179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[0], ex->ri_cprmask[0]);
1665179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[1], ex->ri_cprmask[1]);
1666179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[2], ex->ri_cprmask[2]);
1667179404Sobrien  H_PUT_32 (abfd, in->ri_cprmask[3], ex->ri_cprmask[3]);
1668179404Sobrien  H_PUT_64 (abfd, in->ri_gp_value, ex->ri_gp_value);
1669179404Sobrien}
1670179404Sobrien
1671179404Sobrien/* Swap in an options header.  */
1672179404Sobrien
1673179404Sobrienvoid
1674179404Sobrienbfd_mips_elf_swap_options_in (bfd *abfd, const Elf_External_Options *ex,
1675179404Sobrien			      Elf_Internal_Options *in)
1676179404Sobrien{
1677179404Sobrien  in->kind = H_GET_8 (abfd, ex->kind);
1678179404Sobrien  in->size = H_GET_8 (abfd, ex->size);
1679179404Sobrien  in->section = H_GET_16 (abfd, ex->section);
1680179404Sobrien  in->info = H_GET_32 (abfd, ex->info);
1681179404Sobrien}
1682179404Sobrien
1683179404Sobrien/* Swap out an options header.  */
1684179404Sobrien
1685179404Sobrienvoid
1686179404Sobrienbfd_mips_elf_swap_options_out (bfd *abfd, const Elf_Internal_Options *in,
1687179404Sobrien			       Elf_External_Options *ex)
1688179404Sobrien{
1689179404Sobrien  H_PUT_8 (abfd, in->kind, ex->kind);
1690179404Sobrien  H_PUT_8 (abfd, in->size, ex->size);
1691179404Sobrien  H_PUT_16 (abfd, in->section, ex->section);
1692179404Sobrien  H_PUT_32 (abfd, in->info, ex->info);
1693179404Sobrien}
1694179404Sobrien
1695179404Sobrien/* This function is called via qsort() to sort the dynamic relocation
1696179404Sobrien   entries by increasing r_symndx value.  */
1697179404Sobrien
1698179404Sobrienstatic int
1699179404Sobriensort_dynamic_relocs (const void *arg1, const void *arg2)
1700179404Sobrien{
1701179404Sobrien  Elf_Internal_Rela int_reloc1;
1702179404Sobrien  Elf_Internal_Rela int_reloc2;
1703218822Sdim  int diff;
1704179404Sobrien
1705179404Sobrien  bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg1, &int_reloc1);
1706179404Sobrien  bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg2, &int_reloc2);
1707179404Sobrien
1708218822Sdim  diff = ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info);
1709218822Sdim  if (diff != 0)
1710218822Sdim    return diff;
1711218822Sdim
1712218822Sdim  if (int_reloc1.r_offset < int_reloc2.r_offset)
1713218822Sdim    return -1;
1714218822Sdim  if (int_reloc1.r_offset > int_reloc2.r_offset)
1715218822Sdim    return 1;
1716218822Sdim  return 0;
1717179404Sobrien}
1718179404Sobrien
1719179404Sobrien/* Like sort_dynamic_relocs, but used for elf64 relocations.  */
1720179404Sobrien
1721179404Sobrienstatic int
1722218822Sdimsort_dynamic_relocs_64 (const void *arg1 ATTRIBUTE_UNUSED,
1723218822Sdim			const void *arg2 ATTRIBUTE_UNUSED)
1724179404Sobrien{
1725218822Sdim#ifdef BFD64
1726179404Sobrien  Elf_Internal_Rela int_reloc1[3];
1727179404Sobrien  Elf_Internal_Rela int_reloc2[3];
1728179404Sobrien
1729179404Sobrien  (*get_elf_backend_data (reldyn_sorting_bfd)->s->swap_reloc_in)
1730179404Sobrien    (reldyn_sorting_bfd, arg1, int_reloc1);
1731179404Sobrien  (*get_elf_backend_data (reldyn_sorting_bfd)->s->swap_reloc_in)
1732179404Sobrien    (reldyn_sorting_bfd, arg2, int_reloc2);
1733179404Sobrien
1734218822Sdim  if (ELF64_R_SYM (int_reloc1[0].r_info) < ELF64_R_SYM (int_reloc2[0].r_info))
1735218822Sdim    return -1;
1736218822Sdim  if (ELF64_R_SYM (int_reloc1[0].r_info) > ELF64_R_SYM (int_reloc2[0].r_info))
1737218822Sdim    return 1;
1738218822Sdim
1739218822Sdim  if (int_reloc1[0].r_offset < int_reloc2[0].r_offset)
1740218822Sdim    return -1;
1741218822Sdim  if (int_reloc1[0].r_offset > int_reloc2[0].r_offset)
1742218822Sdim    return 1;
1743218822Sdim  return 0;
1744218822Sdim#else
1745218822Sdim  abort ();
1746218822Sdim#endif
1747179404Sobrien}
1748179404Sobrien
1749179404Sobrien
1750179404Sobrien/* This routine is used to write out ECOFF debugging external symbol
1751179404Sobrien   information.  It is called via mips_elf_link_hash_traverse.  The
1752179404Sobrien   ECOFF external symbol information must match the ELF external
1753179404Sobrien   symbol information.  Unfortunately, at this point we don't know
1754179404Sobrien   whether a symbol is required by reloc information, so the two
1755179404Sobrien   tables may wind up being different.  We must sort out the external
1756179404Sobrien   symbol information before we can set the final size of the .mdebug
1757179404Sobrien   section, and we must set the size of the .mdebug section before we
1758179404Sobrien   can relocate any sections, and we can't know which symbols are
1759179404Sobrien   required by relocation until we relocate the sections.
1760179404Sobrien   Fortunately, it is relatively unlikely that any symbol will be
1761179404Sobrien   stripped but required by a reloc.  In particular, it can not happen
1762179404Sobrien   when generating a final executable.  */
1763179404Sobrien
1764179404Sobrienstatic bfd_boolean
1765179404Sobrienmips_elf_output_extsym (struct mips_elf_link_hash_entry *h, void *data)
1766179404Sobrien{
1767179404Sobrien  struct extsym_info *einfo = data;
1768179404Sobrien  bfd_boolean strip;
1769179404Sobrien  asection *sec, *output_section;
1770179404Sobrien
1771179404Sobrien  if (h->root.root.type == bfd_link_hash_warning)
1772179404Sobrien    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
1773179404Sobrien
1774179404Sobrien  if (h->root.indx == -2)
1775179404Sobrien    strip = FALSE;
1776218822Sdim  else if ((h->root.def_dynamic
1777218822Sdim	    || h->root.ref_dynamic
1778218822Sdim	    || h->root.type == bfd_link_hash_new)
1779218822Sdim	   && !h->root.def_regular
1780218822Sdim	   && !h->root.ref_regular)
1781179404Sobrien    strip = TRUE;
1782179404Sobrien  else if (einfo->info->strip == strip_all
1783179404Sobrien	   || (einfo->info->strip == strip_some
1784179404Sobrien	       && bfd_hash_lookup (einfo->info->keep_hash,
1785179404Sobrien				   h->root.root.root.string,
1786179404Sobrien				   FALSE, FALSE) == NULL))
1787179404Sobrien    strip = TRUE;
1788179404Sobrien  else
1789179404Sobrien    strip = FALSE;
1790179404Sobrien
1791179404Sobrien  if (strip)
1792179404Sobrien    return TRUE;
1793179404Sobrien
1794179404Sobrien  if (h->esym.ifd == -2)
1795179404Sobrien    {
1796179404Sobrien      h->esym.jmptbl = 0;
1797179404Sobrien      h->esym.cobol_main = 0;
1798179404Sobrien      h->esym.weakext = 0;
1799179404Sobrien      h->esym.reserved = 0;
1800179404Sobrien      h->esym.ifd = ifdNil;
1801179404Sobrien      h->esym.asym.value = 0;
1802179404Sobrien      h->esym.asym.st = stGlobal;
1803179404Sobrien
1804179404Sobrien      if (h->root.root.type == bfd_link_hash_undefined
1805179404Sobrien	  || h->root.root.type == bfd_link_hash_undefweak)
1806179404Sobrien	{
1807179404Sobrien	  const char *name;
1808179404Sobrien
1809179404Sobrien	  /* Use undefined class.  Also, set class and type for some
1810179404Sobrien             special symbols.  */
1811179404Sobrien	  name = h->root.root.root.string;
1812179404Sobrien	  if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
1813179404Sobrien	      || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
1814179404Sobrien	    {
1815179404Sobrien	      h->esym.asym.sc = scData;
1816179404Sobrien	      h->esym.asym.st = stLabel;
1817179404Sobrien	      h->esym.asym.value = 0;
1818179404Sobrien	    }
1819179404Sobrien	  else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
1820179404Sobrien	    {
1821179404Sobrien	      h->esym.asym.sc = scAbs;
1822179404Sobrien	      h->esym.asym.st = stLabel;
1823179404Sobrien	      h->esym.asym.value =
1824179404Sobrien		mips_elf_hash_table (einfo->info)->procedure_count;
1825179404Sobrien	    }
1826179404Sobrien	  else if (strcmp (name, "_gp_disp") == 0 && ! NEWABI_P (einfo->abfd))
1827179404Sobrien	    {
1828179404Sobrien	      h->esym.asym.sc = scAbs;
1829179404Sobrien	      h->esym.asym.st = stLabel;
1830179404Sobrien	      h->esym.asym.value = elf_gp (einfo->abfd);
1831179404Sobrien	    }
1832179404Sobrien	  else
1833179404Sobrien	    h->esym.asym.sc = scUndefined;
1834179404Sobrien	}
1835179404Sobrien      else if (h->root.root.type != bfd_link_hash_defined
1836179404Sobrien	  && h->root.root.type != bfd_link_hash_defweak)
1837179404Sobrien	h->esym.asym.sc = scAbs;
1838179404Sobrien      else
1839179404Sobrien	{
1840179404Sobrien	  const char *name;
1841179404Sobrien
1842179404Sobrien	  sec = h->root.root.u.def.section;
1843179404Sobrien	  output_section = sec->output_section;
1844179404Sobrien
1845179404Sobrien	  /* When making a shared library and symbol h is the one from
1846179404Sobrien	     the another shared library, OUTPUT_SECTION may be null.  */
1847179404Sobrien	  if (output_section == NULL)
1848179404Sobrien	    h->esym.asym.sc = scUndefined;
1849179404Sobrien	  else
1850179404Sobrien	    {
1851179404Sobrien	      name = bfd_section_name (output_section->owner, output_section);
1852179404Sobrien
1853179404Sobrien	      if (strcmp (name, ".text") == 0)
1854179404Sobrien		h->esym.asym.sc = scText;
1855179404Sobrien	      else if (strcmp (name, ".data") == 0)
1856179404Sobrien		h->esym.asym.sc = scData;
1857179404Sobrien	      else if (strcmp (name, ".sdata") == 0)
1858179404Sobrien		h->esym.asym.sc = scSData;
1859179404Sobrien	      else if (strcmp (name, ".rodata") == 0
1860179404Sobrien		       || strcmp (name, ".rdata") == 0)
1861179404Sobrien		h->esym.asym.sc = scRData;
1862179404Sobrien	      else if (strcmp (name, ".bss") == 0)
1863179404Sobrien		h->esym.asym.sc = scBss;
1864179404Sobrien	      else if (strcmp (name, ".sbss") == 0)
1865179404Sobrien		h->esym.asym.sc = scSBss;
1866179404Sobrien	      else if (strcmp (name, ".init") == 0)
1867179404Sobrien		h->esym.asym.sc = scInit;
1868179404Sobrien	      else if (strcmp (name, ".fini") == 0)
1869179404Sobrien		h->esym.asym.sc = scFini;
1870179404Sobrien	      else
1871179404Sobrien		h->esym.asym.sc = scAbs;
1872179404Sobrien	    }
1873179404Sobrien	}
1874179404Sobrien
1875179404Sobrien      h->esym.asym.reserved = 0;
1876179404Sobrien      h->esym.asym.index = indexNil;
1877179404Sobrien    }
1878179404Sobrien
1879179404Sobrien  if (h->root.root.type == bfd_link_hash_common)
1880179404Sobrien    h->esym.asym.value = h->root.root.u.c.size;
1881179404Sobrien  else if (h->root.root.type == bfd_link_hash_defined
1882179404Sobrien	   || h->root.root.type == bfd_link_hash_defweak)
1883179404Sobrien    {
1884179404Sobrien      if (h->esym.asym.sc == scCommon)
1885179404Sobrien	h->esym.asym.sc = scBss;
1886179404Sobrien      else if (h->esym.asym.sc == scSCommon)
1887179404Sobrien	h->esym.asym.sc = scSBss;
1888179404Sobrien
1889179404Sobrien      sec = h->root.root.u.def.section;
1890179404Sobrien      output_section = sec->output_section;
1891179404Sobrien      if (output_section != NULL)
1892179404Sobrien	h->esym.asym.value = (h->root.root.u.def.value
1893179404Sobrien			      + sec->output_offset
1894179404Sobrien			      + output_section->vma);
1895179404Sobrien      else
1896179404Sobrien	h->esym.asym.value = 0;
1897179404Sobrien    }
1898218822Sdim  else if (h->root.needs_plt)
1899179404Sobrien    {
1900179404Sobrien      struct mips_elf_link_hash_entry *hd = h;
1901179404Sobrien      bfd_boolean no_fn_stub = h->no_fn_stub;
1902179404Sobrien
1903179404Sobrien      while (hd->root.root.type == bfd_link_hash_indirect)
1904179404Sobrien	{
1905179404Sobrien	  hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
1906179404Sobrien	  no_fn_stub = no_fn_stub || hd->no_fn_stub;
1907179404Sobrien	}
1908179404Sobrien
1909179404Sobrien      if (!no_fn_stub)
1910179404Sobrien	{
1911179404Sobrien	  /* Set type and value for a symbol with a function stub.  */
1912179404Sobrien	  h->esym.asym.st = stProc;
1913179404Sobrien	  sec = hd->root.root.u.def.section;
1914179404Sobrien	  if (sec == NULL)
1915179404Sobrien	    h->esym.asym.value = 0;
1916179404Sobrien	  else
1917179404Sobrien	    {
1918179404Sobrien	      output_section = sec->output_section;
1919179404Sobrien	      if (output_section != NULL)
1920179404Sobrien		h->esym.asym.value = (hd->root.plt.offset
1921179404Sobrien				      + sec->output_offset
1922179404Sobrien				      + output_section->vma);
1923179404Sobrien	      else
1924179404Sobrien		h->esym.asym.value = 0;
1925179404Sobrien	    }
1926179404Sobrien	}
1927179404Sobrien    }
1928179404Sobrien
1929179404Sobrien  if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
1930179404Sobrien				      h->root.root.root.string,
1931179404Sobrien				      &h->esym))
1932179404Sobrien    {
1933179404Sobrien      einfo->failed = TRUE;
1934179404Sobrien      return FALSE;
1935179404Sobrien    }
1936179404Sobrien
1937179404Sobrien  return TRUE;
1938179404Sobrien}
1939179404Sobrien
1940179404Sobrien/* A comparison routine used to sort .gptab entries.  */
1941179404Sobrien
1942179404Sobrienstatic int
1943179404Sobriengptab_compare (const void *p1, const void *p2)
1944179404Sobrien{
1945179404Sobrien  const Elf32_gptab *a1 = p1;
1946179404Sobrien  const Elf32_gptab *a2 = p2;
1947179404Sobrien
1948179404Sobrien  return a1->gt_entry.gt_g_value - a2->gt_entry.gt_g_value;
1949179404Sobrien}
1950179404Sobrien
1951179404Sobrien/* Functions to manage the got entry hash table.  */
1952179404Sobrien
1953179404Sobrien/* Use all 64 bits of a bfd_vma for the computation of a 32-bit
1954179404Sobrien   hash number.  */
1955179404Sobrien
1956179404Sobrienstatic INLINE hashval_t
1957179404Sobrienmips_elf_hash_bfd_vma (bfd_vma addr)
1958179404Sobrien{
1959179404Sobrien#ifdef BFD64
1960179404Sobrien  return addr + (addr >> 32);
1961179404Sobrien#else
1962179404Sobrien  return addr;
1963179404Sobrien#endif
1964179404Sobrien}
1965179404Sobrien
1966179404Sobrien/* got_entries only match if they're identical, except for gotidx, so
1967179404Sobrien   use all fields to compute the hash, and compare the appropriate
1968179404Sobrien   union members.  */
1969179404Sobrien
1970179404Sobrienstatic hashval_t
1971179404Sobrienmips_elf_got_entry_hash (const void *entry_)
1972179404Sobrien{
1973179404Sobrien  const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
1974179404Sobrien
1975179404Sobrien  return entry->symndx
1976218822Sdim    + ((entry->tls_type & GOT_TLS_LDM) << 17)
1977179404Sobrien    + (! entry->abfd ? mips_elf_hash_bfd_vma (entry->d.address)
1978179404Sobrien       : entry->abfd->id
1979179404Sobrien         + (entry->symndx >= 0 ? mips_elf_hash_bfd_vma (entry->d.addend)
1980179404Sobrien	    : entry->d.h->root.root.root.hash));
1981179404Sobrien}
1982179404Sobrien
1983179404Sobrienstatic int
1984179404Sobrienmips_elf_got_entry_eq (const void *entry1, const void *entry2)
1985179404Sobrien{
1986179404Sobrien  const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
1987179404Sobrien  const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
1988179404Sobrien
1989218822Sdim  /* An LDM entry can only match another LDM entry.  */
1990218822Sdim  if ((e1->tls_type ^ e2->tls_type) & GOT_TLS_LDM)
1991218822Sdim    return 0;
1992218822Sdim
1993179404Sobrien  return e1->abfd == e2->abfd && e1->symndx == e2->symndx
1994179404Sobrien    && (! e1->abfd ? e1->d.address == e2->d.address
1995179404Sobrien	: e1->symndx >= 0 ? e1->d.addend == e2->d.addend
1996179404Sobrien	: e1->d.h == e2->d.h);
1997179404Sobrien}
1998179404Sobrien
1999179404Sobrien/* multi_got_entries are still a match in the case of global objects,
2000179404Sobrien   even if the input bfd in which they're referenced differs, so the
2001179404Sobrien   hash computation and compare functions are adjusted
2002179404Sobrien   accordingly.  */
2003179404Sobrien
2004179404Sobrienstatic hashval_t
2005179404Sobrienmips_elf_multi_got_entry_hash (const void *entry_)
2006179404Sobrien{
2007179404Sobrien  const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
2008179404Sobrien
2009179404Sobrien  return entry->symndx
2010179404Sobrien    + (! entry->abfd
2011179404Sobrien       ? mips_elf_hash_bfd_vma (entry->d.address)
2012179404Sobrien       : entry->symndx >= 0
2013218822Sdim       ? ((entry->tls_type & GOT_TLS_LDM)
2014218822Sdim	  ? (GOT_TLS_LDM << 17)
2015218822Sdim	  : (entry->abfd->id
2016218822Sdim	     + mips_elf_hash_bfd_vma (entry->d.addend)))
2017179404Sobrien       : entry->d.h->root.root.root.hash);
2018179404Sobrien}
2019179404Sobrien
2020179404Sobrienstatic int
2021179404Sobrienmips_elf_multi_got_entry_eq (const void *entry1, const void *entry2)
2022179404Sobrien{
2023179404Sobrien  const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
2024179404Sobrien  const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
2025179404Sobrien
2026218822Sdim  /* Any two LDM entries match.  */
2027218822Sdim  if (e1->tls_type & e2->tls_type & GOT_TLS_LDM)
2028218822Sdim    return 1;
2029218822Sdim
2030218822Sdim  /* Nothing else matches an LDM entry.  */
2031218822Sdim  if ((e1->tls_type ^ e2->tls_type) & GOT_TLS_LDM)
2032218822Sdim    return 0;
2033218822Sdim
2034179404Sobrien  return e1->symndx == e2->symndx
2035179404Sobrien    && (e1->symndx >= 0 ? e1->abfd == e2->abfd && e1->d.addend == e2->d.addend
2036179404Sobrien	: e1->abfd == NULL || e2->abfd == NULL
2037179404Sobrien	? e1->abfd == e2->abfd && e1->d.address == e2->d.address
2038179404Sobrien	: e1->d.h == e2->d.h);
2039179404Sobrien}
2040179404Sobrien
2041218822Sdim/* Return the dynamic relocation section.  If it doesn't exist, try to
2042218822Sdim   create a new it if CREATE_P, otherwise return NULL.  Also return NULL
2043218822Sdim   if creation fails.  */
2044179404Sobrien
2045179404Sobrienstatic asection *
2046218822Sdimmips_elf_rel_dyn_section (struct bfd_link_info *info, bfd_boolean create_p)
2047179404Sobrien{
2048218822Sdim  const char *dname;
2049179404Sobrien  asection *sreloc;
2050218822Sdim  bfd *dynobj;
2051179404Sobrien
2052218822Sdim  dname = MIPS_ELF_REL_DYN_NAME (info);
2053218822Sdim  dynobj = elf_hash_table (info)->dynobj;
2054179404Sobrien  sreloc = bfd_get_section_by_name (dynobj, dname);
2055179404Sobrien  if (sreloc == NULL && create_p)
2056179404Sobrien    {
2057218822Sdim      sreloc = bfd_make_section_with_flags (dynobj, dname,
2058218822Sdim					    (SEC_ALLOC
2059218822Sdim					     | SEC_LOAD
2060218822Sdim					     | SEC_HAS_CONTENTS
2061218822Sdim					     | SEC_IN_MEMORY
2062218822Sdim					     | SEC_LINKER_CREATED
2063218822Sdim					     | SEC_READONLY));
2064179404Sobrien      if (sreloc == NULL
2065179404Sobrien	  || ! bfd_set_section_alignment (dynobj, sreloc,
2066179404Sobrien					  MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
2067179404Sobrien	return NULL;
2068179404Sobrien    }
2069179404Sobrien  return sreloc;
2070179404Sobrien}
2071179404Sobrien
2072179404Sobrien/* Returns the GOT section for ABFD.  */
2073179404Sobrien
2074179404Sobrienstatic asection *
2075179404Sobrienmips_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded)
2076179404Sobrien{
2077179404Sobrien  asection *sgot = bfd_get_section_by_name (abfd, ".got");
2078179404Sobrien  if (sgot == NULL
2079179404Sobrien      || (! maybe_excluded && (sgot->flags & SEC_EXCLUDE) != 0))
2080179404Sobrien    return NULL;
2081179404Sobrien  return sgot;
2082179404Sobrien}
2083179404Sobrien
2084179404Sobrien/* Returns the GOT information associated with the link indicated by
2085179404Sobrien   INFO.  If SGOTP is non-NULL, it is filled in with the GOT
2086179404Sobrien   section.  */
2087179404Sobrien
2088179404Sobrienstatic struct mips_got_info *
2089179404Sobrienmips_elf_got_info (bfd *abfd, asection **sgotp)
2090179404Sobrien{
2091179404Sobrien  asection *sgot;
2092179404Sobrien  struct mips_got_info *g;
2093179404Sobrien
2094179404Sobrien  sgot = mips_elf_got_section (abfd, TRUE);
2095179404Sobrien  BFD_ASSERT (sgot != NULL);
2096179404Sobrien  BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
2097179404Sobrien  g = mips_elf_section_data (sgot)->u.got_info;
2098179404Sobrien  BFD_ASSERT (g != NULL);
2099179404Sobrien
2100179404Sobrien  if (sgotp)
2101179404Sobrien    *sgotp = (sgot->flags & SEC_EXCLUDE) == 0 ? sgot : NULL;
2102179404Sobrien
2103179404Sobrien  return g;
2104179404Sobrien}
2105179404Sobrien
2106218822Sdim/* Count the number of relocations needed for a TLS GOT entry, with
2107218822Sdim   access types from TLS_TYPE, and symbol H (or a local symbol if H
2108218822Sdim   is NULL).  */
2109218822Sdim
2110218822Sdimstatic int
2111218822Sdimmips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type,
2112218822Sdim		     struct elf_link_hash_entry *h)
2113179404Sobrien{
2114218822Sdim  int indx = 0;
2115218822Sdim  int ret = 0;
2116218822Sdim  bfd_boolean need_relocs = FALSE;
2117218822Sdim  bfd_boolean dyn = elf_hash_table (info)->dynamic_sections_created;
2118179404Sobrien
2119218822Sdim  if (h && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
2120218822Sdim      && (!info->shared || !SYMBOL_REFERENCES_LOCAL (info, h)))
2121218822Sdim    indx = h->dynindx;
2122179404Sobrien
2123218822Sdim  if ((info->shared || indx != 0)
2124218822Sdim      && (h == NULL
2125218822Sdim	  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
2126218822Sdim	  || h->root.type != bfd_link_hash_undefweak))
2127218822Sdim    need_relocs = TRUE;
2128179404Sobrien
2129218822Sdim  if (!need_relocs)
2130218822Sdim    return FALSE;
2131179404Sobrien
2132218822Sdim  if (tls_type & GOT_TLS_GD)
2133218822Sdim    {
2134218822Sdim      ret++;
2135218822Sdim      if (indx != 0)
2136218822Sdim	ret++;
2137218822Sdim    }
2138218822Sdim
2139218822Sdim  if (tls_type & GOT_TLS_IE)
2140218822Sdim    ret++;
2141218822Sdim
2142218822Sdim  if ((tls_type & GOT_TLS_LDM) && info->shared)
2143218822Sdim    ret++;
2144218822Sdim
2145218822Sdim  return ret;
2146179404Sobrien}
2147179404Sobrien
2148218822Sdim/* Count the number of TLS relocations required for the GOT entry in
2149218822Sdim   ARG1, if it describes a local symbol.  */
2150179404Sobrien
2151218822Sdimstatic int
2152218822Sdimmips_elf_count_local_tls_relocs (void **arg1, void *arg2)
2153218822Sdim{
2154218822Sdim  struct mips_got_entry *entry = * (struct mips_got_entry **) arg1;
2155218822Sdim  struct mips_elf_count_tls_arg *arg = arg2;
2156218822Sdim
2157218822Sdim  if (entry->abfd != NULL && entry->symndx != -1)
2158218822Sdim    arg->needed += mips_tls_got_relocs (arg->info, entry->tls_type, NULL);
2159218822Sdim
2160218822Sdim  return 1;
2161218822Sdim}
2162218822Sdim
2163218822Sdim/* Count the number of TLS GOT entries required for the global (or
2164218822Sdim   forced-local) symbol in ARG1.  */
2165218822Sdim
2166218822Sdimstatic int
2167218822Sdimmips_elf_count_global_tls_entries (void *arg1, void *arg2)
2168218822Sdim{
2169218822Sdim  struct mips_elf_link_hash_entry *hm
2170218822Sdim    = (struct mips_elf_link_hash_entry *) arg1;
2171218822Sdim  struct mips_elf_count_tls_arg *arg = arg2;
2172218822Sdim
2173218822Sdim  if (hm->tls_type & GOT_TLS_GD)
2174218822Sdim    arg->needed += 2;
2175218822Sdim  if (hm->tls_type & GOT_TLS_IE)
2176218822Sdim    arg->needed += 1;
2177218822Sdim
2178218822Sdim  return 1;
2179218822Sdim}
2180218822Sdim
2181218822Sdim/* Count the number of TLS relocations required for the global (or
2182218822Sdim   forced-local) symbol in ARG1.  */
2183218822Sdim
2184218822Sdimstatic int
2185218822Sdimmips_elf_count_global_tls_relocs (void *arg1, void *arg2)
2186218822Sdim{
2187218822Sdim  struct mips_elf_link_hash_entry *hm
2188218822Sdim    = (struct mips_elf_link_hash_entry *) arg1;
2189218822Sdim  struct mips_elf_count_tls_arg *arg = arg2;
2190218822Sdim
2191218822Sdim  arg->needed += mips_tls_got_relocs (arg->info, hm->tls_type, &hm->root);
2192218822Sdim
2193218822Sdim  return 1;
2194218822Sdim}
2195218822Sdim
2196218822Sdim/* Output a simple dynamic relocation into SRELOC.  */
2197218822Sdim
2198218822Sdimstatic void
2199218822Sdimmips_elf_output_dynamic_relocation (bfd *output_bfd,
2200218822Sdim				    asection *sreloc,
2201218822Sdim				    unsigned long indx,
2202218822Sdim				    int r_type,
2203218822Sdim				    bfd_vma offset)
2204218822Sdim{
2205218822Sdim  Elf_Internal_Rela rel[3];
2206218822Sdim
2207218822Sdim  memset (rel, 0, sizeof (rel));
2208218822Sdim
2209218822Sdim  rel[0].r_info = ELF_R_INFO (output_bfd, indx, r_type);
2210218822Sdim  rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
2211218822Sdim
2212218822Sdim  if (ABI_64_P (output_bfd))
2213218822Sdim    {
2214218822Sdim      (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
2215218822Sdim	(output_bfd, &rel[0],
2216218822Sdim	 (sreloc->contents
2217218822Sdim	  + sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
2218218822Sdim    }
2219218822Sdim  else
2220218822Sdim    bfd_elf32_swap_reloc_out
2221218822Sdim      (output_bfd, &rel[0],
2222218822Sdim       (sreloc->contents
2223218822Sdim	+ sreloc->reloc_count * sizeof (Elf32_External_Rel)));
2224218822Sdim  ++sreloc->reloc_count;
2225218822Sdim}
2226218822Sdim
2227218822Sdim/* Initialize a set of TLS GOT entries for one symbol.  */
2228218822Sdim
2229218822Sdimstatic void
2230218822Sdimmips_elf_initialize_tls_slots (bfd *abfd, bfd_vma got_offset,
2231218822Sdim			       unsigned char *tls_type_p,
2232218822Sdim			       struct bfd_link_info *info,
2233218822Sdim			       struct mips_elf_link_hash_entry *h,
2234218822Sdim			       bfd_vma value)
2235218822Sdim{
2236218822Sdim  int indx;
2237218822Sdim  asection *sreloc, *sgot;
2238218822Sdim  bfd_vma offset, offset2;
2239218822Sdim  bfd *dynobj;
2240218822Sdim  bfd_boolean need_relocs = FALSE;
2241218822Sdim
2242218822Sdim  dynobj = elf_hash_table (info)->dynobj;
2243218822Sdim  sgot = mips_elf_got_section (dynobj, FALSE);
2244218822Sdim
2245218822Sdim  indx = 0;
2246218822Sdim  if (h != NULL)
2247218822Sdim    {
2248218822Sdim      bfd_boolean dyn = elf_hash_table (info)->dynamic_sections_created;
2249218822Sdim
2250218822Sdim      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, &h->root)
2251218822Sdim	  && (!info->shared || !SYMBOL_REFERENCES_LOCAL (info, &h->root)))
2252218822Sdim	indx = h->root.dynindx;
2253218822Sdim    }
2254218822Sdim
2255218822Sdim  if (*tls_type_p & GOT_TLS_DONE)
2256218822Sdim    return;
2257218822Sdim
2258218822Sdim  if ((info->shared || indx != 0)
2259218822Sdim      && (h == NULL
2260218822Sdim	  || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT
2261218822Sdim	  || h->root.type != bfd_link_hash_undefweak))
2262218822Sdim    need_relocs = TRUE;
2263218822Sdim
2264218822Sdim  /* MINUS_ONE means the symbol is not defined in this object.  It may not
2265218822Sdim     be defined at all; assume that the value doesn't matter in that
2266218822Sdim     case.  Otherwise complain if we would use the value.  */
2267218822Sdim  BFD_ASSERT (value != MINUS_ONE || (indx != 0 && need_relocs)
2268218822Sdim	      || h->root.root.type == bfd_link_hash_undefweak);
2269218822Sdim
2270218822Sdim  /* Emit necessary relocations.  */
2271218822Sdim  sreloc = mips_elf_rel_dyn_section (info, FALSE);
2272218822Sdim
2273218822Sdim  /* General Dynamic.  */
2274218822Sdim  if (*tls_type_p & GOT_TLS_GD)
2275218822Sdim    {
2276218822Sdim      offset = got_offset;
2277218822Sdim      offset2 = offset + MIPS_ELF_GOT_SIZE (abfd);
2278218822Sdim
2279218822Sdim      if (need_relocs)
2280218822Sdim	{
2281218822Sdim	  mips_elf_output_dynamic_relocation
2282218822Sdim	    (abfd, sreloc, indx,
2283218822Sdim	     ABI_64_P (abfd) ? R_MIPS_TLS_DTPMOD64 : R_MIPS_TLS_DTPMOD32,
2284218822Sdim	     sgot->output_offset + sgot->output_section->vma + offset);
2285218822Sdim
2286218822Sdim	  if (indx)
2287218822Sdim	    mips_elf_output_dynamic_relocation
2288218822Sdim	      (abfd, sreloc, indx,
2289218822Sdim	       ABI_64_P (abfd) ? R_MIPS_TLS_DTPREL64 : R_MIPS_TLS_DTPREL32,
2290218822Sdim	       sgot->output_offset + sgot->output_section->vma + offset2);
2291218822Sdim	  else
2292218822Sdim	    MIPS_ELF_PUT_WORD (abfd, value - dtprel_base (info),
2293218822Sdim			       sgot->contents + offset2);
2294218822Sdim	}
2295218822Sdim      else
2296218822Sdim	{
2297218822Sdim	  MIPS_ELF_PUT_WORD (abfd, 1,
2298218822Sdim			     sgot->contents + offset);
2299218822Sdim	  MIPS_ELF_PUT_WORD (abfd, value - dtprel_base (info),
2300218822Sdim			     sgot->contents + offset2);
2301218822Sdim	}
2302218822Sdim
2303218822Sdim      got_offset += 2 * MIPS_ELF_GOT_SIZE (abfd);
2304218822Sdim    }
2305218822Sdim
2306218822Sdim  /* Initial Exec model.  */
2307218822Sdim  if (*tls_type_p & GOT_TLS_IE)
2308218822Sdim    {
2309218822Sdim      offset = got_offset;
2310218822Sdim
2311218822Sdim      if (need_relocs)
2312218822Sdim	{
2313218822Sdim	  if (indx == 0)
2314218822Sdim	    MIPS_ELF_PUT_WORD (abfd, value - elf_hash_table (info)->tls_sec->vma,
2315218822Sdim			       sgot->contents + offset);
2316218822Sdim	  else
2317218822Sdim	    MIPS_ELF_PUT_WORD (abfd, 0,
2318218822Sdim			       sgot->contents + offset);
2319218822Sdim
2320218822Sdim	  mips_elf_output_dynamic_relocation
2321218822Sdim	    (abfd, sreloc, indx,
2322218822Sdim	     ABI_64_P (abfd) ? R_MIPS_TLS_TPREL64 : R_MIPS_TLS_TPREL32,
2323218822Sdim	     sgot->output_offset + sgot->output_section->vma + offset);
2324218822Sdim	}
2325218822Sdim      else
2326218822Sdim	MIPS_ELF_PUT_WORD (abfd, value - tprel_base (info),
2327218822Sdim			   sgot->contents + offset);
2328218822Sdim    }
2329218822Sdim
2330218822Sdim  if (*tls_type_p & GOT_TLS_LDM)
2331218822Sdim    {
2332218822Sdim      /* The initial offset is zero, and the LD offsets will include the
2333218822Sdim	 bias by DTP_OFFSET.  */
2334218822Sdim      MIPS_ELF_PUT_WORD (abfd, 0,
2335218822Sdim			 sgot->contents + got_offset
2336218822Sdim			 + MIPS_ELF_GOT_SIZE (abfd));
2337218822Sdim
2338218822Sdim      if (!info->shared)
2339218822Sdim	MIPS_ELF_PUT_WORD (abfd, 1,
2340218822Sdim			   sgot->contents + got_offset);
2341218822Sdim      else
2342218822Sdim	mips_elf_output_dynamic_relocation
2343218822Sdim	  (abfd, sreloc, indx,
2344218822Sdim	   ABI_64_P (abfd) ? R_MIPS_TLS_DTPMOD64 : R_MIPS_TLS_DTPMOD32,
2345218822Sdim	   sgot->output_offset + sgot->output_section->vma + got_offset);
2346218822Sdim    }
2347218822Sdim
2348218822Sdim  *tls_type_p |= GOT_TLS_DONE;
2349218822Sdim}
2350218822Sdim
2351218822Sdim/* Return the GOT index to use for a relocation of type R_TYPE against
2352218822Sdim   a symbol accessed using TLS_TYPE models.  The GOT entries for this
2353218822Sdim   symbol in this GOT start at GOT_INDEX.  This function initializes the
2354218822Sdim   GOT entries and corresponding relocations.  */
2355218822Sdim
2356179404Sobrienstatic bfd_vma
2357218822Sdimmips_tls_got_index (bfd *abfd, bfd_vma got_index, unsigned char *tls_type,
2358218822Sdim		    int r_type, struct bfd_link_info *info,
2359218822Sdim		    struct mips_elf_link_hash_entry *h, bfd_vma symbol)
2360218822Sdim{
2361218822Sdim  BFD_ASSERT (r_type == R_MIPS_TLS_GOTTPREL || r_type == R_MIPS_TLS_GD
2362218822Sdim	      || r_type == R_MIPS_TLS_LDM);
2363218822Sdim
2364218822Sdim  mips_elf_initialize_tls_slots (abfd, got_index, tls_type, info, h, symbol);
2365218822Sdim
2366218822Sdim  if (r_type == R_MIPS_TLS_GOTTPREL)
2367218822Sdim    {
2368218822Sdim      BFD_ASSERT (*tls_type & GOT_TLS_IE);
2369218822Sdim      if (*tls_type & GOT_TLS_GD)
2370218822Sdim	return got_index + 2 * MIPS_ELF_GOT_SIZE (abfd);
2371218822Sdim      else
2372218822Sdim	return got_index;
2373218822Sdim    }
2374218822Sdim
2375218822Sdim  if (r_type == R_MIPS_TLS_GD)
2376218822Sdim    {
2377218822Sdim      BFD_ASSERT (*tls_type & GOT_TLS_GD);
2378218822Sdim      return got_index;
2379218822Sdim    }
2380218822Sdim
2381218822Sdim  if (r_type == R_MIPS_TLS_LDM)
2382218822Sdim    {
2383218822Sdim      BFD_ASSERT (*tls_type & GOT_TLS_LDM);
2384218822Sdim      return got_index;
2385218822Sdim    }
2386218822Sdim
2387218822Sdim  return got_index;
2388218822Sdim}
2389218822Sdim
2390218822Sdim/* Return the offset from _GLOBAL_OFFSET_TABLE_ of the .got.plt entry
2391218822Sdim   for global symbol H.  .got.plt comes before the GOT, so the offset
2392218822Sdim   will be negative.  */
2393218822Sdim
2394218822Sdimstatic bfd_vma
2395218822Sdimmips_elf_gotplt_index (struct bfd_link_info *info,
2396218822Sdim		       struct elf_link_hash_entry *h)
2397218822Sdim{
2398218822Sdim  bfd_vma plt_index, got_address, got_value;
2399218822Sdim  struct mips_elf_link_hash_table *htab;
2400218822Sdim
2401218822Sdim  htab = mips_elf_hash_table (info);
2402218822Sdim  BFD_ASSERT (h->plt.offset != (bfd_vma) -1);
2403218822Sdim
2404218822Sdim  /* Calculate the index of the symbol's PLT entry.  */
2405218822Sdim  plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
2406218822Sdim
2407218822Sdim  /* Calculate the address of the associated .got.plt entry.  */
2408218822Sdim  got_address = (htab->sgotplt->output_section->vma
2409218822Sdim		 + htab->sgotplt->output_offset
2410218822Sdim		 + plt_index * 4);
2411218822Sdim
2412218822Sdim  /* Calculate the value of _GLOBAL_OFFSET_TABLE_.  */
2413218822Sdim  got_value = (htab->root.hgot->root.u.def.section->output_section->vma
2414218822Sdim	       + htab->root.hgot->root.u.def.section->output_offset
2415218822Sdim	       + htab->root.hgot->root.u.def.value);
2416218822Sdim
2417218822Sdim  return got_address - got_value;
2418218822Sdim}
2419218822Sdim
2420218822Sdim/* Return the GOT offset for address VALUE.   If there is not yet a GOT
2421218822Sdim   entry for this value, create one.  If R_SYMNDX refers to a TLS symbol,
2422218822Sdim   create a TLS GOT entry instead.  Return -1 if no satisfactory GOT
2423218822Sdim   offset can be found.  */
2424218822Sdim
2425218822Sdimstatic bfd_vma
2426179404Sobrienmips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
2427218822Sdim			  bfd_vma value, unsigned long r_symndx,
2428218822Sdim			  struct mips_elf_link_hash_entry *h, int r_type)
2429179404Sobrien{
2430179404Sobrien  asection *sgot;
2431179404Sobrien  struct mips_got_info *g;
2432179404Sobrien  struct mips_got_entry *entry;
2433179404Sobrien
2434179404Sobrien  g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
2435179404Sobrien
2436218822Sdim  entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
2437218822Sdim					   value, r_symndx, h, r_type);
2438218822Sdim  if (!entry)
2439218822Sdim    return MINUS_ONE;
2440218822Sdim
2441218822Sdim  if (TLS_RELOC_P (r_type))
2442218822Sdim    {
2443218822Sdim      if (entry->symndx == -1 && g->next == NULL)
2444218822Sdim	/* A type (3) entry in the single-GOT case.  We use the symbol's
2445218822Sdim	   hash table entry to track the index.  */
2446218822Sdim	return mips_tls_got_index (abfd, h->tls_got_offset, &h->tls_type,
2447218822Sdim				   r_type, info, h, value);
2448218822Sdim      else
2449218822Sdim	return mips_tls_got_index (abfd, entry->gotidx, &entry->tls_type,
2450218822Sdim				   r_type, info, h, value);
2451218822Sdim    }
2452218822Sdim  else
2453179404Sobrien    return entry->gotidx;
2454179404Sobrien}
2455179404Sobrien
2456179404Sobrien/* Returns the GOT index for the global symbol indicated by H.  */
2457179404Sobrien
2458179404Sobrienstatic bfd_vma
2459218822Sdimmips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
2460218822Sdim			   int r_type, struct bfd_link_info *info)
2461179404Sobrien{
2462179404Sobrien  bfd_vma index;
2463179404Sobrien  asection *sgot;
2464179404Sobrien  struct mips_got_info *g, *gg;
2465179404Sobrien  long global_got_dynindx = 0;
2466179404Sobrien
2467179404Sobrien  gg = g = mips_elf_got_info (abfd, &sgot);
2468179404Sobrien  if (g->bfd2got && ibfd)
2469179404Sobrien    {
2470179404Sobrien      struct mips_got_entry e, *p;
2471179404Sobrien
2472179404Sobrien      BFD_ASSERT (h->dynindx >= 0);
2473179404Sobrien
2474179404Sobrien      g = mips_elf_got_for_ibfd (g, ibfd);
2475218822Sdim      if (g->next != gg || TLS_RELOC_P (r_type))
2476179404Sobrien	{
2477179404Sobrien	  e.abfd = ibfd;
2478179404Sobrien	  e.symndx = -1;
2479179404Sobrien	  e.d.h = (struct mips_elf_link_hash_entry *)h;
2480218822Sdim	  e.tls_type = 0;
2481179404Sobrien
2482179404Sobrien	  p = htab_find (g->got_entries, &e);
2483179404Sobrien
2484179404Sobrien	  BFD_ASSERT (p->gotidx > 0);
2485218822Sdim
2486218822Sdim	  if (TLS_RELOC_P (r_type))
2487218822Sdim	    {
2488218822Sdim	      bfd_vma value = MINUS_ONE;
2489218822Sdim	      if ((h->root.type == bfd_link_hash_defined
2490218822Sdim		   || h->root.type == bfd_link_hash_defweak)
2491218822Sdim		  && h->root.u.def.section->output_section)
2492218822Sdim		value = (h->root.u.def.value
2493218822Sdim			 + h->root.u.def.section->output_offset
2494218822Sdim			 + h->root.u.def.section->output_section->vma);
2495218822Sdim
2496218822Sdim	      return mips_tls_got_index (abfd, p->gotidx, &p->tls_type, r_type,
2497218822Sdim					 info, e.d.h, value);
2498218822Sdim	    }
2499218822Sdim	  else
2500218822Sdim	    return p->gotidx;
2501179404Sobrien	}
2502179404Sobrien    }
2503179404Sobrien
2504179404Sobrien  if (gg->global_gotsym != NULL)
2505179404Sobrien    global_got_dynindx = gg->global_gotsym->dynindx;
2506179404Sobrien
2507218822Sdim  if (TLS_RELOC_P (r_type))
2508218822Sdim    {
2509218822Sdim      struct mips_elf_link_hash_entry *hm
2510218822Sdim	= (struct mips_elf_link_hash_entry *) h;
2511218822Sdim      bfd_vma value = MINUS_ONE;
2512179404Sobrien
2513218822Sdim      if ((h->root.type == bfd_link_hash_defined
2514218822Sdim	   || h->root.type == bfd_link_hash_defweak)
2515218822Sdim	  && h->root.u.def.section->output_section)
2516218822Sdim	value = (h->root.u.def.value
2517218822Sdim		 + h->root.u.def.section->output_offset
2518218822Sdim		 + h->root.u.def.section->output_section->vma);
2519218822Sdim
2520218822Sdim      index = mips_tls_got_index (abfd, hm->tls_got_offset, &hm->tls_type,
2521218822Sdim				  r_type, info, hm, value);
2522218822Sdim    }
2523218822Sdim  else
2524218822Sdim    {
2525218822Sdim      /* Once we determine the global GOT entry with the lowest dynamic
2526218822Sdim	 symbol table index, we must put all dynamic symbols with greater
2527218822Sdim	 indices into the GOT.  That makes it easy to calculate the GOT
2528218822Sdim	 offset.  */
2529218822Sdim      BFD_ASSERT (h->dynindx >= global_got_dynindx);
2530218822Sdim      index = ((h->dynindx - global_got_dynindx + g->local_gotno)
2531218822Sdim	       * MIPS_ELF_GOT_SIZE (abfd));
2532218822Sdim    }
2533218822Sdim  BFD_ASSERT (index < sgot->size);
2534218822Sdim
2535179404Sobrien  return index;
2536179404Sobrien}
2537179404Sobrien
2538218822Sdim/* Find a GOT page entry that points to within 32KB of VALUE.  These
2539218822Sdim   entries are supposed to be placed at small offsets in the GOT, i.e.,
2540218822Sdim   within 32KB of GP.  Return the index of the GOT entry, or -1 if no
2541218822Sdim   entry could be created.  If OFFSETP is nonnull, use it to return the
2542218822Sdim   offset of the GOT entry from VALUE.  */
2543179404Sobrien
2544179404Sobrienstatic bfd_vma
2545179404Sobrienmips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
2546179404Sobrien		   bfd_vma value, bfd_vma *offsetp)
2547179404Sobrien{
2548179404Sobrien  asection *sgot;
2549179404Sobrien  struct mips_got_info *g;
2550218822Sdim  bfd_vma page, index;
2551179404Sobrien  struct mips_got_entry *entry;
2552179404Sobrien
2553179404Sobrien  g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
2554179404Sobrien
2555218822Sdim  page = (value + 0x8000) & ~(bfd_vma) 0xffff;
2556218822Sdim  entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
2557218822Sdim					   page, 0, NULL, R_MIPS_GOT_PAGE);
2558179404Sobrien
2559179404Sobrien  if (!entry)
2560179404Sobrien    return MINUS_ONE;
2561179404Sobrien
2562179404Sobrien  index = entry->gotidx;
2563179404Sobrien
2564179404Sobrien  if (offsetp)
2565179404Sobrien    *offsetp = value - entry->d.address;
2566179404Sobrien
2567179404Sobrien  return index;
2568179404Sobrien}
2569179404Sobrien
2570218822Sdim/* Find a local GOT entry for an R_MIPS_GOT16 relocation against VALUE.
2571218822Sdim   EXTERNAL is true if the relocation was against a global symbol
2572218822Sdim   that has been forced local.  */
2573179404Sobrien
2574179404Sobrienstatic bfd_vma
2575179404Sobrienmips_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
2576179404Sobrien		      bfd_vma value, bfd_boolean external)
2577179404Sobrien{
2578179404Sobrien  asection *sgot;
2579179404Sobrien  struct mips_got_info *g;
2580179404Sobrien  struct mips_got_entry *entry;
2581179404Sobrien
2582218822Sdim  /* GOT16 relocations against local symbols are followed by a LO16
2583218822Sdim     relocation; those against global symbols are not.  Thus if the
2584218822Sdim     symbol was originally local, the GOT16 relocation should load the
2585218822Sdim     equivalent of %hi(VALUE), otherwise it should load VALUE itself.  */
2586179404Sobrien  if (! external)
2587218822Sdim    value = mips_elf_high (value) << 16;
2588179404Sobrien
2589179404Sobrien  g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
2590179404Sobrien
2591218822Sdim  entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
2592218822Sdim					   value, 0, NULL, R_MIPS_GOT16);
2593179404Sobrien  if (entry)
2594179404Sobrien    return entry->gotidx;
2595179404Sobrien  else
2596179404Sobrien    return MINUS_ONE;
2597179404Sobrien}
2598179404Sobrien
2599179404Sobrien/* Returns the offset for the entry at the INDEXth position
2600179404Sobrien   in the GOT.  */
2601179404Sobrien
2602179404Sobrienstatic bfd_vma
2603179404Sobrienmips_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
2604179404Sobrien				bfd *input_bfd, bfd_vma index)
2605179404Sobrien{
2606179404Sobrien  asection *sgot;
2607179404Sobrien  bfd_vma gp;
2608179404Sobrien  struct mips_got_info *g;
2609179404Sobrien
2610179404Sobrien  g = mips_elf_got_info (dynobj, &sgot);
2611179404Sobrien  gp = _bfd_get_gp_value (output_bfd)
2612179404Sobrien    + mips_elf_adjust_gp (output_bfd, g, input_bfd);
2613179404Sobrien
2614179404Sobrien  return sgot->output_section->vma + sgot->output_offset + index - gp;
2615179404Sobrien}
2616179404Sobrien
2617218822Sdim/* Create and return a local GOT entry for VALUE, which was calculated
2618218822Sdim   from a symbol belonging to INPUT_SECTON.  Return NULL if it could not
2619218822Sdim   be created.  If R_SYMNDX refers to a TLS symbol, create a TLS entry
2620218822Sdim   instead.  */
2621179404Sobrien
2622179404Sobrienstatic struct mips_got_entry *
2623218822Sdimmips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
2624218822Sdim				 bfd *ibfd, struct mips_got_info *gg,
2625218822Sdim				 asection *sgot, bfd_vma value,
2626218822Sdim				 unsigned long r_symndx,
2627218822Sdim				 struct mips_elf_link_hash_entry *h,
2628218822Sdim				 int r_type)
2629179404Sobrien{
2630179404Sobrien  struct mips_got_entry entry, **loc;
2631179404Sobrien  struct mips_got_info *g;
2632218822Sdim  struct mips_elf_link_hash_table *htab;
2633179404Sobrien
2634218822Sdim  htab = mips_elf_hash_table (info);
2635218822Sdim
2636179404Sobrien  entry.abfd = NULL;
2637179404Sobrien  entry.symndx = -1;
2638179404Sobrien  entry.d.address = value;
2639218822Sdim  entry.tls_type = 0;
2640179404Sobrien
2641179404Sobrien  g = mips_elf_got_for_ibfd (gg, ibfd);
2642179404Sobrien  if (g == NULL)
2643179404Sobrien    {
2644179404Sobrien      g = mips_elf_got_for_ibfd (gg, abfd);
2645179404Sobrien      BFD_ASSERT (g != NULL);
2646179404Sobrien    }
2647179404Sobrien
2648218822Sdim  /* We might have a symbol, H, if it has been forced local.  Use the
2649218822Sdim     global entry then.  It doesn't matter whether an entry is local
2650218822Sdim     or global for TLS, since the dynamic linker does not
2651218822Sdim     automatically relocate TLS GOT entries.  */
2652218822Sdim  BFD_ASSERT (h == NULL || h->root.forced_local);
2653218822Sdim  if (TLS_RELOC_P (r_type))
2654218822Sdim    {
2655218822Sdim      struct mips_got_entry *p;
2656218822Sdim
2657218822Sdim      entry.abfd = ibfd;
2658218822Sdim      if (r_type == R_MIPS_TLS_LDM)
2659218822Sdim	{
2660218822Sdim	  entry.tls_type = GOT_TLS_LDM;
2661218822Sdim	  entry.symndx = 0;
2662218822Sdim	  entry.d.addend = 0;
2663218822Sdim	}
2664218822Sdim      else if (h == NULL)
2665218822Sdim	{
2666218822Sdim	  entry.symndx = r_symndx;
2667218822Sdim	  entry.d.addend = 0;
2668218822Sdim	}
2669218822Sdim      else
2670218822Sdim	entry.d.h = h;
2671218822Sdim
2672218822Sdim      p = (struct mips_got_entry *)
2673218822Sdim	htab_find (g->got_entries, &entry);
2674218822Sdim
2675218822Sdim      BFD_ASSERT (p);
2676218822Sdim      return p;
2677218822Sdim    }
2678218822Sdim
2679179404Sobrien  loc = (struct mips_got_entry **) htab_find_slot (g->got_entries, &entry,
2680179404Sobrien						   INSERT);
2681179404Sobrien  if (*loc)
2682179404Sobrien    return *loc;
2683179404Sobrien
2684179404Sobrien  entry.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
2685218822Sdim  entry.tls_type = 0;
2686179404Sobrien
2687179404Sobrien  *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
2688179404Sobrien
2689179404Sobrien  if (! *loc)
2690179404Sobrien    return NULL;
2691179404Sobrien
2692179404Sobrien  memcpy (*loc, &entry, sizeof entry);
2693179404Sobrien
2694179404Sobrien  if (g->assigned_gotno >= g->local_gotno)
2695179404Sobrien    {
2696179404Sobrien      (*loc)->gotidx = -1;
2697179404Sobrien      /* We didn't allocate enough space in the GOT.  */
2698179404Sobrien      (*_bfd_error_handler)
2699179404Sobrien	(_("not enough GOT space for local GOT entries"));
2700179404Sobrien      bfd_set_error (bfd_error_bad_value);
2701179404Sobrien      return NULL;
2702179404Sobrien    }
2703179404Sobrien
2704179404Sobrien  MIPS_ELF_PUT_WORD (abfd, value,
2705179404Sobrien		     (sgot->contents + entry.gotidx));
2706179404Sobrien
2707218822Sdim  /* These GOT entries need a dynamic relocation on VxWorks.  */
2708218822Sdim  if (htab->is_vxworks)
2709218822Sdim    {
2710218822Sdim      Elf_Internal_Rela outrel;
2711218822Sdim      asection *s;
2712218822Sdim      bfd_byte *loc;
2713218822Sdim      bfd_vma got_address;
2714218822Sdim
2715218822Sdim      s = mips_elf_rel_dyn_section (info, FALSE);
2716218822Sdim      got_address = (sgot->output_section->vma
2717218822Sdim		     + sgot->output_offset
2718218822Sdim		     + entry.gotidx);
2719218822Sdim
2720218822Sdim      loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
2721218822Sdim      outrel.r_offset = got_address;
2722218822Sdim      outrel.r_info = ELF32_R_INFO (STN_UNDEF, R_MIPS_32);
2723218822Sdim      outrel.r_addend = value;
2724218822Sdim      bfd_elf32_swap_reloca_out (abfd, &outrel, loc);
2725218822Sdim    }
2726218822Sdim
2727179404Sobrien  return *loc;
2728179404Sobrien}
2729179404Sobrien
2730179404Sobrien/* Sort the dynamic symbol table so that symbols that need GOT entries
2731179404Sobrien   appear towards the end.  This reduces the amount of GOT space
2732179404Sobrien   required.  MAX_LOCAL is used to set the number of local symbols
2733179404Sobrien   known to be in the dynamic symbol table.  During
2734179404Sobrien   _bfd_mips_elf_size_dynamic_sections, this value is 1.  Afterward, the
2735179404Sobrien   section symbols are added and the count is higher.  */
2736179404Sobrien
2737179404Sobrienstatic bfd_boolean
2738179404Sobrienmips_elf_sort_hash_table (struct bfd_link_info *info, unsigned long max_local)
2739179404Sobrien{
2740179404Sobrien  struct mips_elf_hash_sort_data hsd;
2741179404Sobrien  struct mips_got_info *g;
2742179404Sobrien  bfd *dynobj;
2743179404Sobrien
2744179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
2745179404Sobrien
2746179404Sobrien  g = mips_elf_got_info (dynobj, NULL);
2747179404Sobrien
2748179404Sobrien  hsd.low = NULL;
2749179404Sobrien  hsd.max_unref_got_dynindx =
2750179404Sobrien  hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
2751179404Sobrien    /* In the multi-got case, assigned_gotno of the master got_info
2752179404Sobrien       indicate the number of entries that aren't referenced in the
2753179404Sobrien       primary GOT, but that must have entries because there are
2754179404Sobrien       dynamic relocations that reference it.  Since they aren't
2755179404Sobrien       referenced, we move them to the end of the GOT, so that they
2756179404Sobrien       don't prevent other entries that are referenced from getting
2757179404Sobrien       too large offsets.  */
2758179404Sobrien    - (g->next ? g->assigned_gotno : 0);
2759179404Sobrien  hsd.max_non_got_dynindx = max_local;
2760179404Sobrien  mips_elf_link_hash_traverse (((struct mips_elf_link_hash_table *)
2761179404Sobrien				elf_hash_table (info)),
2762179404Sobrien			       mips_elf_sort_hash_table_f,
2763179404Sobrien			       &hsd);
2764179404Sobrien
2765179404Sobrien  /* There should have been enough room in the symbol table to
2766179404Sobrien     accommodate both the GOT and non-GOT symbols.  */
2767179404Sobrien  BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
2768179404Sobrien  BFD_ASSERT ((unsigned long)hsd.max_unref_got_dynindx
2769179404Sobrien	      <= elf_hash_table (info)->dynsymcount);
2770179404Sobrien
2771179404Sobrien  /* Now we know which dynamic symbol has the lowest dynamic symbol
2772179404Sobrien     table index in the GOT.  */
2773179404Sobrien  g->global_gotsym = hsd.low;
2774179404Sobrien
2775179404Sobrien  return TRUE;
2776179404Sobrien}
2777179404Sobrien
2778179404Sobrien/* If H needs a GOT entry, assign it the highest available dynamic
2779179404Sobrien   index.  Otherwise, assign it the lowest available dynamic
2780179404Sobrien   index.  */
2781179404Sobrien
2782179404Sobrienstatic bfd_boolean
2783179404Sobrienmips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
2784179404Sobrien{
2785179404Sobrien  struct mips_elf_hash_sort_data *hsd = data;
2786179404Sobrien
2787179404Sobrien  if (h->root.root.type == bfd_link_hash_warning)
2788179404Sobrien    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
2789179404Sobrien
2790179404Sobrien  /* Symbols without dynamic symbol table entries aren't interesting
2791179404Sobrien     at all.  */
2792179404Sobrien  if (h->root.dynindx == -1)
2793179404Sobrien    return TRUE;
2794179404Sobrien
2795179404Sobrien  /* Global symbols that need GOT entries that are not explicitly
2796179404Sobrien     referenced are marked with got offset 2.  Those that are
2797179404Sobrien     referenced get a 1, and those that don't need GOT entries get
2798179404Sobrien     -1.  */
2799179404Sobrien  if (h->root.got.offset == 2)
2800179404Sobrien    {
2801218822Sdim      BFD_ASSERT (h->tls_type == GOT_NORMAL);
2802218822Sdim
2803179404Sobrien      if (hsd->max_unref_got_dynindx == hsd->min_got_dynindx)
2804179404Sobrien	hsd->low = (struct elf_link_hash_entry *) h;
2805179404Sobrien      h->root.dynindx = hsd->max_unref_got_dynindx++;
2806179404Sobrien    }
2807179404Sobrien  else if (h->root.got.offset != 1)
2808179404Sobrien    h->root.dynindx = hsd->max_non_got_dynindx++;
2809179404Sobrien  else
2810179404Sobrien    {
2811218822Sdim      BFD_ASSERT (h->tls_type == GOT_NORMAL);
2812218822Sdim
2813179404Sobrien      h->root.dynindx = --hsd->min_got_dynindx;
2814179404Sobrien      hsd->low = (struct elf_link_hash_entry *) h;
2815179404Sobrien    }
2816179404Sobrien
2817179404Sobrien  return TRUE;
2818179404Sobrien}
2819179404Sobrien
2820179404Sobrien/* If H is a symbol that needs a global GOT entry, but has a dynamic
2821179404Sobrien   symbol table index lower than any we've seen to date, record it for
2822179404Sobrien   posterity.  */
2823179404Sobrien
2824179404Sobrienstatic bfd_boolean
2825179404Sobrienmips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
2826179404Sobrien				   bfd *abfd, struct bfd_link_info *info,
2827218822Sdim				   struct mips_got_info *g,
2828218822Sdim				   unsigned char tls_flag)
2829179404Sobrien{
2830179404Sobrien  struct mips_got_entry entry, **loc;
2831179404Sobrien
2832179404Sobrien  /* A global symbol in the GOT must also be in the dynamic symbol
2833179404Sobrien     table.  */
2834179404Sobrien  if (h->dynindx == -1)
2835179404Sobrien    {
2836179404Sobrien      switch (ELF_ST_VISIBILITY (h->other))
2837179404Sobrien	{
2838179404Sobrien	case STV_INTERNAL:
2839179404Sobrien	case STV_HIDDEN:
2840179404Sobrien	  _bfd_mips_elf_hide_symbol (info, h, TRUE);
2841179404Sobrien	  break;
2842179404Sobrien	}
2843179404Sobrien      if (!bfd_elf_link_record_dynamic_symbol (info, h))
2844179404Sobrien	return FALSE;
2845179404Sobrien    }
2846179404Sobrien
2847218822Sdim  /* Make sure we have a GOT to put this entry into.  */
2848218822Sdim  BFD_ASSERT (g != NULL);
2849218822Sdim
2850179404Sobrien  entry.abfd = abfd;
2851179404Sobrien  entry.symndx = -1;
2852179404Sobrien  entry.d.h = (struct mips_elf_link_hash_entry *) h;
2853218822Sdim  entry.tls_type = 0;
2854179404Sobrien
2855179404Sobrien  loc = (struct mips_got_entry **) htab_find_slot (g->got_entries, &entry,
2856179404Sobrien						   INSERT);
2857179404Sobrien
2858179404Sobrien  /* If we've already marked this entry as needing GOT space, we don't
2859179404Sobrien     need to do it again.  */
2860179404Sobrien  if (*loc)
2861218822Sdim    {
2862218822Sdim      (*loc)->tls_type |= tls_flag;
2863218822Sdim      return TRUE;
2864218822Sdim    }
2865179404Sobrien
2866179404Sobrien  *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
2867179404Sobrien
2868179404Sobrien  if (! *loc)
2869179404Sobrien    return FALSE;
2870179404Sobrien
2871179404Sobrien  entry.gotidx = -1;
2872218822Sdim  entry.tls_type = tls_flag;
2873218822Sdim
2874179404Sobrien  memcpy (*loc, &entry, sizeof entry);
2875179404Sobrien
2876179404Sobrien  if (h->got.offset != MINUS_ONE)
2877179404Sobrien    return TRUE;
2878179404Sobrien
2879179404Sobrien  /* By setting this to a value other than -1, we are indicating that
2880179404Sobrien     there needs to be a GOT entry for H.  Avoid using zero, as the
2881179404Sobrien     generic ELF copy_indirect_symbol tests for <= 0.  */
2882218822Sdim  if (tls_flag == 0)
2883218822Sdim    h->got.offset = 1;
2884179404Sobrien
2885179404Sobrien  return TRUE;
2886179404Sobrien}
2887179404Sobrien
2888179404Sobrien/* Reserve space in G for a GOT entry containing the value of symbol
2889179404Sobrien   SYMNDX in input bfd ABDF, plus ADDEND.  */
2890179404Sobrien
2891179404Sobrienstatic bfd_boolean
2892179404Sobrienmips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
2893218822Sdim				  struct mips_got_info *g,
2894218822Sdim				  unsigned char tls_flag)
2895179404Sobrien{
2896179404Sobrien  struct mips_got_entry entry, **loc;
2897179404Sobrien
2898179404Sobrien  entry.abfd = abfd;
2899179404Sobrien  entry.symndx = symndx;
2900179404Sobrien  entry.d.addend = addend;
2901218822Sdim  entry.tls_type = tls_flag;
2902179404Sobrien  loc = (struct mips_got_entry **)
2903179404Sobrien    htab_find_slot (g->got_entries, &entry, INSERT);
2904179404Sobrien
2905179404Sobrien  if (*loc)
2906218822Sdim    {
2907218822Sdim      if (tls_flag == GOT_TLS_GD && !((*loc)->tls_type & GOT_TLS_GD))
2908218822Sdim	{
2909218822Sdim	  g->tls_gotno += 2;
2910218822Sdim	  (*loc)->tls_type |= tls_flag;
2911218822Sdim	}
2912218822Sdim      else if (tls_flag == GOT_TLS_IE && !((*loc)->tls_type & GOT_TLS_IE))
2913218822Sdim	{
2914218822Sdim	  g->tls_gotno += 1;
2915218822Sdim	  (*loc)->tls_type |= tls_flag;
2916218822Sdim	}
2917218822Sdim      return TRUE;
2918218822Sdim    }
2919179404Sobrien
2920218822Sdim  if (tls_flag != 0)
2921218822Sdim    {
2922218822Sdim      entry.gotidx = -1;
2923218822Sdim      entry.tls_type = tls_flag;
2924218822Sdim      if (tls_flag == GOT_TLS_IE)
2925218822Sdim	g->tls_gotno += 1;
2926218822Sdim      else if (tls_flag == GOT_TLS_GD)
2927218822Sdim	g->tls_gotno += 2;
2928218822Sdim      else if (g->tls_ldm_offset == MINUS_ONE)
2929218822Sdim	{
2930218822Sdim	  g->tls_ldm_offset = MINUS_TWO;
2931218822Sdim	  g->tls_gotno += 2;
2932218822Sdim	}
2933218822Sdim    }
2934218822Sdim  else
2935218822Sdim    {
2936218822Sdim      entry.gotidx = g->local_gotno++;
2937218822Sdim      entry.tls_type = 0;
2938218822Sdim    }
2939179404Sobrien
2940179404Sobrien  *loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
2941179404Sobrien
2942179404Sobrien  if (! *loc)
2943179404Sobrien    return FALSE;
2944179404Sobrien
2945179404Sobrien  memcpy (*loc, &entry, sizeof entry);
2946179404Sobrien
2947179404Sobrien  return TRUE;
2948179404Sobrien}
2949179404Sobrien
2950179404Sobrien/* Compute the hash value of the bfd in a bfd2got hash entry.  */
2951179404Sobrien
2952179404Sobrienstatic hashval_t
2953179404Sobrienmips_elf_bfd2got_entry_hash (const void *entry_)
2954179404Sobrien{
2955179404Sobrien  const struct mips_elf_bfd2got_hash *entry
2956179404Sobrien    = (struct mips_elf_bfd2got_hash *)entry_;
2957179404Sobrien
2958179404Sobrien  return entry->bfd->id;
2959179404Sobrien}
2960179404Sobrien
2961179404Sobrien/* Check whether two hash entries have the same bfd.  */
2962179404Sobrien
2963179404Sobrienstatic int
2964179404Sobrienmips_elf_bfd2got_entry_eq (const void *entry1, const void *entry2)
2965179404Sobrien{
2966179404Sobrien  const struct mips_elf_bfd2got_hash *e1
2967179404Sobrien    = (const struct mips_elf_bfd2got_hash *)entry1;
2968179404Sobrien  const struct mips_elf_bfd2got_hash *e2
2969179404Sobrien    = (const struct mips_elf_bfd2got_hash *)entry2;
2970179404Sobrien
2971179404Sobrien  return e1->bfd == e2->bfd;
2972179404Sobrien}
2973179404Sobrien
2974218822Sdim/* In a multi-got link, determine the GOT to be used for IBFD.  G must
2975179404Sobrien   be the master GOT data.  */
2976179404Sobrien
2977179404Sobrienstatic struct mips_got_info *
2978179404Sobrienmips_elf_got_for_ibfd (struct mips_got_info *g, bfd *ibfd)
2979179404Sobrien{
2980179404Sobrien  struct mips_elf_bfd2got_hash e, *p;
2981179404Sobrien
2982179404Sobrien  if (! g->bfd2got)
2983179404Sobrien    return g;
2984179404Sobrien
2985179404Sobrien  e.bfd = ibfd;
2986179404Sobrien  p = htab_find (g->bfd2got, &e);
2987179404Sobrien  return p ? p->g : NULL;
2988179404Sobrien}
2989179404Sobrien
2990179404Sobrien/* Create one separate got for each bfd that has entries in the global
2991179404Sobrien   got, such that we can tell how many local and global entries each
2992179404Sobrien   bfd requires.  */
2993179404Sobrien
2994179404Sobrienstatic int
2995179404Sobrienmips_elf_make_got_per_bfd (void **entryp, void *p)
2996179404Sobrien{
2997179404Sobrien  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
2998179404Sobrien  struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *)p;
2999179404Sobrien  htab_t bfd2got = arg->bfd2got;
3000179404Sobrien  struct mips_got_info *g;
3001179404Sobrien  struct mips_elf_bfd2got_hash bfdgot_entry, *bfdgot;
3002179404Sobrien  void **bfdgotp;
3003179404Sobrien
3004179404Sobrien  /* Find the got_info for this GOT entry's input bfd.  Create one if
3005179404Sobrien     none exists.  */
3006179404Sobrien  bfdgot_entry.bfd = entry->abfd;
3007179404Sobrien  bfdgotp = htab_find_slot (bfd2got, &bfdgot_entry, INSERT);
3008179404Sobrien  bfdgot = (struct mips_elf_bfd2got_hash *)*bfdgotp;
3009179404Sobrien
3010179404Sobrien  if (bfdgot != NULL)
3011179404Sobrien    g = bfdgot->g;
3012179404Sobrien  else
3013179404Sobrien    {
3014179404Sobrien      bfdgot = (struct mips_elf_bfd2got_hash *)bfd_alloc
3015179404Sobrien	(arg->obfd, sizeof (struct mips_elf_bfd2got_hash));
3016179404Sobrien
3017179404Sobrien      if (bfdgot == NULL)
3018179404Sobrien	{
3019179404Sobrien	  arg->obfd = 0;
3020179404Sobrien	  return 0;
3021179404Sobrien	}
3022179404Sobrien
3023179404Sobrien      *bfdgotp = bfdgot;
3024179404Sobrien
3025179404Sobrien      bfdgot->bfd = entry->abfd;
3026179404Sobrien      bfdgot->g = g = (struct mips_got_info *)
3027179404Sobrien	bfd_alloc (arg->obfd, sizeof (struct mips_got_info));
3028179404Sobrien      if (g == NULL)
3029179404Sobrien	{
3030179404Sobrien	  arg->obfd = 0;
3031179404Sobrien	  return 0;
3032179404Sobrien	}
3033179404Sobrien
3034179404Sobrien      g->global_gotsym = NULL;
3035179404Sobrien      g->global_gotno = 0;
3036179404Sobrien      g->local_gotno = 0;
3037179404Sobrien      g->assigned_gotno = -1;
3038218822Sdim      g->tls_gotno = 0;
3039218822Sdim      g->tls_assigned_gotno = 0;
3040218822Sdim      g->tls_ldm_offset = MINUS_ONE;
3041179404Sobrien      g->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
3042179404Sobrien					mips_elf_multi_got_entry_eq, NULL);
3043179404Sobrien      if (g->got_entries == NULL)
3044179404Sobrien	{
3045179404Sobrien	  arg->obfd = 0;
3046179404Sobrien	  return 0;
3047179404Sobrien	}
3048179404Sobrien
3049179404Sobrien      g->bfd2got = NULL;
3050179404Sobrien      g->next = NULL;
3051179404Sobrien    }
3052179404Sobrien
3053179404Sobrien  /* Insert the GOT entry in the bfd's got entry hash table.  */
3054179404Sobrien  entryp = htab_find_slot (g->got_entries, entry, INSERT);
3055179404Sobrien  if (*entryp != NULL)
3056179404Sobrien    return 1;
3057179404Sobrien
3058179404Sobrien  *entryp = entry;
3059179404Sobrien
3060218822Sdim  if (entry->tls_type)
3061218822Sdim    {
3062218822Sdim      if (entry->tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
3063218822Sdim	g->tls_gotno += 2;
3064218822Sdim      if (entry->tls_type & GOT_TLS_IE)
3065218822Sdim	g->tls_gotno += 1;
3066218822Sdim    }
3067218822Sdim  else if (entry->symndx >= 0 || entry->d.h->forced_local)
3068179404Sobrien    ++g->local_gotno;
3069179404Sobrien  else
3070179404Sobrien    ++g->global_gotno;
3071179404Sobrien
3072179404Sobrien  return 1;
3073179404Sobrien}
3074179404Sobrien
3075179404Sobrien/* Attempt to merge gots of different input bfds.  Try to use as much
3076179404Sobrien   as possible of the primary got, since it doesn't require explicit
3077179404Sobrien   dynamic relocations, but don't use bfds that would reference global
3078179404Sobrien   symbols out of the addressable range.  Failing the primary got,
3079179404Sobrien   attempt to merge with the current got, or finish the current got
3080179404Sobrien   and then make make the new got current.  */
3081179404Sobrien
3082179404Sobrienstatic int
3083179404Sobrienmips_elf_merge_gots (void **bfd2got_, void *p)
3084179404Sobrien{
3085179404Sobrien  struct mips_elf_bfd2got_hash *bfd2got
3086179404Sobrien    = (struct mips_elf_bfd2got_hash *)*bfd2got_;
3087179404Sobrien  struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *)p;
3088179404Sobrien  unsigned int lcount = bfd2got->g->local_gotno;
3089179404Sobrien  unsigned int gcount = bfd2got->g->global_gotno;
3090218822Sdim  unsigned int tcount = bfd2got->g->tls_gotno;
3091179404Sobrien  unsigned int maxcnt = arg->max_count;
3092218822Sdim  bfd_boolean too_many_for_tls = FALSE;
3093179404Sobrien
3094218822Sdim  /* We place TLS GOT entries after both locals and globals.  The globals
3095218822Sdim     for the primary GOT may overflow the normal GOT size limit, so be
3096218822Sdim     sure not to merge a GOT which requires TLS with the primary GOT in that
3097218822Sdim     case.  This doesn't affect non-primary GOTs.  */
3098218822Sdim  if (tcount > 0)
3099218822Sdim    {
3100218822Sdim      unsigned int primary_total = lcount + tcount + arg->global_count;
3101218822Sdim      if (primary_total > maxcnt)
3102218822Sdim	too_many_for_tls = TRUE;
3103218822Sdim    }
3104218822Sdim
3105179404Sobrien  /* If we don't have a primary GOT and this is not too big, use it as
3106179404Sobrien     a starting point for the primary GOT.  */
3107218822Sdim  if (! arg->primary && lcount + gcount + tcount <= maxcnt
3108218822Sdim      && ! too_many_for_tls)
3109179404Sobrien    {
3110179404Sobrien      arg->primary = bfd2got->g;
3111179404Sobrien      arg->primary_count = lcount + gcount;
3112179404Sobrien    }
3113179404Sobrien  /* If it looks like we can merge this bfd's entries with those of
3114179404Sobrien     the primary, merge them.  The heuristics is conservative, but we
3115179404Sobrien     don't have to squeeze it too hard.  */
3116218822Sdim  else if (arg->primary && ! too_many_for_tls
3117218822Sdim	   && (arg->primary_count + lcount + gcount + tcount) <= maxcnt)
3118179404Sobrien    {
3119179404Sobrien      struct mips_got_info *g = bfd2got->g;
3120179404Sobrien      int old_lcount = arg->primary->local_gotno;
3121179404Sobrien      int old_gcount = arg->primary->global_gotno;
3122218822Sdim      int old_tcount = arg->primary->tls_gotno;
3123179404Sobrien
3124179404Sobrien      bfd2got->g = arg->primary;
3125179404Sobrien
3126179404Sobrien      htab_traverse (g->got_entries,
3127179404Sobrien		     mips_elf_make_got_per_bfd,
3128179404Sobrien		     arg);
3129179404Sobrien      if (arg->obfd == NULL)
3130179404Sobrien	return 0;
3131179404Sobrien
3132179404Sobrien      htab_delete (g->got_entries);
3133179404Sobrien      /* We don't have to worry about releasing memory of the actual
3134179404Sobrien	 got entries, since they're all in the master got_entries hash
3135179404Sobrien	 table anyway.  */
3136179404Sobrien
3137179404Sobrien      BFD_ASSERT (old_lcount + lcount >= arg->primary->local_gotno);
3138179404Sobrien      BFD_ASSERT (old_gcount + gcount >= arg->primary->global_gotno);
3139218822Sdim      BFD_ASSERT (old_tcount + tcount >= arg->primary->tls_gotno);
3140179404Sobrien
3141179404Sobrien      arg->primary_count = arg->primary->local_gotno
3142218822Sdim	+ arg->primary->global_gotno + arg->primary->tls_gotno;
3143179404Sobrien    }
3144179404Sobrien  /* If we can merge with the last-created got, do it.  */
3145179404Sobrien  else if (arg->current
3146218822Sdim	   && arg->current_count + lcount + gcount + tcount <= maxcnt)
3147179404Sobrien    {
3148179404Sobrien      struct mips_got_info *g = bfd2got->g;
3149179404Sobrien      int old_lcount = arg->current->local_gotno;
3150179404Sobrien      int old_gcount = arg->current->global_gotno;
3151218822Sdim      int old_tcount = arg->current->tls_gotno;
3152179404Sobrien
3153179404Sobrien      bfd2got->g = arg->current;
3154179404Sobrien
3155179404Sobrien      htab_traverse (g->got_entries,
3156179404Sobrien		     mips_elf_make_got_per_bfd,
3157179404Sobrien		     arg);
3158179404Sobrien      if (arg->obfd == NULL)
3159179404Sobrien	return 0;
3160179404Sobrien
3161179404Sobrien      htab_delete (g->got_entries);
3162179404Sobrien
3163179404Sobrien      BFD_ASSERT (old_lcount + lcount >= arg->current->local_gotno);
3164179404Sobrien      BFD_ASSERT (old_gcount + gcount >= arg->current->global_gotno);
3165218822Sdim      BFD_ASSERT (old_tcount + tcount >= arg->current->tls_gotno);
3166179404Sobrien
3167179404Sobrien      arg->current_count = arg->current->local_gotno
3168218822Sdim	+ arg->current->global_gotno + arg->current->tls_gotno;
3169179404Sobrien    }
3170179404Sobrien  /* Well, we couldn't merge, so create a new GOT.  Don't check if it
3171179404Sobrien     fits; if it turns out that it doesn't, we'll get relocation
3172179404Sobrien     overflows anyway.  */
3173179404Sobrien  else
3174179404Sobrien    {
3175179404Sobrien      bfd2got->g->next = arg->current;
3176179404Sobrien      arg->current = bfd2got->g;
3177179404Sobrien
3178218822Sdim      arg->current_count = lcount + gcount + 2 * tcount;
3179179404Sobrien    }
3180179404Sobrien
3181179404Sobrien  return 1;
3182179404Sobrien}
3183179404Sobrien
3184218822Sdim/* Set the TLS GOT index for the GOT entry in ENTRYP.  ENTRYP's NEXT field
3185218822Sdim   is null iff there is just a single GOT.  */
3186218822Sdim
3187218822Sdimstatic int
3188218822Sdimmips_elf_initialize_tls_index (void **entryp, void *p)
3189218822Sdim{
3190218822Sdim  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
3191218822Sdim  struct mips_got_info *g = p;
3192218822Sdim  bfd_vma next_index;
3193218822Sdim  unsigned char tls_type;
3194218822Sdim
3195218822Sdim  /* We're only interested in TLS symbols.  */
3196218822Sdim  if (entry->tls_type == 0)
3197218822Sdim    return 1;
3198218822Sdim
3199218822Sdim  next_index = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
3200218822Sdim
3201218822Sdim  if (entry->symndx == -1 && g->next == NULL)
3202218822Sdim    {
3203218822Sdim      /* A type (3) got entry in the single-GOT case.  We use the symbol's
3204218822Sdim	 hash table entry to track its index.  */
3205218822Sdim      if (entry->d.h->tls_type & GOT_TLS_OFFSET_DONE)
3206218822Sdim	return 1;
3207218822Sdim      entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
3208218822Sdim      entry->d.h->tls_got_offset = next_index;
3209218822Sdim      tls_type = entry->d.h->tls_type;
3210218822Sdim    }
3211218822Sdim  else
3212218822Sdim    {
3213218822Sdim      if (entry->tls_type & GOT_TLS_LDM)
3214218822Sdim	{
3215218822Sdim	  /* There are separate mips_got_entry objects for each input bfd
3216218822Sdim	     that requires an LDM entry.  Make sure that all LDM entries in
3217218822Sdim	     a GOT resolve to the same index.  */
3218218822Sdim	  if (g->tls_ldm_offset != MINUS_TWO && g->tls_ldm_offset != MINUS_ONE)
3219218822Sdim	    {
3220218822Sdim	      entry->gotidx = g->tls_ldm_offset;
3221218822Sdim	      return 1;
3222218822Sdim	    }
3223218822Sdim	  g->tls_ldm_offset = next_index;
3224218822Sdim	}
3225218822Sdim      entry->gotidx = next_index;
3226218822Sdim      tls_type = entry->tls_type;
3227218822Sdim    }
3228218822Sdim
3229218822Sdim  /* Account for the entries we've just allocated.  */
3230218822Sdim  if (tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
3231218822Sdim    g->tls_assigned_gotno += 2;
3232218822Sdim  if (tls_type & GOT_TLS_IE)
3233218822Sdim    g->tls_assigned_gotno += 1;
3234218822Sdim
3235218822Sdim  return 1;
3236218822Sdim}
3237218822Sdim
3238179404Sobrien/* If passed a NULL mips_got_info in the argument, set the marker used
3239179404Sobrien   to tell whether a global symbol needs a got entry (in the primary
3240179404Sobrien   got) to the given VALUE.
3241179404Sobrien
3242179404Sobrien   If passed a pointer G to a mips_got_info in the argument (it must
3243179404Sobrien   not be the primary GOT), compute the offset from the beginning of
3244179404Sobrien   the (primary) GOT section to the entry in G corresponding to the
3245179404Sobrien   global symbol.  G's assigned_gotno must contain the index of the
3246179404Sobrien   first available global GOT entry in G.  VALUE must contain the size
3247179404Sobrien   of a GOT entry in bytes.  For each global GOT entry that requires a
3248179404Sobrien   dynamic relocation, NEEDED_RELOCS is incremented, and the symbol is
3249179404Sobrien   marked as not eligible for lazy resolution through a function
3250179404Sobrien   stub.  */
3251179404Sobrienstatic int
3252179404Sobrienmips_elf_set_global_got_offset (void **entryp, void *p)
3253179404Sobrien{
3254179404Sobrien  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
3255179404Sobrien  struct mips_elf_set_global_got_offset_arg *arg
3256179404Sobrien    = (struct mips_elf_set_global_got_offset_arg *)p;
3257179404Sobrien  struct mips_got_info *g = arg->g;
3258179404Sobrien
3259218822Sdim  if (g && entry->tls_type != GOT_NORMAL)
3260218822Sdim    arg->needed_relocs +=
3261218822Sdim      mips_tls_got_relocs (arg->info, entry->tls_type,
3262218822Sdim			   entry->symndx == -1 ? &entry->d.h->root : NULL);
3263218822Sdim
3264179404Sobrien  if (entry->abfd != NULL && entry->symndx == -1
3265218822Sdim      && entry->d.h->root.dynindx != -1
3266218822Sdim      && entry->d.h->tls_type == GOT_NORMAL)
3267179404Sobrien    {
3268179404Sobrien      if (g)
3269179404Sobrien	{
3270179404Sobrien	  BFD_ASSERT (g->global_gotsym == NULL);
3271179404Sobrien
3272179404Sobrien	  entry->gotidx = arg->value * (long) g->assigned_gotno++;
3273179404Sobrien	  if (arg->info->shared
3274179404Sobrien	      || (elf_hash_table (arg->info)->dynamic_sections_created
3275218822Sdim		  && entry->d.h->root.def_dynamic
3276218822Sdim		  && !entry->d.h->root.def_regular))
3277179404Sobrien	    ++arg->needed_relocs;
3278179404Sobrien	}
3279179404Sobrien      else
3280179404Sobrien	entry->d.h->root.got.offset = arg->value;
3281179404Sobrien    }
3282179404Sobrien
3283179404Sobrien  return 1;
3284179404Sobrien}
3285179404Sobrien
3286179404Sobrien/* Mark any global symbols referenced in the GOT we are iterating over
3287179404Sobrien   as inelligible for lazy resolution stubs.  */
3288179404Sobrienstatic int
3289179404Sobrienmips_elf_set_no_stub (void **entryp, void *p ATTRIBUTE_UNUSED)
3290179404Sobrien{
3291179404Sobrien  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
3292179404Sobrien
3293179404Sobrien  if (entry->abfd != NULL
3294179404Sobrien      && entry->symndx == -1
3295179404Sobrien      && entry->d.h->root.dynindx != -1)
3296179404Sobrien    entry->d.h->no_fn_stub = TRUE;
3297179404Sobrien
3298179404Sobrien  return 1;
3299179404Sobrien}
3300179404Sobrien
3301179404Sobrien/* Follow indirect and warning hash entries so that each got entry
3302179404Sobrien   points to the final symbol definition.  P must point to a pointer
3303179404Sobrien   to the hash table we're traversing.  Since this traversal may
3304179404Sobrien   modify the hash table, we set this pointer to NULL to indicate
3305179404Sobrien   we've made a potentially-destructive change to the hash table, so
3306179404Sobrien   the traversal must be restarted.  */
3307179404Sobrienstatic int
3308179404Sobrienmips_elf_resolve_final_got_entry (void **entryp, void *p)
3309179404Sobrien{
3310179404Sobrien  struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
3311179404Sobrien  htab_t got_entries = *(htab_t *)p;
3312179404Sobrien
3313179404Sobrien  if (entry->abfd != NULL && entry->symndx == -1)
3314179404Sobrien    {
3315179404Sobrien      struct mips_elf_link_hash_entry *h = entry->d.h;
3316179404Sobrien
3317179404Sobrien      while (h->root.root.type == bfd_link_hash_indirect
3318179404Sobrien 	     || h->root.root.type == bfd_link_hash_warning)
3319179404Sobrien	h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
3320179404Sobrien
3321179404Sobrien      if (entry->d.h == h)
3322179404Sobrien	return 1;
3323179404Sobrien
3324179404Sobrien      entry->d.h = h;
3325179404Sobrien
3326179404Sobrien      /* If we can't find this entry with the new bfd hash, re-insert
3327179404Sobrien	 it, and get the traversal restarted.  */
3328179404Sobrien      if (! htab_find (got_entries, entry))
3329179404Sobrien	{
3330179404Sobrien	  htab_clear_slot (got_entries, entryp);
3331179404Sobrien	  entryp = htab_find_slot (got_entries, entry, INSERT);
3332179404Sobrien	  if (! *entryp)
3333179404Sobrien	    *entryp = entry;
3334179404Sobrien	  /* Abort the traversal, since the whole table may have
3335179404Sobrien	     moved, and leave it up to the parent to restart the
3336179404Sobrien	     process.  */
3337179404Sobrien	  *(htab_t *)p = NULL;
3338179404Sobrien	  return 0;
3339179404Sobrien	}
3340179404Sobrien      /* We might want to decrement the global_gotno count, but it's
3341179404Sobrien	 either too early or too late for that at this point.  */
3342179404Sobrien    }
3343179404Sobrien
3344179404Sobrien  return 1;
3345179404Sobrien}
3346179404Sobrien
3347179404Sobrien/* Turn indirect got entries in a got_entries table into their final
3348179404Sobrien   locations.  */
3349179404Sobrienstatic void
3350179404Sobrienmips_elf_resolve_final_got_entries (struct mips_got_info *g)
3351179404Sobrien{
3352179404Sobrien  htab_t got_entries;
3353179404Sobrien
3354179404Sobrien  do
3355179404Sobrien    {
3356179404Sobrien      got_entries = g->got_entries;
3357179404Sobrien
3358179404Sobrien      htab_traverse (got_entries,
3359179404Sobrien		     mips_elf_resolve_final_got_entry,
3360179404Sobrien		     &got_entries);
3361179404Sobrien    }
3362179404Sobrien  while (got_entries == NULL);
3363179404Sobrien}
3364179404Sobrien
3365179404Sobrien/* Return the offset of an input bfd IBFD's GOT from the beginning of
3366179404Sobrien   the primary GOT.  */
3367179404Sobrienstatic bfd_vma
3368179404Sobrienmips_elf_adjust_gp (bfd *abfd, struct mips_got_info *g, bfd *ibfd)
3369179404Sobrien{
3370179404Sobrien  if (g->bfd2got == NULL)
3371179404Sobrien    return 0;
3372179404Sobrien
3373179404Sobrien  g = mips_elf_got_for_ibfd (g, ibfd);
3374179404Sobrien  if (! g)
3375179404Sobrien    return 0;
3376179404Sobrien
3377179404Sobrien  BFD_ASSERT (g->next);
3378179404Sobrien
3379179404Sobrien  g = g->next;
3380179404Sobrien
3381218822Sdim  return (g->local_gotno + g->global_gotno + g->tls_gotno)
3382218822Sdim    * MIPS_ELF_GOT_SIZE (abfd);
3383179404Sobrien}
3384179404Sobrien
3385179404Sobrien/* Turn a single GOT that is too big for 16-bit addressing into
3386179404Sobrien   a sequence of GOTs, each one 16-bit addressable.  */
3387179404Sobrien
3388179404Sobrienstatic bfd_boolean
3389179404Sobrienmips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
3390179404Sobrien		    struct mips_got_info *g, asection *got,
3391179404Sobrien		    bfd_size_type pages)
3392179404Sobrien{
3393179404Sobrien  struct mips_elf_got_per_bfd_arg got_per_bfd_arg;
3394179404Sobrien  struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
3395179404Sobrien  struct mips_got_info *gg;
3396179404Sobrien  unsigned int assign;
3397179404Sobrien
3398179404Sobrien  g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
3399179404Sobrien				mips_elf_bfd2got_entry_eq, NULL);
3400179404Sobrien  if (g->bfd2got == NULL)
3401179404Sobrien    return FALSE;
3402179404Sobrien
3403179404Sobrien  got_per_bfd_arg.bfd2got = g->bfd2got;
3404179404Sobrien  got_per_bfd_arg.obfd = abfd;
3405179404Sobrien  got_per_bfd_arg.info = info;
3406179404Sobrien
3407179404Sobrien  /* Count how many GOT entries each input bfd requires, creating a
3408179404Sobrien     map from bfd to got info while at that.  */
3409179404Sobrien  htab_traverse (g->got_entries, mips_elf_make_got_per_bfd, &got_per_bfd_arg);
3410179404Sobrien  if (got_per_bfd_arg.obfd == NULL)
3411179404Sobrien    return FALSE;
3412179404Sobrien
3413179404Sobrien  got_per_bfd_arg.current = NULL;
3414179404Sobrien  got_per_bfd_arg.primary = NULL;
3415179404Sobrien  /* Taking out PAGES entries is a worst-case estimate.  We could
3416179404Sobrien     compute the maximum number of pages that each separate input bfd
3417179404Sobrien     uses, but it's probably not worth it.  */
3418218822Sdim  got_per_bfd_arg.max_count = ((MIPS_ELF_GOT_MAX_SIZE (info)
3419179404Sobrien				/ MIPS_ELF_GOT_SIZE (abfd))
3420218822Sdim			       - MIPS_RESERVED_GOTNO (info) - pages);
3421218822Sdim  /* The number of globals that will be included in the primary GOT.
3422218822Sdim     See the calls to mips_elf_set_global_got_offset below for more
3423218822Sdim     information.  */
3424218822Sdim  got_per_bfd_arg.global_count = g->global_gotno;
3425179404Sobrien
3426179404Sobrien  /* Try to merge the GOTs of input bfds together, as long as they
3427179404Sobrien     don't seem to exceed the maximum GOT size, choosing one of them
3428179404Sobrien     to be the primary GOT.  */
3429179404Sobrien  htab_traverse (g->bfd2got, mips_elf_merge_gots, &got_per_bfd_arg);
3430179404Sobrien  if (got_per_bfd_arg.obfd == NULL)
3431179404Sobrien    return FALSE;
3432179404Sobrien
3433218822Sdim  /* If we do not find any suitable primary GOT, create an empty one.  */
3434179404Sobrien  if (got_per_bfd_arg.primary == NULL)
3435179404Sobrien    {
3436179404Sobrien      g->next = (struct mips_got_info *)
3437179404Sobrien	bfd_alloc (abfd, sizeof (struct mips_got_info));
3438179404Sobrien      if (g->next == NULL)
3439179404Sobrien	return FALSE;
3440179404Sobrien
3441179404Sobrien      g->next->global_gotsym = NULL;
3442179404Sobrien      g->next->global_gotno = 0;
3443179404Sobrien      g->next->local_gotno = 0;
3444218822Sdim      g->next->tls_gotno = 0;
3445179404Sobrien      g->next->assigned_gotno = 0;
3446218822Sdim      g->next->tls_assigned_gotno = 0;
3447218822Sdim      g->next->tls_ldm_offset = MINUS_ONE;
3448179404Sobrien      g->next->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
3449179404Sobrien					      mips_elf_multi_got_entry_eq,
3450179404Sobrien					      NULL);
3451179404Sobrien      if (g->next->got_entries == NULL)
3452179404Sobrien	return FALSE;
3453179404Sobrien      g->next->bfd2got = NULL;
3454179404Sobrien    }
3455179404Sobrien  else
3456179404Sobrien    g->next = got_per_bfd_arg.primary;
3457179404Sobrien  g->next->next = got_per_bfd_arg.current;
3458179404Sobrien
3459179404Sobrien  /* GG is now the master GOT, and G is the primary GOT.  */
3460179404Sobrien  gg = g;
3461179404Sobrien  g = g->next;
3462179404Sobrien
3463179404Sobrien  /* Map the output bfd to the primary got.  That's what we're going
3464179404Sobrien     to use for bfds that use GOT16 or GOT_PAGE relocations that we
3465179404Sobrien     didn't mark in check_relocs, and we want a quick way to find it.
3466179404Sobrien     We can't just use gg->next because we're going to reverse the
3467179404Sobrien     list.  */
3468179404Sobrien  {
3469179404Sobrien    struct mips_elf_bfd2got_hash *bfdgot;
3470179404Sobrien    void **bfdgotp;
3471179404Sobrien
3472179404Sobrien    bfdgot = (struct mips_elf_bfd2got_hash *)bfd_alloc
3473179404Sobrien      (abfd, sizeof (struct mips_elf_bfd2got_hash));
3474179404Sobrien
3475179404Sobrien    if (bfdgot == NULL)
3476179404Sobrien      return FALSE;
3477179404Sobrien
3478179404Sobrien    bfdgot->bfd = abfd;
3479179404Sobrien    bfdgot->g = g;
3480179404Sobrien    bfdgotp = htab_find_slot (gg->bfd2got, bfdgot, INSERT);
3481179404Sobrien
3482179404Sobrien    BFD_ASSERT (*bfdgotp == NULL);
3483179404Sobrien    *bfdgotp = bfdgot;
3484179404Sobrien  }
3485179404Sobrien
3486179404Sobrien  /* The IRIX dynamic linker requires every symbol that is referenced
3487179404Sobrien     in a dynamic relocation to be present in the primary GOT, so
3488179404Sobrien     arrange for them to appear after those that are actually
3489179404Sobrien     referenced.
3490179404Sobrien
3491179404Sobrien     GNU/Linux could very well do without it, but it would slow down
3492179404Sobrien     the dynamic linker, since it would have to resolve every dynamic
3493179404Sobrien     symbol referenced in other GOTs more than once, without help from
3494179404Sobrien     the cache.  Also, knowing that every external symbol has a GOT
3495179404Sobrien     helps speed up the resolution of local symbols too, so GNU/Linux
3496179404Sobrien     follows IRIX's practice.
3497179404Sobrien
3498179404Sobrien     The number 2 is used by mips_elf_sort_hash_table_f to count
3499179404Sobrien     global GOT symbols that are unreferenced in the primary GOT, with
3500179404Sobrien     an initial dynamic index computed from gg->assigned_gotno, where
3501179404Sobrien     the number of unreferenced global entries in the primary GOT is
3502179404Sobrien     preserved.  */
3503179404Sobrien  if (1)
3504179404Sobrien    {
3505179404Sobrien      gg->assigned_gotno = gg->global_gotno - g->global_gotno;
3506179404Sobrien      g->global_gotno = gg->global_gotno;
3507179404Sobrien      set_got_offset_arg.value = 2;
3508179404Sobrien    }
3509179404Sobrien  else
3510179404Sobrien    {
3511179404Sobrien      /* This could be used for dynamic linkers that don't optimize
3512179404Sobrien	 symbol resolution while applying relocations so as to use
3513179404Sobrien	 primary GOT entries or assuming the symbol is locally-defined.
3514179404Sobrien	 With this code, we assign lower dynamic indices to global
3515179404Sobrien	 symbols that are not referenced in the primary GOT, so that
3516179404Sobrien	 their entries can be omitted.  */
3517179404Sobrien      gg->assigned_gotno = 0;
3518179404Sobrien      set_got_offset_arg.value = -1;
3519179404Sobrien    }
3520179404Sobrien
3521179404Sobrien  /* Reorder dynamic symbols as described above (which behavior
3522179404Sobrien     depends on the setting of VALUE).  */
3523179404Sobrien  set_got_offset_arg.g = NULL;
3524179404Sobrien  htab_traverse (gg->got_entries, mips_elf_set_global_got_offset,
3525179404Sobrien		 &set_got_offset_arg);
3526179404Sobrien  set_got_offset_arg.value = 1;
3527179404Sobrien  htab_traverse (g->got_entries, mips_elf_set_global_got_offset,
3528179404Sobrien		 &set_got_offset_arg);
3529179404Sobrien  if (! mips_elf_sort_hash_table (info, 1))
3530179404Sobrien    return FALSE;
3531179404Sobrien
3532179404Sobrien  /* Now go through the GOTs assigning them offset ranges.
3533179404Sobrien     [assigned_gotno, local_gotno[ will be set to the range of local
3534179404Sobrien     entries in each GOT.  We can then compute the end of a GOT by
3535179404Sobrien     adding local_gotno to global_gotno.  We reverse the list and make
3536179404Sobrien     it circular since then we'll be able to quickly compute the
3537179404Sobrien     beginning of a GOT, by computing the end of its predecessor.  To
3538179404Sobrien     avoid special cases for the primary GOT, while still preserving
3539179404Sobrien     assertions that are valid for both single- and multi-got links,
3540179404Sobrien     we arrange for the main got struct to have the right number of
3541179404Sobrien     global entries, but set its local_gotno such that the initial
3542179404Sobrien     offset of the primary GOT is zero.  Remember that the primary GOT
3543179404Sobrien     will become the last item in the circular linked list, so it
3544179404Sobrien     points back to the master GOT.  */
3545179404Sobrien  gg->local_gotno = -g->global_gotno;
3546179404Sobrien  gg->global_gotno = g->global_gotno;
3547218822Sdim  gg->tls_gotno = 0;
3548179404Sobrien  assign = 0;
3549179404Sobrien  gg->next = gg;
3550179404Sobrien
3551179404Sobrien  do
3552179404Sobrien    {
3553179404Sobrien      struct mips_got_info *gn;
3554179404Sobrien
3555218822Sdim      assign += MIPS_RESERVED_GOTNO (info);
3556179404Sobrien      g->assigned_gotno = assign;
3557179404Sobrien      g->local_gotno += assign + pages;
3558218822Sdim      assign = g->local_gotno + g->global_gotno + g->tls_gotno;
3559179404Sobrien
3560179404Sobrien      /* Take g out of the direct list, and push it onto the reversed
3561218822Sdim	 list that gg points to.  g->next is guaranteed to be nonnull after
3562218822Sdim	 this operation, as required by mips_elf_initialize_tls_index. */
3563179404Sobrien      gn = g->next;
3564179404Sobrien      g->next = gg->next;
3565179404Sobrien      gg->next = g;
3566218822Sdim
3567218822Sdim      /* Set up any TLS entries.  We always place the TLS entries after
3568218822Sdim	 all non-TLS entries.  */
3569218822Sdim      g->tls_assigned_gotno = g->local_gotno + g->global_gotno;
3570218822Sdim      htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
3571218822Sdim
3572218822Sdim      /* Move onto the next GOT.  It will be a secondary GOT if nonull.  */
3573179404Sobrien      g = gn;
3574179404Sobrien
3575179404Sobrien      /* Mark global symbols in every non-primary GOT as ineligible for
3576179404Sobrien	 stubs.  */
3577179404Sobrien      if (g)
3578179404Sobrien	htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
3579179404Sobrien    }
3580179404Sobrien  while (g);
3581179404Sobrien
3582218822Sdim  got->size = (gg->next->local_gotno
3583218822Sdim		    + gg->next->global_gotno
3584218822Sdim		    + gg->next->tls_gotno) * MIPS_ELF_GOT_SIZE (abfd);
3585179404Sobrien
3586179404Sobrien  return TRUE;
3587179404Sobrien}
3588179404Sobrien
3589179404Sobrien
3590179404Sobrien/* Returns the first relocation of type r_type found, beginning with
3591179404Sobrien   RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
3592179404Sobrien
3593179404Sobrienstatic const Elf_Internal_Rela *
3594179404Sobrienmips_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
3595179404Sobrien			  const Elf_Internal_Rela *relocation,
3596179404Sobrien			  const Elf_Internal_Rela *relend)
3597179404Sobrien{
3598218822Sdim  unsigned long r_symndx = ELF_R_SYM (abfd, relocation->r_info);
3599218822Sdim
3600179404Sobrien  while (relocation < relend)
3601179404Sobrien    {
3602218822Sdim      if (ELF_R_TYPE (abfd, relocation->r_info) == r_type
3603218822Sdim	  && ELF_R_SYM (abfd, relocation->r_info) == r_symndx)
3604179404Sobrien	return relocation;
3605179404Sobrien
3606179404Sobrien      ++relocation;
3607179404Sobrien    }
3608179404Sobrien
3609179404Sobrien  /* We didn't find it.  */
3610179404Sobrien  return NULL;
3611179404Sobrien}
3612179404Sobrien
3613179404Sobrien/* Return whether a relocation is against a local symbol.  */
3614179404Sobrien
3615179404Sobrienstatic bfd_boolean
3616179404Sobrienmips_elf_local_relocation_p (bfd *input_bfd,
3617179404Sobrien			     const Elf_Internal_Rela *relocation,
3618179404Sobrien			     asection **local_sections,
3619179404Sobrien			     bfd_boolean check_forced)
3620179404Sobrien{
3621179404Sobrien  unsigned long r_symndx;
3622179404Sobrien  Elf_Internal_Shdr *symtab_hdr;
3623179404Sobrien  struct mips_elf_link_hash_entry *h;
3624179404Sobrien  size_t extsymoff;
3625179404Sobrien
3626179404Sobrien  r_symndx = ELF_R_SYM (input_bfd, relocation->r_info);
3627179404Sobrien  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
3628179404Sobrien  extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
3629179404Sobrien
3630179404Sobrien  if (r_symndx < extsymoff)
3631179404Sobrien    return TRUE;
3632179404Sobrien  if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL)
3633179404Sobrien    return TRUE;
3634179404Sobrien
3635179404Sobrien  if (check_forced)
3636179404Sobrien    {
3637179404Sobrien      /* Look up the hash table to check whether the symbol
3638179404Sobrien 	 was forced local.  */
3639179404Sobrien      h = (struct mips_elf_link_hash_entry *)
3640179404Sobrien	elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
3641179404Sobrien      /* Find the real hash-table entry for this symbol.  */
3642179404Sobrien      while (h->root.root.type == bfd_link_hash_indirect
3643179404Sobrien 	     || h->root.root.type == bfd_link_hash_warning)
3644179404Sobrien	h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
3645218822Sdim      if (h->root.forced_local)
3646179404Sobrien	return TRUE;
3647179404Sobrien    }
3648179404Sobrien
3649179404Sobrien  return FALSE;
3650179404Sobrien}
3651179404Sobrien
3652179404Sobrien/* Sign-extend VALUE, which has the indicated number of BITS.  */
3653179404Sobrien
3654179404Sobrienbfd_vma
3655179404Sobrien_bfd_mips_elf_sign_extend (bfd_vma value, int bits)
3656179404Sobrien{
3657179404Sobrien  if (value & ((bfd_vma) 1 << (bits - 1)))
3658179404Sobrien    /* VALUE is negative.  */
3659179404Sobrien    value |= ((bfd_vma) - 1) << bits;
3660179404Sobrien
3661179404Sobrien  return value;
3662179404Sobrien}
3663179404Sobrien
3664179404Sobrien/* Return non-zero if the indicated VALUE has overflowed the maximum
3665179404Sobrien   range expressible by a signed number with the indicated number of
3666179404Sobrien   BITS.  */
3667179404Sobrien
3668179404Sobrienstatic bfd_boolean
3669179404Sobrienmips_elf_overflow_p (bfd_vma value, int bits)
3670179404Sobrien{
3671179404Sobrien  bfd_signed_vma svalue = (bfd_signed_vma) value;
3672179404Sobrien
3673179404Sobrien  if (svalue > (1 << (bits - 1)) - 1)
3674179404Sobrien    /* The value is too big.  */
3675179404Sobrien    return TRUE;
3676179404Sobrien  else if (svalue < -(1 << (bits - 1)))
3677179404Sobrien    /* The value is too small.  */
3678179404Sobrien    return TRUE;
3679179404Sobrien
3680179404Sobrien  /* All is well.  */
3681179404Sobrien  return FALSE;
3682179404Sobrien}
3683179404Sobrien
3684179404Sobrien/* Calculate the %high function.  */
3685179404Sobrien
3686179404Sobrienstatic bfd_vma
3687179404Sobrienmips_elf_high (bfd_vma value)
3688179404Sobrien{
3689179404Sobrien  return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
3690179404Sobrien}
3691179404Sobrien
3692179404Sobrien/* Calculate the %higher function.  */
3693179404Sobrien
3694179404Sobrienstatic bfd_vma
3695179404Sobrienmips_elf_higher (bfd_vma value ATTRIBUTE_UNUSED)
3696179404Sobrien{
3697179404Sobrien#ifdef BFD64
3698179404Sobrien  return ((value + (bfd_vma) 0x80008000) >> 32) & 0xffff;
3699179404Sobrien#else
3700179404Sobrien  abort ();
3701218822Sdim  return MINUS_ONE;
3702179404Sobrien#endif
3703179404Sobrien}
3704179404Sobrien
3705179404Sobrien/* Calculate the %highest function.  */
3706179404Sobrien
3707179404Sobrienstatic bfd_vma
3708179404Sobrienmips_elf_highest (bfd_vma value ATTRIBUTE_UNUSED)
3709179404Sobrien{
3710179404Sobrien#ifdef BFD64
3711179404Sobrien  return ((value + (((bfd_vma) 0x8000 << 32) | 0x80008000)) >> 48) & 0xffff;
3712179404Sobrien#else
3713179404Sobrien  abort ();
3714218822Sdim  return MINUS_ONE;
3715179404Sobrien#endif
3716179404Sobrien}
3717179404Sobrien
3718179404Sobrien/* Create the .compact_rel section.  */
3719179404Sobrien
3720179404Sobrienstatic bfd_boolean
3721179404Sobrienmips_elf_create_compact_rel_section
3722179404Sobrien  (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
3723179404Sobrien{
3724179404Sobrien  flagword flags;
3725179404Sobrien  register asection *s;
3726179404Sobrien
3727179404Sobrien  if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
3728179404Sobrien    {
3729179404Sobrien      flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED
3730179404Sobrien	       | SEC_READONLY);
3731179404Sobrien
3732218822Sdim      s = bfd_make_section_with_flags (abfd, ".compact_rel", flags);
3733179404Sobrien      if (s == NULL
3734179404Sobrien	  || ! bfd_set_section_alignment (abfd, s,
3735179404Sobrien					  MIPS_ELF_LOG_FILE_ALIGN (abfd)))
3736179404Sobrien	return FALSE;
3737179404Sobrien
3738218822Sdim      s->size = sizeof (Elf32_External_compact_rel);
3739179404Sobrien    }
3740179404Sobrien
3741179404Sobrien  return TRUE;
3742179404Sobrien}
3743179404Sobrien
3744179404Sobrien/* Create the .got section to hold the global offset table.  */
3745179404Sobrien
3746179404Sobrienstatic bfd_boolean
3747179404Sobrienmips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
3748179404Sobrien			     bfd_boolean maybe_exclude)
3749179404Sobrien{
3750179404Sobrien  flagword flags;
3751179404Sobrien  register asection *s;
3752179404Sobrien  struct elf_link_hash_entry *h;
3753179404Sobrien  struct bfd_link_hash_entry *bh;
3754179404Sobrien  struct mips_got_info *g;
3755179404Sobrien  bfd_size_type amt;
3756218822Sdim  struct mips_elf_link_hash_table *htab;
3757179404Sobrien
3758218822Sdim  htab = mips_elf_hash_table (info);
3759218822Sdim
3760179404Sobrien  /* This function may be called more than once.  */
3761179404Sobrien  s = mips_elf_got_section (abfd, TRUE);
3762179404Sobrien  if (s)
3763179404Sobrien    {
3764179404Sobrien      if (! maybe_exclude)
3765179404Sobrien	s->flags &= ~SEC_EXCLUDE;
3766179404Sobrien      return TRUE;
3767179404Sobrien    }
3768179404Sobrien
3769179404Sobrien  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
3770179404Sobrien	   | SEC_LINKER_CREATED);
3771179404Sobrien
3772179404Sobrien  if (maybe_exclude)
3773179404Sobrien    flags |= SEC_EXCLUDE;
3774179404Sobrien
3775179404Sobrien  /* We have to use an alignment of 2**4 here because this is hardcoded
3776179404Sobrien     in the function stub generation and in the linker script.  */
3777218822Sdim  s = bfd_make_section_with_flags (abfd, ".got", flags);
3778179404Sobrien  if (s == NULL
3779179404Sobrien      || ! bfd_set_section_alignment (abfd, s, 4))
3780179404Sobrien    return FALSE;
3781179404Sobrien
3782179404Sobrien  /* Define the symbol _GLOBAL_OFFSET_TABLE_.  We don't do this in the
3783179404Sobrien     linker script because we don't want to define the symbol if we
3784179404Sobrien     are not creating a global offset table.  */
3785179404Sobrien  bh = NULL;
3786179404Sobrien  if (! (_bfd_generic_link_add_one_symbol
3787179404Sobrien	 (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
3788179404Sobrien	  0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
3789179404Sobrien    return FALSE;
3790179404Sobrien
3791179404Sobrien  h = (struct elf_link_hash_entry *) bh;
3792218822Sdim  h->non_elf = 0;
3793218822Sdim  h->def_regular = 1;
3794179404Sobrien  h->type = STT_OBJECT;
3795218822Sdim  elf_hash_table (info)->hgot = h;
3796179404Sobrien
3797179404Sobrien  if (info->shared
3798179404Sobrien      && ! bfd_elf_link_record_dynamic_symbol (info, h))
3799179404Sobrien    return FALSE;
3800179404Sobrien
3801179404Sobrien  amt = sizeof (struct mips_got_info);
3802179404Sobrien  g = bfd_alloc (abfd, amt);
3803179404Sobrien  if (g == NULL)
3804179404Sobrien    return FALSE;
3805179404Sobrien  g->global_gotsym = NULL;
3806179404Sobrien  g->global_gotno = 0;
3807218822Sdim  g->tls_gotno = 0;
3808218822Sdim  g->local_gotno = MIPS_RESERVED_GOTNO (info);
3809218822Sdim  g->assigned_gotno = MIPS_RESERVED_GOTNO (info);
3810179404Sobrien  g->bfd2got = NULL;
3811179404Sobrien  g->next = NULL;
3812218822Sdim  g->tls_ldm_offset = MINUS_ONE;
3813179404Sobrien  g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
3814179404Sobrien				    mips_elf_got_entry_eq, NULL);
3815179404Sobrien  if (g->got_entries == NULL)
3816179404Sobrien    return FALSE;
3817179404Sobrien  mips_elf_section_data (s)->u.got_info = g;
3818179404Sobrien  mips_elf_section_data (s)->elf.this_hdr.sh_flags
3819179404Sobrien    |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
3820179404Sobrien
3821218822Sdim  /* VxWorks also needs a .got.plt section.  */
3822218822Sdim  if (htab->is_vxworks)
3823218822Sdim    {
3824218822Sdim      s = bfd_make_section_with_flags (abfd, ".got.plt",
3825218822Sdim				       SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
3826218822Sdim				       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
3827218822Sdim      if (s == NULL || !bfd_set_section_alignment (abfd, s, 4))
3828218822Sdim	return FALSE;
3829218822Sdim
3830218822Sdim      htab->sgotplt = s;
3831218822Sdim    }
3832179404Sobrien  return TRUE;
3833179404Sobrien}
3834179404Sobrien
3835218822Sdim/* Return true if H refers to the special VxWorks __GOTT_BASE__ or
3836218822Sdim   __GOTT_INDEX__ symbols.  These symbols are only special for
3837218822Sdim   shared objects; they are not used in executables.  */
3838218822Sdim
3839218822Sdimstatic bfd_boolean
3840218822Sdimis_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
3841218822Sdim{
3842218822Sdim  return (mips_elf_hash_table (info)->is_vxworks
3843218822Sdim	  && info->shared
3844218822Sdim	  && (strcmp (h->root.root.string, "__GOTT_BASE__") == 0
3845218822Sdim	      || strcmp (h->root.root.string, "__GOTT_INDEX__") == 0));
3846218822Sdim}
3847218822Sdim
3848179404Sobrien/* Calculate the value produced by the RELOCATION (which comes from
3849179404Sobrien   the INPUT_BFD).  The ADDEND is the addend to use for this
3850179404Sobrien   RELOCATION; RELOCATION->R_ADDEND is ignored.
3851179404Sobrien
3852179404Sobrien   The result of the relocation calculation is stored in VALUEP.
3853179404Sobrien   REQUIRE_JALXP indicates whether or not the opcode used with this
3854179404Sobrien   relocation must be JALX.
3855179404Sobrien
3856179404Sobrien   This function returns bfd_reloc_continue if the caller need take no
3857179404Sobrien   further action regarding this relocation, bfd_reloc_notsupported if
3858179404Sobrien   something goes dramatically wrong, bfd_reloc_overflow if an
3859179404Sobrien   overflow occurs, and bfd_reloc_ok to indicate success.  */
3860179404Sobrien
3861179404Sobrienstatic bfd_reloc_status_type
3862179404Sobrienmips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
3863179404Sobrien			       asection *input_section,
3864179404Sobrien			       struct bfd_link_info *info,
3865179404Sobrien			       const Elf_Internal_Rela *relocation,
3866179404Sobrien			       bfd_vma addend, reloc_howto_type *howto,
3867179404Sobrien			       Elf_Internal_Sym *local_syms,
3868179404Sobrien			       asection **local_sections, bfd_vma *valuep,
3869179404Sobrien			       const char **namep, bfd_boolean *require_jalxp,
3870179404Sobrien			       bfd_boolean save_addend)
3871179404Sobrien{
3872179404Sobrien  /* The eventual value we will return.  */
3873179404Sobrien  bfd_vma value;
3874179404Sobrien  /* The address of the symbol against which the relocation is
3875179404Sobrien     occurring.  */
3876179404Sobrien  bfd_vma symbol = 0;
3877179404Sobrien  /* The final GP value to be used for the relocatable, executable, or
3878179404Sobrien     shared object file being produced.  */
3879179404Sobrien  bfd_vma gp = MINUS_ONE;
3880179404Sobrien  /* The place (section offset or address) of the storage unit being
3881179404Sobrien     relocated.  */
3882179404Sobrien  bfd_vma p;
3883179404Sobrien  /* The value of GP used to create the relocatable object.  */
3884179404Sobrien  bfd_vma gp0 = MINUS_ONE;
3885179404Sobrien  /* The offset into the global offset table at which the address of
3886179404Sobrien     the relocation entry symbol, adjusted by the addend, resides
3887179404Sobrien     during execution.  */
3888179404Sobrien  bfd_vma g = MINUS_ONE;
3889179404Sobrien  /* The section in which the symbol referenced by the relocation is
3890179404Sobrien     located.  */
3891179404Sobrien  asection *sec = NULL;
3892179404Sobrien  struct mips_elf_link_hash_entry *h = NULL;
3893179404Sobrien  /* TRUE if the symbol referred to by this relocation is a local
3894179404Sobrien     symbol.  */
3895179404Sobrien  bfd_boolean local_p, was_local_p;
3896179404Sobrien  /* TRUE if the symbol referred to by this relocation is "_gp_disp".  */
3897179404Sobrien  bfd_boolean gp_disp_p = FALSE;
3898218822Sdim  /* TRUE if the symbol referred to by this relocation is
3899218822Sdim     "__gnu_local_gp".  */
3900218822Sdim  bfd_boolean gnu_local_gp_p = FALSE;
3901179404Sobrien  Elf_Internal_Shdr *symtab_hdr;
3902179404Sobrien  size_t extsymoff;
3903179404Sobrien  unsigned long r_symndx;
3904179404Sobrien  int r_type;
3905179404Sobrien  /* TRUE if overflow occurred during the calculation of the
3906179404Sobrien     relocation value.  */
3907179404Sobrien  bfd_boolean overflowed_p;
3908179404Sobrien  /* TRUE if this relocation refers to a MIPS16 function.  */
3909179404Sobrien  bfd_boolean target_is_16_bit_code_p = FALSE;
3910218822Sdim  struct mips_elf_link_hash_table *htab;
3911218822Sdim  bfd *dynobj;
3912179404Sobrien
3913218822Sdim  dynobj = elf_hash_table (info)->dynobj;
3914218822Sdim  htab = mips_elf_hash_table (info);
3915218822Sdim
3916179404Sobrien  /* Parse the relocation.  */
3917179404Sobrien  r_symndx = ELF_R_SYM (input_bfd, relocation->r_info);
3918179404Sobrien  r_type = ELF_R_TYPE (input_bfd, relocation->r_info);
3919179404Sobrien  p = (input_section->output_section->vma
3920179404Sobrien       + input_section->output_offset
3921179404Sobrien       + relocation->r_offset);
3922179404Sobrien
3923179404Sobrien  /* Assume that there will be no overflow.  */
3924179404Sobrien  overflowed_p = FALSE;
3925179404Sobrien
3926179404Sobrien  /* Figure out whether or not the symbol is local, and get the offset
3927179404Sobrien     used in the array of hash table entries.  */
3928179404Sobrien  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
3929179404Sobrien  local_p = mips_elf_local_relocation_p (input_bfd, relocation,
3930179404Sobrien					 local_sections, FALSE);
3931179404Sobrien  was_local_p = local_p;
3932179404Sobrien  if (! elf_bad_symtab (input_bfd))
3933179404Sobrien    extsymoff = symtab_hdr->sh_info;
3934179404Sobrien  else
3935179404Sobrien    {
3936179404Sobrien      /* The symbol table does not follow the rule that local symbols
3937179404Sobrien	 must come before globals.  */
3938179404Sobrien      extsymoff = 0;
3939179404Sobrien    }
3940179404Sobrien
3941179404Sobrien  /* Figure out the value of the symbol.  */
3942179404Sobrien  if (local_p)
3943179404Sobrien    {
3944179404Sobrien      Elf_Internal_Sym *sym;
3945179404Sobrien
3946179404Sobrien      sym = local_syms + r_symndx;
3947179404Sobrien      sec = local_sections[r_symndx];
3948179404Sobrien
3949179404Sobrien      symbol = sec->output_section->vma + sec->output_offset;
3950179404Sobrien      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION
3951179404Sobrien	  || (sec->flags & SEC_MERGE))
3952179404Sobrien	symbol += sym->st_value;
3953179404Sobrien      if ((sec->flags & SEC_MERGE)
3954179404Sobrien	  && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
3955179404Sobrien	{
3956179404Sobrien	  addend = _bfd_elf_rel_local_sym (abfd, sym, &sec, addend);
3957179404Sobrien	  addend -= symbol;
3958179404Sobrien	  addend += sec->output_section->vma + sec->output_offset;
3959179404Sobrien	}
3960179404Sobrien
3961179404Sobrien      /* MIPS16 text labels should be treated as odd.  */
3962179404Sobrien      if (sym->st_other == STO_MIPS16)
3963179404Sobrien	++symbol;
3964179404Sobrien
3965179404Sobrien      /* Record the name of this symbol, for our caller.  */
3966179404Sobrien      *namep = bfd_elf_string_from_elf_section (input_bfd,
3967179404Sobrien						symtab_hdr->sh_link,
3968179404Sobrien						sym->st_name);
3969179404Sobrien      if (*namep == '\0')
3970179404Sobrien	*namep = bfd_section_name (input_bfd, sec);
3971179404Sobrien
3972179404Sobrien      target_is_16_bit_code_p = (sym->st_other == STO_MIPS16);
3973179404Sobrien    }
3974179404Sobrien  else
3975179404Sobrien    {
3976179404Sobrien      /* ??? Could we use RELOC_FOR_GLOBAL_SYMBOL here ?  */
3977179404Sobrien
3978179404Sobrien      /* For global symbols we look up the symbol in the hash-table.  */
3979179404Sobrien      h = ((struct mips_elf_link_hash_entry *)
3980179404Sobrien	   elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
3981179404Sobrien      /* Find the real hash-table entry for this symbol.  */
3982179404Sobrien      while (h->root.root.type == bfd_link_hash_indirect
3983179404Sobrien	     || h->root.root.type == bfd_link_hash_warning)
3984179404Sobrien	h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
3985179404Sobrien
3986179404Sobrien      /* Record the name of this symbol, for our caller.  */
3987179404Sobrien      *namep = h->root.root.root.string;
3988179404Sobrien
3989179404Sobrien      /* See if this is the special _gp_disp symbol.  Note that such a
3990179404Sobrien	 symbol must always be a global symbol.  */
3991179404Sobrien      if (strcmp (*namep, "_gp_disp") == 0
3992179404Sobrien	  && ! NEWABI_P (input_bfd))
3993179404Sobrien	{
3994179404Sobrien	  /* Relocations against _gp_disp are permitted only with
3995179404Sobrien	     R_MIPS_HI16 and R_MIPS_LO16 relocations.  */
3996218822Sdim	  if (r_type != R_MIPS_HI16 && r_type != R_MIPS_LO16
3997218822Sdim	      && r_type != R_MIPS16_HI16 && r_type != R_MIPS16_LO16)
3998179404Sobrien	    return bfd_reloc_notsupported;
3999179404Sobrien
4000179404Sobrien	  gp_disp_p = TRUE;
4001179404Sobrien	}
4002218822Sdim      /* See if this is the special _gp symbol.  Note that such a
4003218822Sdim	 symbol must always be a global symbol.  */
4004218822Sdim      else if (strcmp (*namep, "__gnu_local_gp") == 0)
4005218822Sdim	gnu_local_gp_p = TRUE;
4006218822Sdim
4007218822Sdim
4008179404Sobrien      /* If this symbol is defined, calculate its address.  Note that
4009179404Sobrien	 _gp_disp is a magic symbol, always implicitly defined by the
4010179404Sobrien	 linker, so it's inappropriate to check to see whether or not
4011179404Sobrien	 its defined.  */
4012179404Sobrien      else if ((h->root.root.type == bfd_link_hash_defined
4013179404Sobrien		|| h->root.root.type == bfd_link_hash_defweak)
4014179404Sobrien	       && h->root.root.u.def.section)
4015179404Sobrien	{
4016179404Sobrien	  sec = h->root.root.u.def.section;
4017179404Sobrien	  if (sec->output_section)
4018179404Sobrien	    symbol = (h->root.root.u.def.value
4019179404Sobrien		      + sec->output_section->vma
4020179404Sobrien		      + sec->output_offset);
4021179404Sobrien	  else
4022179404Sobrien	    symbol = h->root.root.u.def.value;
4023179404Sobrien	}
4024179404Sobrien      else if (h->root.root.type == bfd_link_hash_undefweak)
4025179404Sobrien	/* We allow relocations against undefined weak symbols, giving
4026179404Sobrien	   it the value zero, so that you can undefined weak functions
4027179404Sobrien	   and check to see if they exist by looking at their
4028179404Sobrien	   addresses.  */
4029179404Sobrien	symbol = 0;
4030179404Sobrien      else if (info->unresolved_syms_in_objects == RM_IGNORE
4031179404Sobrien	       && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
4032179404Sobrien	symbol = 0;
4033218822Sdim      else if (strcmp (*namep, SGI_COMPAT (input_bfd)
4034218822Sdim		       ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING") == 0)
4035179404Sobrien	{
4036179404Sobrien	  /* If this is a dynamic link, we should have created a
4037179404Sobrien	     _DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol
4038179404Sobrien	     in in _bfd_mips_elf_create_dynamic_sections.
4039179404Sobrien	     Otherwise, we should define the symbol with a value of 0.
4040179404Sobrien	     FIXME: It should probably get into the symbol table
4041179404Sobrien	     somehow as well.  */
4042179404Sobrien	  BFD_ASSERT (! info->shared);
4043179404Sobrien	  BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
4044179404Sobrien	  symbol = 0;
4045179404Sobrien	}
4046218822Sdim      else if (ELF_MIPS_IS_OPTIONAL (h->root.other))
4047218822Sdim	{
4048218822Sdim	  /* This is an optional symbol - an Irix specific extension to the
4049218822Sdim	     ELF spec.  Ignore it for now.
4050218822Sdim	     XXX - FIXME - there is more to the spec for OPTIONAL symbols
4051218822Sdim	     than simply ignoring them, but we do not handle this for now.
4052218822Sdim	     For information see the "64-bit ELF Object File Specification"
4053218822Sdim	     which is available from here:
4054218822Sdim	     http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf  */
4055218822Sdim	  symbol = 0;
4056218822Sdim	}
4057179404Sobrien      else
4058179404Sobrien	{
4059179404Sobrien	  if (! ((*info->callbacks->undefined_symbol)
4060179404Sobrien		 (info, h->root.root.root.string, input_bfd,
4061179404Sobrien		  input_section, relocation->r_offset,
4062179404Sobrien		  (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
4063179404Sobrien		   || ELF_ST_VISIBILITY (h->root.other))))
4064179404Sobrien	    return bfd_reloc_undefined;
4065179404Sobrien	  symbol = 0;
4066179404Sobrien	}
4067179404Sobrien
4068179404Sobrien      target_is_16_bit_code_p = (h->root.other == STO_MIPS16);
4069179404Sobrien    }
4070179404Sobrien
4071179404Sobrien  /* If this is a 32- or 64-bit call to a 16-bit function with a stub, we
4072179404Sobrien     need to redirect the call to the stub, unless we're already *in*
4073179404Sobrien     a stub.  */
4074179404Sobrien  if (r_type != R_MIPS16_26 && !info->relocatable
4075179404Sobrien      && ((h != NULL && h->fn_stub != NULL)
4076218822Sdim	  || (local_p
4077218822Sdim	      && elf_tdata (input_bfd)->local_stubs != NULL
4078179404Sobrien	      && elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
4079218822Sdim      && !mips16_stub_section_p (input_bfd, input_section))
4080179404Sobrien    {
4081179404Sobrien      /* This is a 32- or 64-bit call to a 16-bit function.  We should
4082179404Sobrien	 have already noticed that we were going to need the
4083179404Sobrien	 stub.  */
4084179404Sobrien      if (local_p)
4085179404Sobrien	sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
4086179404Sobrien      else
4087179404Sobrien	{
4088179404Sobrien	  BFD_ASSERT (h->need_fn_stub);
4089179404Sobrien	  sec = h->fn_stub;
4090179404Sobrien	}
4091179404Sobrien
4092179404Sobrien      symbol = sec->output_section->vma + sec->output_offset;
4093218822Sdim      /* The target is 16-bit, but the stub isn't.  */
4094218822Sdim      target_is_16_bit_code_p = FALSE;
4095179404Sobrien    }
4096179404Sobrien  /* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
4097179404Sobrien     need to redirect the call to the stub.  */
4098179404Sobrien  else if (r_type == R_MIPS16_26 && !info->relocatable
4099218822Sdim	   && ((h != NULL && (h->call_stub != NULL || h->call_fp_stub != NULL))
4100218822Sdim	       || (local_p
4101218822Sdim		   && elf_tdata (input_bfd)->local_call_stubs != NULL
4102218822Sdim		   && elf_tdata (input_bfd)->local_call_stubs[r_symndx] != NULL))
4103179404Sobrien	   && !target_is_16_bit_code_p)
4104179404Sobrien    {
4105218822Sdim      if (local_p)
4106218822Sdim	sec = elf_tdata (input_bfd)->local_call_stubs[r_symndx];
4107218822Sdim      else
4108179404Sobrien	{
4109218822Sdim	  /* If both call_stub and call_fp_stub are defined, we can figure
4110218822Sdim	     out which one to use by checking which one appears in the input
4111218822Sdim	     file.  */
4112218822Sdim	  if (h->call_stub != NULL && h->call_fp_stub != NULL)
4113179404Sobrien	    {
4114218822Sdim	      asection *o;
4115218822Sdim
4116218822Sdim	      sec = NULL;
4117218822Sdim	      for (o = input_bfd->sections; o != NULL; o = o->next)
4118179404Sobrien		{
4119218822Sdim		  if (CALL_FP_STUB_P (bfd_get_section_name (input_bfd, o)))
4120218822Sdim		    {
4121218822Sdim		      sec = h->call_fp_stub;
4122218822Sdim		      break;
4123218822Sdim		    }
4124179404Sobrien		}
4125218822Sdim	      if (sec == NULL)
4126218822Sdim		sec = h->call_stub;
4127179404Sobrien	    }
4128218822Sdim	  else if (h->call_stub != NULL)
4129179404Sobrien	    sec = h->call_stub;
4130218822Sdim	  else
4131218822Sdim	    sec = h->call_fp_stub;
4132218822Sdim  	}
4133179404Sobrien
4134218822Sdim      BFD_ASSERT (sec->size > 0);
4135179404Sobrien      symbol = sec->output_section->vma + sec->output_offset;
4136179404Sobrien    }
4137179404Sobrien
4138179404Sobrien  /* Calls from 16-bit code to 32-bit code and vice versa require the
4139179404Sobrien     special jalx instruction.  */
4140179404Sobrien  *require_jalxp = (!info->relocatable
4141179404Sobrien                    && (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
4142179404Sobrien                        || ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
4143179404Sobrien
4144179404Sobrien  local_p = mips_elf_local_relocation_p (input_bfd, relocation,
4145179404Sobrien					 local_sections, TRUE);
4146179404Sobrien
4147179404Sobrien  /* If we haven't already determined the GOT offset, or the GP value,
4148179404Sobrien     and we're going to need it, get it now.  */
4149179404Sobrien  switch (r_type)
4150179404Sobrien    {
4151179404Sobrien    case R_MIPS_GOT_PAGE:
4152179404Sobrien    case R_MIPS_GOT_OFST:
4153179404Sobrien      /* We need to decay to GOT_DISP/addend if the symbol doesn't
4154179404Sobrien	 bind locally.  */
4155179404Sobrien      local_p = local_p || _bfd_elf_symbol_refs_local_p (&h->root, info, 1);
4156179404Sobrien      if (local_p || r_type == R_MIPS_GOT_OFST)
4157179404Sobrien	break;
4158179404Sobrien      /* Fall through.  */
4159179404Sobrien
4160179404Sobrien    case R_MIPS_CALL16:
4161179404Sobrien    case R_MIPS_GOT16:
4162179404Sobrien    case R_MIPS_GOT_DISP:
4163179404Sobrien    case R_MIPS_GOT_HI16:
4164179404Sobrien    case R_MIPS_CALL_HI16:
4165179404Sobrien    case R_MIPS_GOT_LO16:
4166179404Sobrien    case R_MIPS_CALL_LO16:
4167218822Sdim    case R_MIPS_TLS_GD:
4168218822Sdim    case R_MIPS_TLS_GOTTPREL:
4169218822Sdim    case R_MIPS_TLS_LDM:
4170179404Sobrien      /* Find the index into the GOT where this value is located.  */
4171218822Sdim      if (r_type == R_MIPS_TLS_LDM)
4172179404Sobrien	{
4173218822Sdim	  g = mips_elf_local_got_index (abfd, input_bfd, info,
4174218822Sdim					0, 0, NULL, r_type);
4175218822Sdim	  if (g == MINUS_ONE)
4176218822Sdim	    return bfd_reloc_outofrange;
4177218822Sdim	}
4178218822Sdim      else if (!local_p)
4179218822Sdim	{
4180218822Sdim	  /* On VxWorks, CALL relocations should refer to the .got.plt
4181218822Sdim	     entry, which is initialized to point at the PLT stub.  */
4182218822Sdim	  if (htab->is_vxworks
4183218822Sdim	      && (r_type == R_MIPS_CALL_HI16
4184218822Sdim		  || r_type == R_MIPS_CALL_LO16
4185218822Sdim		  || r_type == R_MIPS_CALL16))
4186179404Sobrien	    {
4187218822Sdim	      BFD_ASSERT (addend == 0);
4188218822Sdim	      BFD_ASSERT (h->root.needs_plt);
4189218822Sdim	      g = mips_elf_gotplt_index (info, &h->root);
4190179404Sobrien	    }
4191218822Sdim	  else
4192218822Sdim	    {
4193218822Sdim	      /* GOT_PAGE may take a non-zero addend, that is ignored in a
4194218822Sdim		 GOT_PAGE relocation that decays to GOT_DISP because the
4195218822Sdim		 symbol turns out to be global.  The addend is then added
4196218822Sdim		 as GOT_OFST.  */
4197218822Sdim	      BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE);
4198218822Sdim	      g = mips_elf_global_got_index (dynobj, input_bfd,
4199218822Sdim					     &h->root, r_type, info);
4200218822Sdim	      if (h->tls_type == GOT_NORMAL
4201218822Sdim		  && (! elf_hash_table(info)->dynamic_sections_created
4202218822Sdim		      || (info->shared
4203218822Sdim			  && (info->symbolic || h->root.forced_local)
4204218822Sdim			  && h->root.def_regular)))
4205218822Sdim		{
4206218822Sdim		  /* This is a static link or a -Bsymbolic link.  The
4207218822Sdim		     symbol is defined locally, or was forced to be local.
4208218822Sdim		     We must initialize this entry in the GOT.  */
4209218822Sdim		  asection *sgot = mips_elf_got_section (dynobj, FALSE);
4210218822Sdim		  MIPS_ELF_PUT_WORD (dynobj, symbol, sgot->contents + g);
4211218822Sdim		}
4212218822Sdim	    }
4213179404Sobrien	}
4214218822Sdim      else if (!htab->is_vxworks
4215218822Sdim	       && (r_type == R_MIPS_CALL16 || (r_type == R_MIPS_GOT16)))
4216218822Sdim	/* The calculation below does not involve "g".  */
4217179404Sobrien	break;
4218179404Sobrien      else
4219179404Sobrien	{
4220218822Sdim	  g = mips_elf_local_got_index (abfd, input_bfd, info,
4221218822Sdim					symbol + addend, r_symndx, h, r_type);
4222179404Sobrien	  if (g == MINUS_ONE)
4223179404Sobrien	    return bfd_reloc_outofrange;
4224179404Sobrien	}
4225179404Sobrien
4226179404Sobrien      /* Convert GOT indices to actual offsets.  */
4227218822Sdim      g = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, g);
4228179404Sobrien      break;
4229179404Sobrien
4230179404Sobrien    case R_MIPS_HI16:
4231179404Sobrien    case R_MIPS_LO16:
4232179404Sobrien    case R_MIPS_GPREL16:
4233179404Sobrien    case R_MIPS_GPREL32:
4234179404Sobrien    case R_MIPS_LITERAL:
4235218822Sdim    case R_MIPS16_HI16:
4236218822Sdim    case R_MIPS16_LO16:
4237218822Sdim    case R_MIPS16_GPREL:
4238179404Sobrien      gp0 = _bfd_get_gp_value (input_bfd);
4239179404Sobrien      gp = _bfd_get_gp_value (abfd);
4240218822Sdim      if (dynobj)
4241218822Sdim	gp += mips_elf_adjust_gp (abfd, mips_elf_got_info (dynobj, NULL),
4242179404Sobrien				  input_bfd);
4243179404Sobrien      break;
4244179404Sobrien
4245179404Sobrien    default:
4246179404Sobrien      break;
4247179404Sobrien    }
4248179404Sobrien
4249218822Sdim  if (gnu_local_gp_p)
4250218822Sdim    symbol = gp;
4251218822Sdim
4252218822Sdim  /* Relocations against the VxWorks __GOTT_BASE__ and __GOTT_INDEX__
4253218822Sdim     symbols are resolved by the loader.  Add them to .rela.dyn.  */
4254218822Sdim  if (h != NULL && is_gott_symbol (info, &h->root))
4255218822Sdim    {
4256218822Sdim      Elf_Internal_Rela outrel;
4257218822Sdim      bfd_byte *loc;
4258218822Sdim      asection *s;
4259218822Sdim
4260218822Sdim      s = mips_elf_rel_dyn_section (info, FALSE);
4261218822Sdim      loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
4262218822Sdim
4263218822Sdim      outrel.r_offset = (input_section->output_section->vma
4264218822Sdim			 + input_section->output_offset
4265218822Sdim			 + relocation->r_offset);
4266218822Sdim      outrel.r_info = ELF32_R_INFO (h->root.dynindx, r_type);
4267218822Sdim      outrel.r_addend = addend;
4268218822Sdim      bfd_elf32_swap_reloca_out (abfd, &outrel, loc);
4269218822Sdim
4270218822Sdim      /* If we've written this relocation for a readonly section,
4271218822Sdim	 we need to set DF_TEXTREL again, so that we do not delete the
4272218822Sdim	 DT_TEXTREL tag.  */
4273218822Sdim      if (MIPS_ELF_READONLY_SECTION (input_section))
4274218822Sdim	info->flags |= DF_TEXTREL;
4275218822Sdim
4276218822Sdim      *valuep = 0;
4277218822Sdim      return bfd_reloc_ok;
4278218822Sdim    }
4279218822Sdim
4280179404Sobrien  /* Figure out what kind of relocation is being performed.  */
4281179404Sobrien  switch (r_type)
4282179404Sobrien    {
4283179404Sobrien    case R_MIPS_NONE:
4284179404Sobrien      return bfd_reloc_continue;
4285179404Sobrien
4286179404Sobrien    case R_MIPS_16:
4287179404Sobrien      value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
4288179404Sobrien      overflowed_p = mips_elf_overflow_p (value, 16);
4289179404Sobrien      break;
4290179404Sobrien
4291179404Sobrien    case R_MIPS_32:
4292179404Sobrien    case R_MIPS_REL32:
4293179404Sobrien    case R_MIPS_64:
4294179404Sobrien      if ((info->shared
4295218822Sdim	   || (!htab->is_vxworks
4296218822Sdim	       && htab->root.dynamic_sections_created
4297179404Sobrien	       && h != NULL
4298218822Sdim	       && h->root.def_dynamic
4299218822Sdim	       && !h->root.def_regular))
4300179404Sobrien	  && r_symndx != 0
4301179404Sobrien	  && (input_section->flags & SEC_ALLOC) != 0)
4302179404Sobrien	{
4303179404Sobrien	  /* If we're creating a shared library, or this relocation is
4304179404Sobrien	     against a symbol in a shared library, then we can't know
4305179404Sobrien	     where the symbol will end up.  So, we create a relocation
4306179404Sobrien	     record in the output, and leave the job up to the dynamic
4307218822Sdim	     linker.
4308218822Sdim
4309218822Sdim	     In VxWorks executables, references to external symbols
4310218822Sdim	     are handled using copy relocs or PLT stubs, so there's
4311218822Sdim	     no need to add a dynamic relocation here.  */
4312179404Sobrien	  value = addend;
4313179404Sobrien	  if (!mips_elf_create_dynamic_relocation (abfd,
4314179404Sobrien						   info,
4315179404Sobrien						   relocation,
4316179404Sobrien						   h,
4317179404Sobrien						   sec,
4318179404Sobrien						   symbol,
4319179404Sobrien						   &value,
4320179404Sobrien						   input_section))
4321179404Sobrien	    return bfd_reloc_undefined;
4322179404Sobrien	}
4323179404Sobrien      else
4324179404Sobrien	{
4325179404Sobrien	  if (r_type != R_MIPS_REL32)
4326179404Sobrien	    value = symbol + addend;
4327179404Sobrien	  else
4328179404Sobrien	    value = addend;
4329179404Sobrien	}
4330179404Sobrien      value &= howto->dst_mask;
4331179404Sobrien      break;
4332179404Sobrien
4333179404Sobrien    case R_MIPS_PC32:
4334179404Sobrien      value = symbol + addend - p;
4335179404Sobrien      value &= howto->dst_mask;
4336179404Sobrien      break;
4337179404Sobrien
4338179404Sobrien    case R_MIPS16_26:
4339179404Sobrien      /* The calculation for R_MIPS16_26 is just the same as for an
4340179404Sobrien	 R_MIPS_26.  It's only the storage of the relocated field into
4341179404Sobrien	 the output file that's different.  That's handled in
4342179404Sobrien	 mips_elf_perform_relocation.  So, we just fall through to the
4343179404Sobrien	 R_MIPS_26 case here.  */
4344179404Sobrien    case R_MIPS_26:
4345179404Sobrien      if (local_p)
4346179404Sobrien	value = ((addend | ((p + 4) & 0xf0000000)) + symbol) >> 2;
4347179404Sobrien      else
4348218822Sdim	{
4349218822Sdim	  value = (_bfd_mips_elf_sign_extend (addend, 28) + symbol) >> 2;
4350218822Sdim	  if (h->root.root.type != bfd_link_hash_undefweak)
4351218822Sdim	    overflowed_p = (value >> 26) != ((p + 4) >> 28);
4352218822Sdim	}
4353179404Sobrien      value &= howto->dst_mask;
4354179404Sobrien      break;
4355179404Sobrien
4356218822Sdim    case R_MIPS_TLS_DTPREL_HI16:
4357218822Sdim      value = (mips_elf_high (addend + symbol - dtprel_base (info))
4358218822Sdim	       & howto->dst_mask);
4359218822Sdim      break;
4360218822Sdim
4361218822Sdim    case R_MIPS_TLS_DTPREL_LO16:
4362218822Sdim    case R_MIPS_TLS_DTPREL32:
4363218822Sdim    case R_MIPS_TLS_DTPREL64:
4364218822Sdim      value = (symbol + addend - dtprel_base (info)) & howto->dst_mask;
4365218822Sdim      break;
4366218822Sdim
4367218822Sdim    case R_MIPS_TLS_TPREL_HI16:
4368218822Sdim      value = (mips_elf_high (addend + symbol - tprel_base (info))
4369218822Sdim	       & howto->dst_mask);
4370218822Sdim      break;
4371218822Sdim
4372218822Sdim    case R_MIPS_TLS_TPREL_LO16:
4373218822Sdim      value = (symbol + addend - tprel_base (info)) & howto->dst_mask;
4374218822Sdim      break;
4375218822Sdim
4376179404Sobrien    case R_MIPS_HI16:
4377218822Sdim    case R_MIPS16_HI16:
4378179404Sobrien      if (!gp_disp_p)
4379179404Sobrien	{
4380179404Sobrien	  value = mips_elf_high (addend + symbol);
4381179404Sobrien	  value &= howto->dst_mask;
4382179404Sobrien	}
4383179404Sobrien      else
4384179404Sobrien	{
4385218822Sdim	  /* For MIPS16 ABI code we generate this sequence
4386218822Sdim	        0: li      $v0,%hi(_gp_disp)
4387218822Sdim	        4: addiupc $v1,%lo(_gp_disp)
4388218822Sdim	        8: sll     $v0,16
4389218822Sdim	       12: addu    $v0,$v1
4390218822Sdim	       14: move    $gp,$v0
4391218822Sdim	     So the offsets of hi and lo relocs are the same, but the
4392218822Sdim	     $pc is four higher than $t9 would be, so reduce
4393218822Sdim	     both reloc addends by 4. */
4394218822Sdim	  if (r_type == R_MIPS16_HI16)
4395218822Sdim	    value = mips_elf_high (addend + gp - p - 4);
4396218822Sdim	  else
4397218822Sdim	    value = mips_elf_high (addend + gp - p);
4398179404Sobrien	  overflowed_p = mips_elf_overflow_p (value, 16);
4399179404Sobrien	}
4400179404Sobrien      break;
4401179404Sobrien
4402179404Sobrien    case R_MIPS_LO16:
4403218822Sdim    case R_MIPS16_LO16:
4404179404Sobrien      if (!gp_disp_p)
4405179404Sobrien	value = (symbol + addend) & howto->dst_mask;
4406179404Sobrien      else
4407179404Sobrien	{
4408218822Sdim	  /* See the comment for R_MIPS16_HI16 above for the reason
4409218822Sdim	     for this conditional.  */
4410218822Sdim	  if (r_type == R_MIPS16_LO16)
4411218822Sdim	    value = addend + gp - p;
4412218822Sdim	  else
4413218822Sdim	    value = addend + gp - p + 4;
4414179404Sobrien	  /* The MIPS ABI requires checking the R_MIPS_LO16 relocation
4415179404Sobrien	     for overflow.  But, on, say, IRIX5, relocations against
4416179404Sobrien	     _gp_disp are normally generated from the .cpload
4417179404Sobrien	     pseudo-op.  It generates code that normally looks like
4418179404Sobrien	     this:
4419179404Sobrien
4420179404Sobrien	       lui    $gp,%hi(_gp_disp)
4421179404Sobrien	       addiu  $gp,$gp,%lo(_gp_disp)
4422179404Sobrien	       addu   $gp,$gp,$t9
4423179404Sobrien
4424179404Sobrien	     Here $t9 holds the address of the function being called,
4425179404Sobrien	     as required by the MIPS ELF ABI.  The R_MIPS_LO16
4426179404Sobrien	     relocation can easily overflow in this situation, but the
4427179404Sobrien	     R_MIPS_HI16 relocation will handle the overflow.
4428179404Sobrien	     Therefore, we consider this a bug in the MIPS ABI, and do
4429179404Sobrien	     not check for overflow here.  */
4430179404Sobrien	}
4431179404Sobrien      break;
4432179404Sobrien
4433179404Sobrien    case R_MIPS_LITERAL:
4434179404Sobrien      /* Because we don't merge literal sections, we can handle this
4435179404Sobrien	 just like R_MIPS_GPREL16.  In the long run, we should merge
4436179404Sobrien	 shared literals, and then we will need to additional work
4437179404Sobrien	 here.  */
4438179404Sobrien
4439179404Sobrien      /* Fall through.  */
4440179404Sobrien
4441179404Sobrien    case R_MIPS16_GPREL:
4442179404Sobrien      /* The R_MIPS16_GPREL performs the same calculation as
4443179404Sobrien	 R_MIPS_GPREL16, but stores the relocated bits in a different
4444179404Sobrien	 order.  We don't need to do anything special here; the
4445179404Sobrien	 differences are handled in mips_elf_perform_relocation.  */
4446179404Sobrien    case R_MIPS_GPREL16:
4447179404Sobrien      /* Only sign-extend the addend if it was extracted from the
4448179404Sobrien	 instruction.  If the addend was separate, leave it alone,
4449179404Sobrien	 otherwise we may lose significant bits.  */
4450179404Sobrien      if (howto->partial_inplace)
4451179404Sobrien	addend = _bfd_mips_elf_sign_extend (addend, 16);
4452179404Sobrien      value = symbol + addend - gp;
4453179404Sobrien      /* If the symbol was local, any earlier relocatable links will
4454179404Sobrien	 have adjusted its addend with the gp offset, so compensate
4455179404Sobrien	 for that now.  Don't do it for symbols forced local in this
4456179404Sobrien	 link, though, since they won't have had the gp offset applied
4457179404Sobrien	 to them before.  */
4458179404Sobrien      if (was_local_p)
4459179404Sobrien	value += gp0;
4460179404Sobrien      overflowed_p = mips_elf_overflow_p (value, 16);
4461179404Sobrien      break;
4462179404Sobrien
4463179404Sobrien    case R_MIPS_GOT16:
4464179404Sobrien    case R_MIPS_CALL16:
4465218822Sdim      /* VxWorks does not have separate local and global semantics for
4466218822Sdim	 R_MIPS_GOT16; every relocation evaluates to "G".  */
4467218822Sdim      if (!htab->is_vxworks && local_p)
4468179404Sobrien	{
4469179404Sobrien	  bfd_boolean forced;
4470179404Sobrien
4471179404Sobrien	  forced = ! mips_elf_local_relocation_p (input_bfd, relocation,
4472179404Sobrien						  local_sections, FALSE);
4473179404Sobrien	  value = mips_elf_got16_entry (abfd, input_bfd, info,
4474179404Sobrien					symbol + addend, forced);
4475179404Sobrien	  if (value == MINUS_ONE)
4476179404Sobrien	    return bfd_reloc_outofrange;
4477179404Sobrien	  value
4478218822Sdim	    = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value);
4479179404Sobrien	  overflowed_p = mips_elf_overflow_p (value, 16);
4480179404Sobrien	  break;
4481179404Sobrien	}
4482179404Sobrien
4483179404Sobrien      /* Fall through.  */
4484179404Sobrien
4485218822Sdim    case R_MIPS_TLS_GD:
4486218822Sdim    case R_MIPS_TLS_GOTTPREL:
4487218822Sdim    case R_MIPS_TLS_LDM:
4488179404Sobrien    case R_MIPS_GOT_DISP:
4489179404Sobrien    got_disp:
4490179404Sobrien      value = g;
4491179404Sobrien      overflowed_p = mips_elf_overflow_p (value, 16);
4492179404Sobrien      break;
4493179404Sobrien
4494179404Sobrien    case R_MIPS_GPREL32:
4495179404Sobrien      value = (addend + symbol + gp0 - gp);
4496179404Sobrien      if (!save_addend)
4497179404Sobrien	value &= howto->dst_mask;
4498179404Sobrien      break;
4499179404Sobrien
4500179404Sobrien    case R_MIPS_PC16:
4501218822Sdim    case R_MIPS_GNU_REL16_S2:
4502218822Sdim      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
4503218822Sdim      overflowed_p = mips_elf_overflow_p (value, 18);
4504218822Sdim      value >>= howto->rightshift;
4505218822Sdim      value &= howto->dst_mask;
4506179404Sobrien      break;
4507179404Sobrien
4508179404Sobrien    case R_MIPS_GOT_HI16:
4509179404Sobrien    case R_MIPS_CALL_HI16:
4510179404Sobrien      /* We're allowed to handle these two relocations identically.
4511179404Sobrien	 The dynamic linker is allowed to handle the CALL relocations
4512179404Sobrien	 differently by creating a lazy evaluation stub.  */
4513179404Sobrien      value = g;
4514179404Sobrien      value = mips_elf_high (value);
4515179404Sobrien      value &= howto->dst_mask;
4516179404Sobrien      break;
4517179404Sobrien
4518179404Sobrien    case R_MIPS_GOT_LO16:
4519179404Sobrien    case R_MIPS_CALL_LO16:
4520179404Sobrien      value = g & howto->dst_mask;
4521179404Sobrien      break;
4522179404Sobrien
4523179404Sobrien    case R_MIPS_GOT_PAGE:
4524179404Sobrien      /* GOT_PAGE relocations that reference non-local symbols decay
4525179404Sobrien	 to GOT_DISP.  The corresponding GOT_OFST relocation decays to
4526179404Sobrien	 0.  */
4527179404Sobrien      if (! local_p)
4528179404Sobrien	goto got_disp;
4529179404Sobrien      value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL);
4530179404Sobrien      if (value == MINUS_ONE)
4531179404Sobrien	return bfd_reloc_outofrange;
4532218822Sdim      value = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value);
4533179404Sobrien      overflowed_p = mips_elf_overflow_p (value, 16);
4534179404Sobrien      break;
4535179404Sobrien
4536179404Sobrien    case R_MIPS_GOT_OFST:
4537179404Sobrien      if (local_p)
4538179404Sobrien	mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
4539179404Sobrien      else
4540179404Sobrien	value = addend;
4541179404Sobrien      overflowed_p = mips_elf_overflow_p (value, 16);
4542179404Sobrien      break;
4543179404Sobrien
4544179404Sobrien    case R_MIPS_SUB:
4545179404Sobrien      value = symbol - addend;
4546179404Sobrien      value &= howto->dst_mask;
4547179404Sobrien      break;
4548179404Sobrien
4549179404Sobrien    case R_MIPS_HIGHER:
4550179404Sobrien      value = mips_elf_higher (addend + symbol);
4551179404Sobrien      value &= howto->dst_mask;
4552179404Sobrien      break;
4553179404Sobrien
4554179404Sobrien    case R_MIPS_HIGHEST:
4555179404Sobrien      value = mips_elf_highest (addend + symbol);
4556179404Sobrien      value &= howto->dst_mask;
4557179404Sobrien      break;
4558179404Sobrien
4559179404Sobrien    case R_MIPS_SCN_DISP:
4560179404Sobrien      value = symbol + addend - sec->output_offset;
4561179404Sobrien      value &= howto->dst_mask;
4562179404Sobrien      break;
4563179404Sobrien
4564179404Sobrien    case R_MIPS_JALR:
4565218822Sdim      /* This relocation is only a hint.  In some cases, we optimize
4566218822Sdim	 it into a bal instruction.  But we don't try to optimize
4567218822Sdim	 branches to the PLT; that will wind up wasting time.  */
4568218822Sdim      if (h != NULL && h->root.plt.offset != (bfd_vma) -1)
4569218822Sdim	return bfd_reloc_continue;
4570218822Sdim      value = symbol + addend;
4571218822Sdim      break;
4572179404Sobrien
4573218822Sdim    case R_MIPS_PJUMP:
4574179404Sobrien    case R_MIPS_GNU_VTINHERIT:
4575179404Sobrien    case R_MIPS_GNU_VTENTRY:
4576179404Sobrien      /* We don't do anything with these at present.  */
4577179404Sobrien      return bfd_reloc_continue;
4578179404Sobrien
4579179404Sobrien    default:
4580179404Sobrien      /* An unrecognized relocation type.  */
4581179404Sobrien      return bfd_reloc_notsupported;
4582179404Sobrien    }
4583179404Sobrien
4584179404Sobrien  /* Store the VALUE for our caller.  */
4585179404Sobrien  *valuep = value;
4586179404Sobrien  return overflowed_p ? bfd_reloc_overflow : bfd_reloc_ok;
4587179404Sobrien}
4588179404Sobrien
4589179404Sobrien/* Obtain the field relocated by RELOCATION.  */
4590179404Sobrien
4591179404Sobrienstatic bfd_vma
4592179404Sobrienmips_elf_obtain_contents (reloc_howto_type *howto,
4593179404Sobrien			  const Elf_Internal_Rela *relocation,
4594179404Sobrien			  bfd *input_bfd, bfd_byte *contents)
4595179404Sobrien{
4596179404Sobrien  bfd_vma x;
4597179404Sobrien  bfd_byte *location = contents + relocation->r_offset;
4598179404Sobrien
4599179404Sobrien  /* Obtain the bytes.  */
4600179404Sobrien  x = bfd_get ((8 * bfd_get_reloc_size (howto)), input_bfd, location);
4601179404Sobrien
4602179404Sobrien  return x;
4603179404Sobrien}
4604179404Sobrien
4605179404Sobrien/* It has been determined that the result of the RELOCATION is the
4606179404Sobrien   VALUE.  Use HOWTO to place VALUE into the output file at the
4607179404Sobrien   appropriate position.  The SECTION is the section to which the
4608179404Sobrien   relocation applies.  If REQUIRE_JALX is TRUE, then the opcode used
4609179404Sobrien   for the relocation must be either JAL or JALX, and it is
4610179404Sobrien   unconditionally converted to JALX.
4611179404Sobrien
4612179404Sobrien   Returns FALSE if anything goes wrong.  */
4613179404Sobrien
4614179404Sobrienstatic bfd_boolean
4615179404Sobrienmips_elf_perform_relocation (struct bfd_link_info *info,
4616179404Sobrien			     reloc_howto_type *howto,
4617179404Sobrien			     const Elf_Internal_Rela *relocation,
4618179404Sobrien			     bfd_vma value, bfd *input_bfd,
4619179404Sobrien			     asection *input_section, bfd_byte *contents,
4620179404Sobrien			     bfd_boolean require_jalx)
4621179404Sobrien{
4622179404Sobrien  bfd_vma x;
4623179404Sobrien  bfd_byte *location;
4624179404Sobrien  int r_type = ELF_R_TYPE (input_bfd, relocation->r_info);
4625179404Sobrien
4626179404Sobrien  /* Figure out where the relocation is occurring.  */
4627179404Sobrien  location = contents + relocation->r_offset;
4628179404Sobrien
4629218822Sdim  _bfd_mips16_elf_reloc_unshuffle (input_bfd, r_type, FALSE, location);
4630218822Sdim
4631179404Sobrien  /* Obtain the current value.  */
4632179404Sobrien  x = mips_elf_obtain_contents (howto, relocation, input_bfd, contents);
4633179404Sobrien
4634179404Sobrien  /* Clear the field we are setting.  */
4635179404Sobrien  x &= ~howto->dst_mask;
4636179404Sobrien
4637179404Sobrien  /* Set the field.  */
4638179404Sobrien  x |= (value & howto->dst_mask);
4639179404Sobrien
4640179404Sobrien  /* If required, turn JAL into JALX.  */
4641179404Sobrien  if (require_jalx)
4642179404Sobrien    {
4643179404Sobrien      bfd_boolean ok;
4644179404Sobrien      bfd_vma opcode = x >> 26;
4645179404Sobrien      bfd_vma jalx_opcode;
4646179404Sobrien
4647179404Sobrien      /* Check to see if the opcode is already JAL or JALX.  */
4648179404Sobrien      if (r_type == R_MIPS16_26)
4649179404Sobrien	{
4650179404Sobrien	  ok = ((opcode == 0x6) || (opcode == 0x7));
4651179404Sobrien	  jalx_opcode = 0x7;
4652179404Sobrien	}
4653179404Sobrien      else
4654179404Sobrien	{
4655179404Sobrien	  ok = ((opcode == 0x3) || (opcode == 0x1d));
4656179404Sobrien	  jalx_opcode = 0x1d;
4657179404Sobrien	}
4658179404Sobrien
4659179404Sobrien      /* If the opcode is not JAL or JALX, there's a problem.  */
4660179404Sobrien      if (!ok)
4661179404Sobrien	{
4662179404Sobrien	  (*_bfd_error_handler)
4663218822Sdim	    (_("%B: %A+0x%lx: jump to stub routine which is not jal"),
4664218822Sdim	     input_bfd,
4665218822Sdim	     input_section,
4666179404Sobrien	     (unsigned long) relocation->r_offset);
4667179404Sobrien	  bfd_set_error (bfd_error_bad_value);
4668179404Sobrien	  return FALSE;
4669179404Sobrien	}
4670179404Sobrien
4671179404Sobrien      /* Make this the JALX opcode.  */
4672179404Sobrien      x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
4673179404Sobrien    }
4674179404Sobrien
4675218822Sdim  /* On the RM9000, bal is faster than jal, because bal uses branch
4676218822Sdim     prediction hardware.  If we are linking for the RM9000, and we
4677218822Sdim     see jal, and bal fits, use it instead.  Note that this
4678218822Sdim     transformation should be safe for all architectures.  */
4679218822Sdim  if (bfd_get_mach (input_bfd) == bfd_mach_mips9000
4680218822Sdim      && !info->relocatable
4681218822Sdim      && !require_jalx
4682218822Sdim      && ((r_type == R_MIPS_26 && (x >> 26) == 0x3)	    /* jal addr */
4683218822Sdim	  || (r_type == R_MIPS_JALR && x == 0x0320f809)))   /* jalr t9 */
4684218822Sdim    {
4685218822Sdim      bfd_vma addr;
4686218822Sdim      bfd_vma dest;
4687218822Sdim      bfd_signed_vma off;
4688179404Sobrien
4689218822Sdim      addr = (input_section->output_section->vma
4690218822Sdim	      + input_section->output_offset
4691218822Sdim	      + relocation->r_offset
4692218822Sdim	      + 4);
4693218822Sdim      if (r_type == R_MIPS_26)
4694218822Sdim	dest = (value << 2) | ((addr >> 28) << 28);
4695218822Sdim      else
4696218822Sdim	dest = value;
4697218822Sdim      off = dest - addr;
4698218822Sdim      if (off <= 0x1ffff && off >= -0x20000)
4699218822Sdim	x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff);   /* bal addr */
4700218822Sdim    }
4701218822Sdim
4702179404Sobrien  /* Put the value into the output.  */
4703179404Sobrien  bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
4704218822Sdim
4705218822Sdim  _bfd_mips16_elf_reloc_shuffle(input_bfd, r_type, !info->relocatable,
4706218822Sdim				location);
4707218822Sdim
4708179404Sobrien  return TRUE;
4709179404Sobrien}
4710179404Sobrien
4711179404Sobrien/* Returns TRUE if SECTION is a MIPS16 stub section.  */
4712179404Sobrien
4713179404Sobrienstatic bfd_boolean
4714218822Sdimmips16_stub_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
4715179404Sobrien{
4716179404Sobrien  const char *name = bfd_get_section_name (abfd, section);
4717179404Sobrien
4718218822Sdim  return FN_STUB_P (name) || CALL_STUB_P (name) || CALL_FP_STUB_P (name);
4719179404Sobrien}
4720179404Sobrien
4721218822Sdim/* Add room for N relocations to the .rel(a).dyn section in ABFD.  */
4722179404Sobrien
4723179404Sobrienstatic void
4724218822Sdimmips_elf_allocate_dynamic_relocations (bfd *abfd, struct bfd_link_info *info,
4725218822Sdim				       unsigned int n)
4726179404Sobrien{
4727179404Sobrien  asection *s;
4728218822Sdim  struct mips_elf_link_hash_table *htab;
4729179404Sobrien
4730218822Sdim  htab = mips_elf_hash_table (info);
4731218822Sdim  s = mips_elf_rel_dyn_section (info, FALSE);
4732179404Sobrien  BFD_ASSERT (s != NULL);
4733179404Sobrien
4734218822Sdim  if (htab->is_vxworks)
4735218822Sdim    s->size += n * MIPS_ELF_RELA_SIZE (abfd);
4736218822Sdim  else
4737179404Sobrien    {
4738218822Sdim      if (s->size == 0)
4739218822Sdim	{
4740218822Sdim	  /* Make room for a null element.  */
4741218822Sdim	  s->size += MIPS_ELF_REL_SIZE (abfd);
4742218822Sdim	  ++s->reloc_count;
4743218822Sdim	}
4744218822Sdim      s->size += n * MIPS_ELF_REL_SIZE (abfd);
4745179404Sobrien    }
4746179404Sobrien}
4747179404Sobrien
4748179404Sobrien/* Create a rel.dyn relocation for the dynamic linker to resolve.  REL
4749179404Sobrien   is the original relocation, which is now being transformed into a
4750179404Sobrien   dynamic relocation.  The ADDENDP is adjusted if necessary; the
4751179404Sobrien   caller should store the result in place of the original addend.  */
4752179404Sobrien
4753179404Sobrienstatic bfd_boolean
4754179404Sobrienmips_elf_create_dynamic_relocation (bfd *output_bfd,
4755179404Sobrien				    struct bfd_link_info *info,
4756179404Sobrien				    const Elf_Internal_Rela *rel,
4757179404Sobrien				    struct mips_elf_link_hash_entry *h,
4758179404Sobrien				    asection *sec, bfd_vma symbol,
4759179404Sobrien				    bfd_vma *addendp, asection *input_section)
4760179404Sobrien{
4761179404Sobrien  Elf_Internal_Rela outrel[3];
4762179404Sobrien  asection *sreloc;
4763179404Sobrien  bfd *dynobj;
4764179404Sobrien  int r_type;
4765218822Sdim  long indx;
4766218822Sdim  bfd_boolean defined_p;
4767218822Sdim  struct mips_elf_link_hash_table *htab;
4768179404Sobrien
4769218822Sdim  htab = mips_elf_hash_table (info);
4770179404Sobrien  r_type = ELF_R_TYPE (output_bfd, rel->r_info);
4771179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
4772218822Sdim  sreloc = mips_elf_rel_dyn_section (info, FALSE);
4773179404Sobrien  BFD_ASSERT (sreloc != NULL);
4774179404Sobrien  BFD_ASSERT (sreloc->contents != NULL);
4775179404Sobrien  BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd)
4776218822Sdim	      < sreloc->size);
4777179404Sobrien
4778179404Sobrien  outrel[0].r_offset =
4779179404Sobrien    _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
4780218822Sdim  if (ABI_64_P (output_bfd))
4781179404Sobrien    {
4782218822Sdim      outrel[1].r_offset =
4783218822Sdim	_bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset);
4784218822Sdim      outrel[2].r_offset =
4785218822Sdim	_bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset);
4786179404Sobrien    }
4787179404Sobrien
4788218822Sdim  if (outrel[0].r_offset == MINUS_ONE)
4789179404Sobrien    /* The relocation field has been deleted.  */
4790218822Sdim    return TRUE;
4791218822Sdim
4792218822Sdim  if (outrel[0].r_offset == MINUS_TWO)
4793179404Sobrien    {
4794179404Sobrien      /* The relocation field has been converted into a relative value of
4795179404Sobrien	 some sort.  Functions like _bfd_elf_write_section_eh_frame expect
4796179404Sobrien	 the field to be fully relocated, so add in the symbol's value.  */
4797179404Sobrien      *addendp += symbol;
4798218822Sdim      return TRUE;
4799179404Sobrien    }
4800179404Sobrien
4801218822Sdim  /* We must now calculate the dynamic symbol table index to use
4802218822Sdim     in the relocation.  */
4803218822Sdim  if (h != NULL
4804218822Sdim      && (!h->root.def_regular
4805218822Sdim	  || (info->shared && !info->symbolic && !h->root.forced_local)))
4806218822Sdim    {
4807218822Sdim      indx = h->root.dynindx;
4808218822Sdim      if (SGI_COMPAT (output_bfd))
4809218822Sdim	defined_p = h->root.def_regular;
4810218822Sdim      else
4811218822Sdim	/* ??? glibc's ld.so just adds the final GOT entry to the
4812218822Sdim	   relocation field.  It therefore treats relocs against
4813218822Sdim	   defined symbols in the same way as relocs against
4814218822Sdim	   undefined symbols.  */
4815218822Sdim	defined_p = FALSE;
4816218822Sdim    }
4817179404Sobrien  else
4818179404Sobrien    {
4819218822Sdim      if (sec != NULL && bfd_is_abs_section (sec))
4820218822Sdim	indx = 0;
4821218822Sdim      else if (sec == NULL || sec->owner == NULL)
4822179404Sobrien	{
4823218822Sdim	  bfd_set_error (bfd_error_bad_value);
4824218822Sdim	  return FALSE;
4825179404Sobrien	}
4826179404Sobrien      else
4827179404Sobrien	{
4828218822Sdim	  indx = elf_section_data (sec->output_section)->dynindx;
4829218822Sdim	  if (indx == 0)
4830179404Sobrien	    {
4831218822Sdim	      asection *osec = htab->root.text_index_section;
4832218822Sdim	      indx = elf_section_data (osec)->dynindx;
4833179404Sobrien	    }
4834218822Sdim	  if (indx == 0)
4835218822Sdim	    abort ();
4836179404Sobrien	}
4837179404Sobrien
4838218822Sdim      /* Instead of generating a relocation using the section
4839218822Sdim	 symbol, we may as well make it a fully relative
4840218822Sdim	 relocation.  We want to avoid generating relocations to
4841218822Sdim	 local symbols because we used to generate them
4842218822Sdim	 incorrectly, without adding the original symbol value,
4843218822Sdim	 which is mandated by the ABI for section symbols.  In
4844218822Sdim	 order to give dynamic loaders and applications time to
4845218822Sdim	 phase out the incorrect use, we refrain from emitting
4846218822Sdim	 section-relative relocations.  It's not like they're
4847218822Sdim	 useful, after all.  This should be a bit more efficient
4848218822Sdim	 as well.  */
4849218822Sdim      /* ??? Although this behavior is compatible with glibc's ld.so,
4850218822Sdim	 the ABI says that relocations against STN_UNDEF should have
4851218822Sdim	 a symbol value of 0.  Irix rld honors this, so relocations
4852218822Sdim	 against STN_UNDEF have no effect.  */
4853218822Sdim      if (!SGI_COMPAT (output_bfd))
4854218822Sdim	indx = 0;
4855218822Sdim      defined_p = TRUE;
4856218822Sdim    }
4857179404Sobrien
4858218822Sdim  /* If the relocation was previously an absolute relocation and
4859218822Sdim     this symbol will not be referred to by the relocation, we must
4860218822Sdim     adjust it by the value we give it in the dynamic symbol table.
4861218822Sdim     Otherwise leave the job up to the dynamic linker.  */
4862218822Sdim  if (defined_p && r_type != R_MIPS_REL32)
4863218822Sdim    *addendp += symbol;
4864179404Sobrien
4865218822Sdim  if (htab->is_vxworks)
4866218822Sdim    /* VxWorks uses non-relative relocations for this.  */
4867218822Sdim    outrel[0].r_info = ELF32_R_INFO (indx, R_MIPS_32);
4868218822Sdim  else
4869218822Sdim    /* The relocation is always an REL32 relocation because we don't
4870218822Sdim       know where the shared library will wind up at load-time.  */
4871218822Sdim    outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
4872218822Sdim				   R_MIPS_REL32);
4873179404Sobrien
4874218822Sdim  /* For strict adherence to the ABI specification, we should
4875218822Sdim     generate a R_MIPS_64 relocation record by itself before the
4876218822Sdim     _REL32/_64 record as well, such that the addend is read in as
4877218822Sdim     a 64-bit value (REL32 is a 32-bit relocation, after all).
4878218822Sdim     However, since none of the existing ELF64 MIPS dynamic
4879218822Sdim     loaders seems to care, we don't waste space with these
4880218822Sdim     artificial relocations.  If this turns out to not be true,
4881218822Sdim     mips_elf_allocate_dynamic_relocation() should be tweaked so
4882218822Sdim     as to make room for a pair of dynamic relocations per
4883218822Sdim     invocation if ABI_64_P, and here we should generate an
4884218822Sdim     additional relocation record with R_MIPS_64 by itself for a
4885218822Sdim     NULL symbol before this relocation record.  */
4886218822Sdim  outrel[1].r_info = ELF_R_INFO (output_bfd, 0,
4887218822Sdim				 ABI_64_P (output_bfd)
4888218822Sdim				 ? R_MIPS_64
4889218822Sdim				 : R_MIPS_NONE);
4890218822Sdim  outrel[2].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_NONE);
4891218822Sdim
4892218822Sdim  /* Adjust the output offset of the relocation to reference the
4893218822Sdim     correct location in the output file.  */
4894218822Sdim  outrel[0].r_offset += (input_section->output_section->vma
4895218822Sdim			 + input_section->output_offset);
4896218822Sdim  outrel[1].r_offset += (input_section->output_section->vma
4897218822Sdim			 + input_section->output_offset);
4898218822Sdim  outrel[2].r_offset += (input_section->output_section->vma
4899218822Sdim			 + input_section->output_offset);
4900218822Sdim
4901179404Sobrien  /* Put the relocation back out.  We have to use the special
4902179404Sobrien     relocation outputter in the 64-bit case since the 64-bit
4903179404Sobrien     relocation format is non-standard.  */
4904179404Sobrien  if (ABI_64_P (output_bfd))
4905179404Sobrien    {
4906179404Sobrien      (*get_elf_backend_data (output_bfd)->s->swap_reloc_out)
4907179404Sobrien	(output_bfd, &outrel[0],
4908179404Sobrien	 (sreloc->contents
4909179404Sobrien	  + sreloc->reloc_count * sizeof (Elf64_Mips_External_Rel)));
4910179404Sobrien    }
4911218822Sdim  else if (htab->is_vxworks)
4912218822Sdim    {
4913218822Sdim      /* VxWorks uses RELA rather than REL dynamic relocations.  */
4914218822Sdim      outrel[0].r_addend = *addendp;
4915218822Sdim      bfd_elf32_swap_reloca_out
4916218822Sdim	(output_bfd, &outrel[0],
4917218822Sdim	 (sreloc->contents
4918218822Sdim	  + sreloc->reloc_count * sizeof (Elf32_External_Rela)));
4919218822Sdim    }
4920179404Sobrien  else
4921179404Sobrien    bfd_elf32_swap_reloc_out
4922179404Sobrien      (output_bfd, &outrel[0],
4923179404Sobrien       (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
4924179404Sobrien
4925179404Sobrien  /* We've now added another relocation.  */
4926179404Sobrien  ++sreloc->reloc_count;
4927179404Sobrien
4928179404Sobrien  /* Make sure the output section is writable.  The dynamic linker
4929179404Sobrien     will be writing to it.  */
4930179404Sobrien  elf_section_data (input_section->output_section)->this_hdr.sh_flags
4931179404Sobrien    |= SHF_WRITE;
4932179404Sobrien
4933179404Sobrien  /* On IRIX5, make an entry of compact relocation info.  */
4934218822Sdim  if (IRIX_COMPAT (output_bfd) == ict_irix5)
4935179404Sobrien    {
4936179404Sobrien      asection *scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
4937179404Sobrien      bfd_byte *cr;
4938179404Sobrien
4939179404Sobrien      if (scpt)
4940179404Sobrien	{
4941179404Sobrien	  Elf32_crinfo cptrel;
4942179404Sobrien
4943179404Sobrien	  mips_elf_set_cr_format (cptrel, CRF_MIPS_LONG);
4944179404Sobrien	  cptrel.vaddr = (rel->r_offset
4945179404Sobrien			  + input_section->output_section->vma
4946179404Sobrien			  + input_section->output_offset);
4947179404Sobrien	  if (r_type == R_MIPS_REL32)
4948179404Sobrien	    mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32);
4949179404Sobrien	  else
4950179404Sobrien	    mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
4951179404Sobrien	  mips_elf_set_cr_dist2to (cptrel, 0);
4952179404Sobrien	  cptrel.konst = *addendp;
4953179404Sobrien
4954179404Sobrien	  cr = (scpt->contents
4955179404Sobrien		+ sizeof (Elf32_External_compact_rel));
4956218822Sdim	  mips_elf_set_cr_relvaddr (cptrel, 0);
4957179404Sobrien	  bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
4958179404Sobrien				     ((Elf32_External_crinfo *) cr
4959179404Sobrien				      + scpt->reloc_count));
4960179404Sobrien	  ++scpt->reloc_count;
4961179404Sobrien	}
4962179404Sobrien    }
4963179404Sobrien
4964218822Sdim  /* If we've written this relocation for a readonly section,
4965218822Sdim     we need to set DF_TEXTREL again, so that we do not delete the
4966218822Sdim     DT_TEXTREL tag.  */
4967218822Sdim  if (MIPS_ELF_READONLY_SECTION (input_section))
4968218822Sdim    info->flags |= DF_TEXTREL;
4969218822Sdim
4970179404Sobrien  return TRUE;
4971179404Sobrien}
4972179404Sobrien
4973179404Sobrien/* Return the MACH for a MIPS e_flags value.  */
4974179404Sobrien
4975179404Sobrienunsigned long
4976179404Sobrien_bfd_elf_mips_mach (flagword flags)
4977179404Sobrien{
4978179404Sobrien  switch (flags & EF_MIPS_MACH)
4979179404Sobrien    {
4980179404Sobrien    case E_MIPS_MACH_3900:
4981179404Sobrien      return bfd_mach_mips3900;
4982179404Sobrien
4983179404Sobrien    case E_MIPS_MACH_4010:
4984179404Sobrien      return bfd_mach_mips4010;
4985179404Sobrien
4986179404Sobrien    case E_MIPS_MACH_4100:
4987179404Sobrien      return bfd_mach_mips4100;
4988179404Sobrien
4989179404Sobrien    case E_MIPS_MACH_4111:
4990179404Sobrien      return bfd_mach_mips4111;
4991179404Sobrien
4992179404Sobrien    case E_MIPS_MACH_4120:
4993179404Sobrien      return bfd_mach_mips4120;
4994179404Sobrien
4995179404Sobrien    case E_MIPS_MACH_4650:
4996179404Sobrien      return bfd_mach_mips4650;
4997179404Sobrien
4998179404Sobrien    case E_MIPS_MACH_5400:
4999179404Sobrien      return bfd_mach_mips5400;
5000179404Sobrien
5001179404Sobrien    case E_MIPS_MACH_5500:
5002179404Sobrien      return bfd_mach_mips5500;
5003179404Sobrien
5004208737Sjmallett    case E_MIPS_MACH_9000:
5005208737Sjmallett      return bfd_mach_mips9000;
5006208737Sjmallett
5007208737Sjmallett    case E_MIPS_MACH_OCTEON:
5008208737Sjmallett      return bfd_mach_mips_octeon;
5009208737Sjmallett
5010179404Sobrien    case E_MIPS_MACH_SB1:
5011179404Sobrien      return bfd_mach_mips_sb1;
5012179404Sobrien
5013179404Sobrien    default:
5014179404Sobrien      switch (flags & EF_MIPS_ARCH)
5015179404Sobrien	{
5016179404Sobrien	default:
5017179404Sobrien	case E_MIPS_ARCH_1:
5018179404Sobrien	  return bfd_mach_mips3000;
5019179404Sobrien
5020179404Sobrien	case E_MIPS_ARCH_2:
5021179404Sobrien	  return bfd_mach_mips6000;
5022179404Sobrien
5023179404Sobrien	case E_MIPS_ARCH_3:
5024179404Sobrien	  return bfd_mach_mips4000;
5025179404Sobrien
5026179404Sobrien	case E_MIPS_ARCH_4:
5027179404Sobrien	  return bfd_mach_mips8000;
5028179404Sobrien
5029179404Sobrien	case E_MIPS_ARCH_5:
5030179404Sobrien	  return bfd_mach_mips5;
5031179404Sobrien
5032179404Sobrien	case E_MIPS_ARCH_32:
5033179404Sobrien	  return bfd_mach_mipsisa32;
5034179404Sobrien
5035179404Sobrien	case E_MIPS_ARCH_64:
5036179404Sobrien	  return bfd_mach_mipsisa64;
5037179404Sobrien
5038179404Sobrien	case E_MIPS_ARCH_32R2:
5039179404Sobrien	  return bfd_mach_mipsisa32r2;
5040179404Sobrien
5041179404Sobrien	case E_MIPS_ARCH_64R2:
5042179404Sobrien	  return bfd_mach_mipsisa64r2;
5043179404Sobrien	}
5044179404Sobrien    }
5045179404Sobrien
5046179404Sobrien  return 0;
5047179404Sobrien}
5048179404Sobrien
5049179404Sobrien/* Return printable name for ABI.  */
5050179404Sobrien
5051179404Sobrienstatic INLINE char *
5052179404Sobrienelf_mips_abi_name (bfd *abfd)
5053179404Sobrien{
5054179404Sobrien  flagword flags;
5055179404Sobrien
5056179404Sobrien  flags = elf_elfheader (abfd)->e_flags;
5057179404Sobrien  switch (flags & EF_MIPS_ABI)
5058179404Sobrien    {
5059179404Sobrien    case 0:
5060179404Sobrien      if (ABI_N32_P (abfd))
5061179404Sobrien	return "N32";
5062179404Sobrien      else if (ABI_64_P (abfd))
5063179404Sobrien	return "64";
5064179404Sobrien      else
5065179404Sobrien	return "none";
5066179404Sobrien    case E_MIPS_ABI_O32:
5067179404Sobrien      return "O32";
5068179404Sobrien    case E_MIPS_ABI_O64:
5069179404Sobrien      return "O64";
5070179404Sobrien    case E_MIPS_ABI_EABI32:
5071179404Sobrien      return "EABI32";
5072179404Sobrien    case E_MIPS_ABI_EABI64:
5073179404Sobrien      return "EABI64";
5074179404Sobrien    default:
5075179404Sobrien      return "unknown abi";
5076179404Sobrien    }
5077179404Sobrien}
5078179404Sobrien
5079179404Sobrien/* MIPS ELF uses two common sections.  One is the usual one, and the
5080179404Sobrien   other is for small objects.  All the small objects are kept
5081179404Sobrien   together, and then referenced via the gp pointer, which yields
5082179404Sobrien   faster assembler code.  This is what we use for the small common
5083179404Sobrien   section.  This approach is copied from ecoff.c.  */
5084179404Sobrienstatic asection mips_elf_scom_section;
5085179404Sobrienstatic asymbol mips_elf_scom_symbol;
5086179404Sobrienstatic asymbol *mips_elf_scom_symbol_ptr;
5087179404Sobrien
5088179404Sobrien/* MIPS ELF also uses an acommon section, which represents an
5089179404Sobrien   allocated common symbol which may be overridden by a
5090179404Sobrien   definition in a shared library.  */
5091179404Sobrienstatic asection mips_elf_acom_section;
5092179404Sobrienstatic asymbol mips_elf_acom_symbol;
5093179404Sobrienstatic asymbol *mips_elf_acom_symbol_ptr;
5094179404Sobrien
5095179404Sobrien/* Handle the special MIPS section numbers that a symbol may use.
5096179404Sobrien   This is used for both the 32-bit and the 64-bit ABI.  */
5097179404Sobrien
5098179404Sobrienvoid
5099179404Sobrien_bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym)
5100179404Sobrien{
5101179404Sobrien  elf_symbol_type *elfsym;
5102179404Sobrien
5103179404Sobrien  elfsym = (elf_symbol_type *) asym;
5104179404Sobrien  switch (elfsym->internal_elf_sym.st_shndx)
5105179404Sobrien    {
5106179404Sobrien    case SHN_MIPS_ACOMMON:
5107179404Sobrien      /* This section is used in a dynamically linked executable file.
5108179404Sobrien	 It is an allocated common section.  The dynamic linker can
5109179404Sobrien	 either resolve these symbols to something in a shared
5110179404Sobrien	 library, or it can just leave them here.  For our purposes,
5111179404Sobrien	 we can consider these symbols to be in a new section.  */
5112179404Sobrien      if (mips_elf_acom_section.name == NULL)
5113179404Sobrien	{
5114179404Sobrien	  /* Initialize the acommon section.  */
5115179404Sobrien	  mips_elf_acom_section.name = ".acommon";
5116179404Sobrien	  mips_elf_acom_section.flags = SEC_ALLOC;
5117179404Sobrien	  mips_elf_acom_section.output_section = &mips_elf_acom_section;
5118179404Sobrien	  mips_elf_acom_section.symbol = &mips_elf_acom_symbol;
5119179404Sobrien	  mips_elf_acom_section.symbol_ptr_ptr = &mips_elf_acom_symbol_ptr;
5120179404Sobrien	  mips_elf_acom_symbol.name = ".acommon";
5121179404Sobrien	  mips_elf_acom_symbol.flags = BSF_SECTION_SYM;
5122179404Sobrien	  mips_elf_acom_symbol.section = &mips_elf_acom_section;
5123179404Sobrien	  mips_elf_acom_symbol_ptr = &mips_elf_acom_symbol;
5124179404Sobrien	}
5125179404Sobrien      asym->section = &mips_elf_acom_section;
5126179404Sobrien      break;
5127179404Sobrien
5128179404Sobrien    case SHN_COMMON:
5129179404Sobrien      /* Common symbols less than the GP size are automatically
5130179404Sobrien	 treated as SHN_MIPS_SCOMMON symbols on IRIX5.  */
5131179404Sobrien      if (asym->value > elf_gp_size (abfd)
5132218822Sdim	  || ELF_ST_TYPE (elfsym->internal_elf_sym.st_info) == STT_TLS
5133179404Sobrien	  || IRIX_COMPAT (abfd) == ict_irix6)
5134179404Sobrien	break;
5135179404Sobrien      /* Fall through.  */
5136179404Sobrien    case SHN_MIPS_SCOMMON:
5137179404Sobrien      if (mips_elf_scom_section.name == NULL)
5138179404Sobrien	{
5139179404Sobrien	  /* Initialize the small common section.  */
5140179404Sobrien	  mips_elf_scom_section.name = ".scommon";
5141179404Sobrien	  mips_elf_scom_section.flags = SEC_IS_COMMON;
5142179404Sobrien	  mips_elf_scom_section.output_section = &mips_elf_scom_section;
5143179404Sobrien	  mips_elf_scom_section.symbol = &mips_elf_scom_symbol;
5144179404Sobrien	  mips_elf_scom_section.symbol_ptr_ptr = &mips_elf_scom_symbol_ptr;
5145179404Sobrien	  mips_elf_scom_symbol.name = ".scommon";
5146179404Sobrien	  mips_elf_scom_symbol.flags = BSF_SECTION_SYM;
5147179404Sobrien	  mips_elf_scom_symbol.section = &mips_elf_scom_section;
5148179404Sobrien	  mips_elf_scom_symbol_ptr = &mips_elf_scom_symbol;
5149179404Sobrien	}
5150179404Sobrien      asym->section = &mips_elf_scom_section;
5151179404Sobrien      asym->value = elfsym->internal_elf_sym.st_size;
5152179404Sobrien      break;
5153179404Sobrien
5154179404Sobrien    case SHN_MIPS_SUNDEFINED:
5155179404Sobrien      asym->section = bfd_und_section_ptr;
5156179404Sobrien      break;
5157179404Sobrien
5158179404Sobrien    case SHN_MIPS_TEXT:
5159218822Sdim      {
5160218822Sdim	asection *section = bfd_get_section_by_name (abfd, ".text");
5161218822Sdim
5162218822Sdim	BFD_ASSERT (SGI_COMPAT (abfd));
5163218822Sdim	if (section != NULL)
5164218822Sdim	  {
5165218822Sdim	    asym->section = section;
5166218822Sdim	    /* MIPS_TEXT is a bit special, the address is not an offset
5167218822Sdim	       to the base of the .text section.  So substract the section
5168218822Sdim	       base address to make it an offset.  */
5169218822Sdim	    asym->value -= section->vma;
5170218822Sdim	  }
5171218822Sdim      }
5172179404Sobrien      break;
5173179404Sobrien
5174179404Sobrien    case SHN_MIPS_DATA:
5175218822Sdim      {
5176218822Sdim	asection *section = bfd_get_section_by_name (abfd, ".data");
5177218822Sdim
5178218822Sdim	BFD_ASSERT (SGI_COMPAT (abfd));
5179218822Sdim	if (section != NULL)
5180218822Sdim	  {
5181218822Sdim	    asym->section = section;
5182218822Sdim	    /* MIPS_DATA is a bit special, the address is not an offset
5183218822Sdim	       to the base of the .data section.  So substract the section
5184218822Sdim	       base address to make it an offset.  */
5185218822Sdim	    asym->value -= section->vma;
5186218822Sdim	  }
5187218822Sdim      }
5188179404Sobrien      break;
5189179404Sobrien    }
5190179404Sobrien}
5191179404Sobrien
5192218822Sdim/* Implement elf_backend_eh_frame_address_size.  This differs from
5193218822Sdim   the default in the way it handles EABI64.
5194218822Sdim
5195218822Sdim   EABI64 was originally specified as an LP64 ABI, and that is what
5196218822Sdim   -mabi=eabi normally gives on a 64-bit target.  However, gcc has
5197218822Sdim   historically accepted the combination of -mabi=eabi and -mlong32,
5198218822Sdim   and this ILP32 variation has become semi-official over time.
5199218822Sdim   Both forms use elf32 and have pointer-sized FDE addresses.
5200218822Sdim
5201218822Sdim   If an EABI object was generated by GCC 4.0 or above, it will have
5202218822Sdim   an empty .gcc_compiled_longXX section, where XX is the size of longs
5203218822Sdim   in bits.  Unfortunately, ILP32 objects generated by earlier compilers
5204218822Sdim   have no special marking to distinguish them from LP64 objects.
5205218822Sdim
5206218822Sdim   We don't want users of the official LP64 ABI to be punished for the
5207218822Sdim   existence of the ILP32 variant, but at the same time, we don't want
5208218822Sdim   to mistakenly interpret pre-4.0 ILP32 objects as being LP64 objects.
5209218822Sdim   We therefore take the following approach:
5210218822Sdim
5211218822Sdim      - If ABFD contains a .gcc_compiled_longXX section, use it to
5212218822Sdim        determine the pointer size.
5213218822Sdim
5214218822Sdim      - Otherwise check the type of the first relocation.  Assume that
5215218822Sdim        the LP64 ABI is being used if the relocation is of type R_MIPS_64.
5216218822Sdim
5217218822Sdim      - Otherwise punt.
5218218822Sdim
5219218822Sdim   The second check is enough to detect LP64 objects generated by pre-4.0
5220218822Sdim   compilers because, in the kind of output generated by those compilers,
5221218822Sdim   the first relocation will be associated with either a CIE personality
5222218822Sdim   routine or an FDE start address.  Furthermore, the compilers never
5223218822Sdim   used a special (non-pointer) encoding for this ABI.
5224218822Sdim
5225218822Sdim   Checking the relocation type should also be safe because there is no
5226218822Sdim   reason to use R_MIPS_64 in an ILP32 object.  Pre-4.0 compilers never
5227218822Sdim   did so.  */
5228218822Sdim
5229218822Sdimunsigned int
5230218822Sdim_bfd_mips_elf_eh_frame_address_size (bfd *abfd, asection *sec)
5231218822Sdim{
5232218822Sdim  if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
5233218822Sdim    return 8;
5234218822Sdim  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
5235218822Sdim    {
5236218822Sdim      bfd_boolean long32_p, long64_p;
5237218822Sdim
5238218822Sdim      long32_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long32") != 0;
5239218822Sdim      long64_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long64") != 0;
5240218822Sdim      if (long32_p && long64_p)
5241218822Sdim	return 0;
5242218822Sdim      if (long32_p)
5243218822Sdim	return 4;
5244218822Sdim      if (long64_p)
5245218822Sdim	return 8;
5246218822Sdim
5247218822Sdim      if (sec->reloc_count > 0
5248218822Sdim	  && elf_section_data (sec)->relocs != NULL
5249218822Sdim	  && (ELF32_R_TYPE (elf_section_data (sec)->relocs[0].r_info)
5250218822Sdim	      == R_MIPS_64))
5251218822Sdim	return 8;
5252218822Sdim
5253218822Sdim      return 0;
5254218822Sdim    }
5255218822Sdim  return 4;
5256218822Sdim}
5257218822Sdim
5258179404Sobrien/* There appears to be a bug in the MIPSpro linker that causes GOT_DISP
5259179404Sobrien   relocations against two unnamed section symbols to resolve to the
5260179404Sobrien   same address.  For example, if we have code like:
5261179404Sobrien
5262179404Sobrien	lw	$4,%got_disp(.data)($gp)
5263179404Sobrien	lw	$25,%got_disp(.text)($gp)
5264179404Sobrien	jalr	$25
5265179404Sobrien
5266179404Sobrien   then the linker will resolve both relocations to .data and the program
5267179404Sobrien   will jump there rather than to .text.
5268179404Sobrien
5269179404Sobrien   We can work around this problem by giving names to local section symbols.
5270179404Sobrien   This is also what the MIPSpro tools do.  */
5271179404Sobrien
5272179404Sobrienbfd_boolean
5273179404Sobrien_bfd_mips_elf_name_local_section_symbols (bfd *abfd)
5274179404Sobrien{
5275179404Sobrien  return SGI_COMPAT (abfd);
5276179404Sobrien}
5277179404Sobrien
5278179404Sobrien/* Work over a section just before writing it out.  This routine is
5279179404Sobrien   used by both the 32-bit and the 64-bit ABI.  FIXME: We recognize
5280179404Sobrien   sections that need the SHF_MIPS_GPREL flag by name; there has to be
5281179404Sobrien   a better way.  */
5282179404Sobrien
5283179404Sobrienbfd_boolean
5284179404Sobrien_bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
5285179404Sobrien{
5286179404Sobrien  if (hdr->sh_type == SHT_MIPS_REGINFO
5287179404Sobrien      && hdr->sh_size > 0)
5288179404Sobrien    {
5289179404Sobrien      bfd_byte buf[4];
5290179404Sobrien
5291179404Sobrien      BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo));
5292179404Sobrien      BFD_ASSERT (hdr->contents == NULL);
5293179404Sobrien
5294179404Sobrien      if (bfd_seek (abfd,
5295179404Sobrien		    hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4,
5296179404Sobrien		    SEEK_SET) != 0)
5297179404Sobrien	return FALSE;
5298179404Sobrien      H_PUT_32 (abfd, elf_gp (abfd), buf);
5299179404Sobrien      if (bfd_bwrite (buf, 4, abfd) != 4)
5300179404Sobrien	return FALSE;
5301179404Sobrien    }
5302179404Sobrien
5303179404Sobrien  if (hdr->sh_type == SHT_MIPS_OPTIONS
5304179404Sobrien      && hdr->bfd_section != NULL
5305179404Sobrien      && mips_elf_section_data (hdr->bfd_section) != NULL
5306179404Sobrien      && mips_elf_section_data (hdr->bfd_section)->u.tdata != NULL)
5307179404Sobrien    {
5308179404Sobrien      bfd_byte *contents, *l, *lend;
5309179404Sobrien
5310179404Sobrien      /* We stored the section contents in the tdata field in the
5311179404Sobrien	 set_section_contents routine.  We save the section contents
5312179404Sobrien	 so that we don't have to read them again.
5313179404Sobrien	 At this point we know that elf_gp is set, so we can look
5314179404Sobrien	 through the section contents to see if there is an
5315179404Sobrien	 ODK_REGINFO structure.  */
5316179404Sobrien
5317179404Sobrien      contents = mips_elf_section_data (hdr->bfd_section)->u.tdata;
5318179404Sobrien      l = contents;
5319179404Sobrien      lend = contents + hdr->sh_size;
5320179404Sobrien      while (l + sizeof (Elf_External_Options) <= lend)
5321179404Sobrien	{
5322179404Sobrien	  Elf_Internal_Options intopt;
5323179404Sobrien
5324179404Sobrien	  bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
5325179404Sobrien					&intopt);
5326214950Sgonzo	  if (intopt.size < sizeof (Elf_External_Options))
5327214950Sgonzo	    {
5328214950Sgonzo	      (*_bfd_error_handler)
5329218822Sdim		(_("%B: Warning: bad `%s' option size %u smaller than its header"),
5330218822Sdim		abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
5331214950Sgonzo	      break;
5332214950Sgonzo	    }
5333179404Sobrien	  if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
5334179404Sobrien	    {
5335179404Sobrien	      bfd_byte buf[8];
5336179404Sobrien
5337179404Sobrien	      if (bfd_seek (abfd,
5338179404Sobrien			    (hdr->sh_offset
5339179404Sobrien			     + (l - contents)
5340179404Sobrien			     + sizeof (Elf_External_Options)
5341179404Sobrien			     + (sizeof (Elf64_External_RegInfo) - 8)),
5342179404Sobrien			     SEEK_SET) != 0)
5343179404Sobrien		return FALSE;
5344179404Sobrien	      H_PUT_64 (abfd, elf_gp (abfd), buf);
5345179404Sobrien	      if (bfd_bwrite (buf, 8, abfd) != 8)
5346179404Sobrien		return FALSE;
5347179404Sobrien	    }
5348179404Sobrien	  else if (intopt.kind == ODK_REGINFO)
5349179404Sobrien	    {
5350179404Sobrien	      bfd_byte buf[4];
5351179404Sobrien
5352179404Sobrien	      if (bfd_seek (abfd,
5353179404Sobrien			    (hdr->sh_offset
5354179404Sobrien			     + (l - contents)
5355179404Sobrien			     + sizeof (Elf_External_Options)
5356179404Sobrien			     + (sizeof (Elf32_External_RegInfo) - 4)),
5357179404Sobrien			    SEEK_SET) != 0)
5358179404Sobrien		return FALSE;
5359179404Sobrien	      H_PUT_32 (abfd, elf_gp (abfd), buf);
5360179404Sobrien	      if (bfd_bwrite (buf, 4, abfd) != 4)
5361179404Sobrien		return FALSE;
5362179404Sobrien	    }
5363179404Sobrien	  l += intopt.size;
5364179404Sobrien	}
5365179404Sobrien    }
5366179404Sobrien
5367179404Sobrien  if (hdr->bfd_section != NULL)
5368179404Sobrien    {
5369179404Sobrien      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
5370179404Sobrien
5371179404Sobrien      if (strcmp (name, ".sdata") == 0
5372179404Sobrien	  || strcmp (name, ".lit8") == 0
5373179404Sobrien	  || strcmp (name, ".lit4") == 0)
5374179404Sobrien	{
5375179404Sobrien	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
5376179404Sobrien	  hdr->sh_type = SHT_PROGBITS;
5377179404Sobrien	}
5378179404Sobrien      else if (strcmp (name, ".sbss") == 0)
5379179404Sobrien	{
5380179404Sobrien	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
5381179404Sobrien	  hdr->sh_type = SHT_NOBITS;
5382179404Sobrien	}
5383179404Sobrien      else if (strcmp (name, ".srdata") == 0)
5384179404Sobrien	{
5385179404Sobrien	  hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
5386179404Sobrien	  hdr->sh_type = SHT_PROGBITS;
5387179404Sobrien	}
5388179404Sobrien      else if (strcmp (name, ".compact_rel") == 0)
5389179404Sobrien	{
5390179404Sobrien	  hdr->sh_flags = 0;
5391179404Sobrien	  hdr->sh_type = SHT_PROGBITS;
5392179404Sobrien	}
5393179404Sobrien      else if (strcmp (name, ".rtproc") == 0)
5394179404Sobrien	{
5395179404Sobrien	  if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
5396179404Sobrien	    {
5397179404Sobrien	      unsigned int adjust;
5398179404Sobrien
5399179404Sobrien	      adjust = hdr->sh_size % hdr->sh_addralign;
5400179404Sobrien	      if (adjust != 0)
5401179404Sobrien		hdr->sh_size += hdr->sh_addralign - adjust;
5402179404Sobrien	    }
5403179404Sobrien	}
5404179404Sobrien    }
5405179404Sobrien
5406179404Sobrien  return TRUE;
5407179404Sobrien}
5408179404Sobrien
5409179404Sobrien/* Handle a MIPS specific section when reading an object file.  This
5410179404Sobrien   is called when elfcode.h finds a section with an unknown type.
5411179404Sobrien   This routine supports both the 32-bit and 64-bit ELF ABI.
5412179404Sobrien
5413179404Sobrien   FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure
5414179404Sobrien   how to.  */
5415179404Sobrien
5416179404Sobrienbfd_boolean
5417218822Sdim_bfd_mips_elf_section_from_shdr (bfd *abfd,
5418218822Sdim				 Elf_Internal_Shdr *hdr,
5419218822Sdim				 const char *name,
5420218822Sdim				 int shindex)
5421179404Sobrien{
5422179404Sobrien  flagword flags = 0;
5423179404Sobrien
5424179404Sobrien  /* There ought to be a place to keep ELF backend specific flags, but
5425179404Sobrien     at the moment there isn't one.  We just keep track of the
5426179404Sobrien     sections by their name, instead.  Fortunately, the ABI gives
5427179404Sobrien     suggested names for all the MIPS specific sections, so we will
5428179404Sobrien     probably get away with this.  */
5429179404Sobrien  switch (hdr->sh_type)
5430179404Sobrien    {
5431179404Sobrien    case SHT_MIPS_LIBLIST:
5432179404Sobrien      if (strcmp (name, ".liblist") != 0)
5433179404Sobrien	return FALSE;
5434179404Sobrien      break;
5435179404Sobrien    case SHT_MIPS_MSYM:
5436179404Sobrien      if (strcmp (name, ".msym") != 0)
5437179404Sobrien	return FALSE;
5438179404Sobrien      break;
5439179404Sobrien    case SHT_MIPS_CONFLICT:
5440179404Sobrien      if (strcmp (name, ".conflict") != 0)
5441179404Sobrien	return FALSE;
5442179404Sobrien      break;
5443179404Sobrien    case SHT_MIPS_GPTAB:
5444218822Sdim      if (! CONST_STRNEQ (name, ".gptab."))
5445179404Sobrien	return FALSE;
5446179404Sobrien      break;
5447179404Sobrien    case SHT_MIPS_UCODE:
5448179404Sobrien      if (strcmp (name, ".ucode") != 0)
5449179404Sobrien	return FALSE;
5450179404Sobrien      break;
5451179404Sobrien    case SHT_MIPS_DEBUG:
5452179404Sobrien      if (strcmp (name, ".mdebug") != 0)
5453179404Sobrien	return FALSE;
5454179404Sobrien      flags = SEC_DEBUGGING;
5455179404Sobrien      break;
5456179404Sobrien    case SHT_MIPS_REGINFO:
5457179404Sobrien      if (strcmp (name, ".reginfo") != 0
5458179404Sobrien	  || hdr->sh_size != sizeof (Elf32_External_RegInfo))
5459179404Sobrien	return FALSE;
5460179404Sobrien      flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
5461179404Sobrien      break;
5462179404Sobrien    case SHT_MIPS_IFACE:
5463179404Sobrien      if (strcmp (name, ".MIPS.interfaces") != 0)
5464179404Sobrien	return FALSE;
5465179404Sobrien      break;
5466179404Sobrien    case SHT_MIPS_CONTENT:
5467218822Sdim      if (! CONST_STRNEQ (name, ".MIPS.content"))
5468179404Sobrien	return FALSE;
5469179404Sobrien      break;
5470179404Sobrien    case SHT_MIPS_OPTIONS:
5471218822Sdim      if (!MIPS_ELF_OPTIONS_SECTION_NAME_P (name))
5472179404Sobrien	return FALSE;
5473179404Sobrien      break;
5474179404Sobrien    case SHT_MIPS_DWARF:
5475218822Sdim      if (! CONST_STRNEQ (name, ".debug_"))
5476179404Sobrien	return FALSE;
5477179404Sobrien      break;
5478179404Sobrien    case SHT_MIPS_SYMBOL_LIB:
5479179404Sobrien      if (strcmp (name, ".MIPS.symlib") != 0)
5480179404Sobrien	return FALSE;
5481179404Sobrien      break;
5482179404Sobrien    case SHT_MIPS_EVENTS:
5483218822Sdim      if (! CONST_STRNEQ (name, ".MIPS.events")
5484218822Sdim	  && ! CONST_STRNEQ (name, ".MIPS.post_rel"))
5485179404Sobrien	return FALSE;
5486179404Sobrien      break;
5487179404Sobrien    default:
5488218822Sdim      break;
5489179404Sobrien    }
5490179404Sobrien
5491218822Sdim  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
5492179404Sobrien    return FALSE;
5493179404Sobrien
5494179404Sobrien  if (flags)
5495179404Sobrien    {
5496179404Sobrien      if (! bfd_set_section_flags (abfd, hdr->bfd_section,
5497179404Sobrien				   (bfd_get_section_flags (abfd,
5498179404Sobrien							   hdr->bfd_section)
5499179404Sobrien				    | flags)))
5500179404Sobrien	return FALSE;
5501179404Sobrien    }
5502179404Sobrien
5503179404Sobrien  /* FIXME: We should record sh_info for a .gptab section.  */
5504179404Sobrien
5505179404Sobrien  /* For a .reginfo section, set the gp value in the tdata information
5506179404Sobrien     from the contents of this section.  We need the gp value while
5507179404Sobrien     processing relocs, so we just get it now.  The .reginfo section
5508179404Sobrien     is not used in the 64-bit MIPS ELF ABI.  */
5509179404Sobrien  if (hdr->sh_type == SHT_MIPS_REGINFO)
5510179404Sobrien    {
5511179404Sobrien      Elf32_External_RegInfo ext;
5512179404Sobrien      Elf32_RegInfo s;
5513179404Sobrien
5514179404Sobrien      if (! bfd_get_section_contents (abfd, hdr->bfd_section,
5515179404Sobrien				      &ext, 0, sizeof ext))
5516179404Sobrien	return FALSE;
5517179404Sobrien      bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
5518179404Sobrien      elf_gp (abfd) = s.ri_gp_value;
5519179404Sobrien    }
5520179404Sobrien
5521179404Sobrien  /* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
5522179404Sobrien     set the gp value based on what we find.  We may see both
5523179404Sobrien     SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
5524179404Sobrien     they should agree.  */
5525179404Sobrien  if (hdr->sh_type == SHT_MIPS_OPTIONS)
5526179404Sobrien    {
5527179404Sobrien      bfd_byte *contents, *l, *lend;
5528179404Sobrien
5529179404Sobrien      contents = bfd_malloc (hdr->sh_size);
5530179404Sobrien      if (contents == NULL)
5531179404Sobrien	return FALSE;
5532179404Sobrien      if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
5533179404Sobrien				      0, hdr->sh_size))
5534179404Sobrien	{
5535179404Sobrien	  free (contents);
5536179404Sobrien	  return FALSE;
5537179404Sobrien	}
5538179404Sobrien      l = contents;
5539179404Sobrien      lend = contents + hdr->sh_size;
5540179404Sobrien      while (l + sizeof (Elf_External_Options) <= lend)
5541179404Sobrien	{
5542179404Sobrien	  Elf_Internal_Options intopt;
5543179404Sobrien
5544179404Sobrien	  bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
5545179404Sobrien					&intopt);
5546214950Sgonzo	  if (intopt.size < sizeof (Elf_External_Options))
5547214950Sgonzo	    {
5548214950Sgonzo	      (*_bfd_error_handler)
5549218822Sdim		(_("%B: Warning: bad `%s' option size %u smaller than its header"),
5550218822Sdim		abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
5551214950Sgonzo	      break;
5552214950Sgonzo	    }
5553179404Sobrien	  if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO)
5554179404Sobrien	    {
5555179404Sobrien	      Elf64_Internal_RegInfo intreg;
5556179404Sobrien
5557179404Sobrien	      bfd_mips_elf64_swap_reginfo_in
5558179404Sobrien		(abfd,
5559179404Sobrien		 ((Elf64_External_RegInfo *)
5560179404Sobrien		  (l + sizeof (Elf_External_Options))),
5561179404Sobrien		 &intreg);
5562179404Sobrien	      elf_gp (abfd) = intreg.ri_gp_value;
5563179404Sobrien	    }
5564179404Sobrien	  else if (intopt.kind == ODK_REGINFO)
5565179404Sobrien	    {
5566179404Sobrien	      Elf32_RegInfo intreg;
5567179404Sobrien
5568179404Sobrien	      bfd_mips_elf32_swap_reginfo_in
5569179404Sobrien		(abfd,
5570179404Sobrien		 ((Elf32_External_RegInfo *)
5571179404Sobrien		  (l + sizeof (Elf_External_Options))),
5572179404Sobrien		 &intreg);
5573179404Sobrien	      elf_gp (abfd) = intreg.ri_gp_value;
5574179404Sobrien	    }
5575179404Sobrien	  l += intopt.size;
5576179404Sobrien	}
5577179404Sobrien      free (contents);
5578179404Sobrien    }
5579179404Sobrien
5580179404Sobrien  return TRUE;
5581179404Sobrien}
5582179404Sobrien
5583179404Sobrien/* Set the correct type for a MIPS ELF section.  We do this by the
5584179404Sobrien   section name, which is a hack, but ought to work.  This routine is
5585179404Sobrien   used by both the 32-bit and the 64-bit ABI.  */
5586179404Sobrien
5587179404Sobrienbfd_boolean
5588179404Sobrien_bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
5589179404Sobrien{
5590218822Sdim  const char *name = bfd_get_section_name (abfd, sec);
5591179404Sobrien
5592179404Sobrien  if (strcmp (name, ".liblist") == 0)
5593179404Sobrien    {
5594179404Sobrien      hdr->sh_type = SHT_MIPS_LIBLIST;
5595218822Sdim      hdr->sh_info = sec->size / sizeof (Elf32_Lib);
5596179404Sobrien      /* The sh_link field is set in final_write_processing.  */
5597179404Sobrien    }
5598179404Sobrien  else if (strcmp (name, ".conflict") == 0)
5599179404Sobrien    hdr->sh_type = SHT_MIPS_CONFLICT;
5600218822Sdim  else if (CONST_STRNEQ (name, ".gptab."))
5601179404Sobrien    {
5602179404Sobrien      hdr->sh_type = SHT_MIPS_GPTAB;
5603179404Sobrien      hdr->sh_entsize = sizeof (Elf32_External_gptab);
5604179404Sobrien      /* The sh_info field is set in final_write_processing.  */
5605179404Sobrien    }
5606179404Sobrien  else if (strcmp (name, ".ucode") == 0)
5607179404Sobrien    hdr->sh_type = SHT_MIPS_UCODE;
5608179404Sobrien  else if (strcmp (name, ".mdebug") == 0)
5609179404Sobrien    {
5610179404Sobrien      hdr->sh_type = SHT_MIPS_DEBUG;
5611179404Sobrien      /* In a shared object on IRIX 5.3, the .mdebug section has an
5612179404Sobrien         entsize of 0.  FIXME: Does this matter?  */
5613179404Sobrien      if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0)
5614179404Sobrien	hdr->sh_entsize = 0;
5615179404Sobrien      else
5616179404Sobrien	hdr->sh_entsize = 1;
5617179404Sobrien    }
5618179404Sobrien  else if (strcmp (name, ".reginfo") == 0)
5619179404Sobrien    {
5620179404Sobrien      hdr->sh_type = SHT_MIPS_REGINFO;
5621179404Sobrien      /* In a shared object on IRIX 5.3, the .reginfo section has an
5622179404Sobrien         entsize of 0x18.  FIXME: Does this matter?  */
5623179404Sobrien      if (SGI_COMPAT (abfd))
5624179404Sobrien	{
5625179404Sobrien	  if ((abfd->flags & DYNAMIC) != 0)
5626179404Sobrien	    hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
5627179404Sobrien	  else
5628179404Sobrien	    hdr->sh_entsize = 1;
5629179404Sobrien	}
5630179404Sobrien      else
5631179404Sobrien	hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
5632179404Sobrien    }
5633179404Sobrien  else if (SGI_COMPAT (abfd)
5634179404Sobrien	   && (strcmp (name, ".hash") == 0
5635179404Sobrien	       || strcmp (name, ".dynamic") == 0
5636179404Sobrien	       || strcmp (name, ".dynstr") == 0))
5637179404Sobrien    {
5638179404Sobrien      if (SGI_COMPAT (abfd))
5639179404Sobrien	hdr->sh_entsize = 0;
5640179404Sobrien#if 0
5641179404Sobrien      /* This isn't how the IRIX6 linker behaves.  */
5642179404Sobrien      hdr->sh_info = SIZEOF_MIPS_DYNSYM_SECNAMES;
5643179404Sobrien#endif
5644179404Sobrien    }
5645179404Sobrien  else if (strcmp (name, ".got") == 0
5646179404Sobrien	   || strcmp (name, ".srdata") == 0
5647179404Sobrien	   || strcmp (name, ".sdata") == 0
5648179404Sobrien	   || strcmp (name, ".sbss") == 0
5649179404Sobrien	   || strcmp (name, ".lit4") == 0
5650179404Sobrien	   || strcmp (name, ".lit8") == 0)
5651179404Sobrien    hdr->sh_flags |= SHF_MIPS_GPREL;
5652179404Sobrien  else if (strcmp (name, ".MIPS.interfaces") == 0)
5653179404Sobrien    {
5654179404Sobrien      hdr->sh_type = SHT_MIPS_IFACE;
5655179404Sobrien      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
5656179404Sobrien    }
5657218822Sdim  else if (CONST_STRNEQ (name, ".MIPS.content"))
5658179404Sobrien    {
5659179404Sobrien      hdr->sh_type = SHT_MIPS_CONTENT;
5660179404Sobrien      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
5661179404Sobrien      /* The sh_info field is set in final_write_processing.  */
5662179404Sobrien    }
5663218822Sdim  else if (MIPS_ELF_OPTIONS_SECTION_NAME_P (name))
5664179404Sobrien    {
5665179404Sobrien      hdr->sh_type = SHT_MIPS_OPTIONS;
5666179404Sobrien      hdr->sh_entsize = 1;
5667179404Sobrien      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
5668179404Sobrien    }
5669218822Sdim  else if (CONST_STRNEQ (name, ".debug_"))
5670179404Sobrien    hdr->sh_type = SHT_MIPS_DWARF;
5671179404Sobrien  else if (strcmp (name, ".MIPS.symlib") == 0)
5672179404Sobrien    {
5673179404Sobrien      hdr->sh_type = SHT_MIPS_SYMBOL_LIB;
5674179404Sobrien      /* The sh_link and sh_info fields are set in
5675179404Sobrien         final_write_processing.  */
5676179404Sobrien    }
5677218822Sdim  else if (CONST_STRNEQ (name, ".MIPS.events")
5678218822Sdim	   || CONST_STRNEQ (name, ".MIPS.post_rel"))
5679179404Sobrien    {
5680179404Sobrien      hdr->sh_type = SHT_MIPS_EVENTS;
5681179404Sobrien      hdr->sh_flags |= SHF_MIPS_NOSTRIP;
5682179404Sobrien      /* The sh_link field is set in final_write_processing.  */
5683179404Sobrien    }
5684179404Sobrien  else if (strcmp (name, ".msym") == 0)
5685179404Sobrien    {
5686179404Sobrien      hdr->sh_type = SHT_MIPS_MSYM;
5687179404Sobrien      hdr->sh_flags |= SHF_ALLOC;
5688179404Sobrien      hdr->sh_entsize = 8;
5689179404Sobrien    }
5690179404Sobrien
5691179404Sobrien  /* The generic elf_fake_sections will set up REL_HDR using the default
5692179404Sobrien   kind of relocations.  We used to set up a second header for the
5693179404Sobrien   non-default kind of relocations here, but only NewABI would use
5694179404Sobrien   these, and the IRIX ld doesn't like resulting empty RELA sections.
5695179404Sobrien   Thus we create those header only on demand now.  */
5696179404Sobrien
5697179404Sobrien  return TRUE;
5698179404Sobrien}
5699179404Sobrien
5700179404Sobrien/* Given a BFD section, try to locate the corresponding ELF section
5701179404Sobrien   index.  This is used by both the 32-bit and the 64-bit ABI.
5702179404Sobrien   Actually, it's not clear to me that the 64-bit ABI supports these,
5703179404Sobrien   but for non-PIC objects we will certainly want support for at least
5704179404Sobrien   the .scommon section.  */
5705179404Sobrien
5706179404Sobrienbfd_boolean
5707179404Sobrien_bfd_mips_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
5708179404Sobrien					asection *sec, int *retval)
5709179404Sobrien{
5710179404Sobrien  if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
5711179404Sobrien    {
5712179404Sobrien      *retval = SHN_MIPS_SCOMMON;
5713179404Sobrien      return TRUE;
5714179404Sobrien    }
5715179404Sobrien  if (strcmp (bfd_get_section_name (abfd, sec), ".acommon") == 0)
5716179404Sobrien    {
5717179404Sobrien      *retval = SHN_MIPS_ACOMMON;
5718179404Sobrien      return TRUE;
5719179404Sobrien    }
5720179404Sobrien  return FALSE;
5721179404Sobrien}
5722179404Sobrien
5723179404Sobrien/* Hook called by the linker routine which adds symbols from an object
5724179404Sobrien   file.  We must handle the special MIPS section numbers here.  */
5725179404Sobrien
5726179404Sobrienbfd_boolean
5727179404Sobrien_bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
5728179404Sobrien			       Elf_Internal_Sym *sym, const char **namep,
5729179404Sobrien			       flagword *flagsp ATTRIBUTE_UNUSED,
5730179404Sobrien			       asection **secp, bfd_vma *valp)
5731179404Sobrien{
5732179404Sobrien  if (SGI_COMPAT (abfd)
5733179404Sobrien      && (abfd->flags & DYNAMIC) != 0
5734179404Sobrien      && strcmp (*namep, "_rld_new_interface") == 0)
5735179404Sobrien    {
5736179404Sobrien      /* Skip IRIX5 rld entry name.  */
5737179404Sobrien      *namep = NULL;
5738179404Sobrien      return TRUE;
5739179404Sobrien    }
5740179404Sobrien
5741218822Sdim  /* Shared objects may have a dynamic symbol '_gp_disp' defined as
5742218822Sdim     a SECTION *ABS*.  This causes ld to think it can resolve _gp_disp
5743218822Sdim     by setting a DT_NEEDED for the shared object.  Since _gp_disp is
5744218822Sdim     a magic symbol resolved by the linker, we ignore this bogus definition
5745218822Sdim     of _gp_disp.  New ABI objects do not suffer from this problem so this
5746218822Sdim     is not done for them. */
5747218822Sdim  if (!NEWABI_P(abfd)
5748218822Sdim      && (sym->st_shndx == SHN_ABS)
5749218822Sdim      && (strcmp (*namep, "_gp_disp") == 0))
5750218822Sdim    {
5751218822Sdim      *namep = NULL;
5752218822Sdim      return TRUE;
5753218822Sdim    }
5754218822Sdim
5755179404Sobrien  switch (sym->st_shndx)
5756179404Sobrien    {
5757179404Sobrien    case SHN_COMMON:
5758179404Sobrien      /* Common symbols less than the GP size are automatically
5759179404Sobrien	 treated as SHN_MIPS_SCOMMON symbols.  */
5760179404Sobrien      if (sym->st_size > elf_gp_size (abfd)
5761218822Sdim	  || ELF_ST_TYPE (sym->st_info) == STT_TLS
5762179404Sobrien	  || IRIX_COMPAT (abfd) == ict_irix6)
5763179404Sobrien	break;
5764179404Sobrien      /* Fall through.  */
5765179404Sobrien    case SHN_MIPS_SCOMMON:
5766179404Sobrien      *secp = bfd_make_section_old_way (abfd, ".scommon");
5767179404Sobrien      (*secp)->flags |= SEC_IS_COMMON;
5768179404Sobrien      *valp = sym->st_size;
5769179404Sobrien      break;
5770179404Sobrien
5771179404Sobrien    case SHN_MIPS_TEXT:
5772179404Sobrien      /* This section is used in a shared object.  */
5773179404Sobrien      if (elf_tdata (abfd)->elf_text_section == NULL)
5774179404Sobrien	{
5775179404Sobrien	  asymbol *elf_text_symbol;
5776179404Sobrien	  asection *elf_text_section;
5777179404Sobrien	  bfd_size_type amt = sizeof (asection);
5778179404Sobrien
5779179404Sobrien	  elf_text_section = bfd_zalloc (abfd, amt);
5780179404Sobrien	  if (elf_text_section == NULL)
5781179404Sobrien	    return FALSE;
5782179404Sobrien
5783179404Sobrien	  amt = sizeof (asymbol);
5784179404Sobrien	  elf_text_symbol = bfd_zalloc (abfd, amt);
5785179404Sobrien	  if (elf_text_symbol == NULL)
5786179404Sobrien	    return FALSE;
5787179404Sobrien
5788179404Sobrien	  /* Initialize the section.  */
5789179404Sobrien
5790179404Sobrien	  elf_tdata (abfd)->elf_text_section = elf_text_section;
5791179404Sobrien	  elf_tdata (abfd)->elf_text_symbol = elf_text_symbol;
5792179404Sobrien
5793179404Sobrien	  elf_text_section->symbol = elf_text_symbol;
5794179404Sobrien	  elf_text_section->symbol_ptr_ptr = &elf_tdata (abfd)->elf_text_symbol;
5795179404Sobrien
5796179404Sobrien	  elf_text_section->name = ".text";
5797179404Sobrien	  elf_text_section->flags = SEC_NO_FLAGS;
5798179404Sobrien	  elf_text_section->output_section = NULL;
5799179404Sobrien	  elf_text_section->owner = abfd;
5800179404Sobrien	  elf_text_symbol->name = ".text";
5801179404Sobrien	  elf_text_symbol->flags = BSF_SECTION_SYM | BSF_DYNAMIC;
5802179404Sobrien	  elf_text_symbol->section = elf_text_section;
5803179404Sobrien	}
5804179404Sobrien      /* This code used to do *secp = bfd_und_section_ptr if
5805179404Sobrien         info->shared.  I don't know why, and that doesn't make sense,
5806179404Sobrien         so I took it out.  */
5807179404Sobrien      *secp = elf_tdata (abfd)->elf_text_section;
5808179404Sobrien      break;
5809179404Sobrien
5810179404Sobrien    case SHN_MIPS_ACOMMON:
5811179404Sobrien      /* Fall through. XXX Can we treat this as allocated data?  */
5812179404Sobrien    case SHN_MIPS_DATA:
5813179404Sobrien      /* This section is used in a shared object.  */
5814179404Sobrien      if (elf_tdata (abfd)->elf_data_section == NULL)
5815179404Sobrien	{
5816179404Sobrien	  asymbol *elf_data_symbol;
5817179404Sobrien	  asection *elf_data_section;
5818179404Sobrien	  bfd_size_type amt = sizeof (asection);
5819179404Sobrien
5820179404Sobrien	  elf_data_section = bfd_zalloc (abfd, amt);
5821179404Sobrien	  if (elf_data_section == NULL)
5822179404Sobrien	    return FALSE;
5823179404Sobrien
5824179404Sobrien	  amt = sizeof (asymbol);
5825179404Sobrien	  elf_data_symbol = bfd_zalloc (abfd, amt);
5826179404Sobrien	  if (elf_data_symbol == NULL)
5827179404Sobrien	    return FALSE;
5828179404Sobrien
5829179404Sobrien	  /* Initialize the section.  */
5830179404Sobrien
5831179404Sobrien	  elf_tdata (abfd)->elf_data_section = elf_data_section;
5832179404Sobrien	  elf_tdata (abfd)->elf_data_symbol = elf_data_symbol;
5833179404Sobrien
5834179404Sobrien	  elf_data_section->symbol = elf_data_symbol;
5835179404Sobrien	  elf_data_section->symbol_ptr_ptr = &elf_tdata (abfd)->elf_data_symbol;
5836179404Sobrien
5837179404Sobrien	  elf_data_section->name = ".data";
5838179404Sobrien	  elf_data_section->flags = SEC_NO_FLAGS;
5839179404Sobrien	  elf_data_section->output_section = NULL;
5840179404Sobrien	  elf_data_section->owner = abfd;
5841179404Sobrien	  elf_data_symbol->name = ".data";
5842179404Sobrien	  elf_data_symbol->flags = BSF_SECTION_SYM | BSF_DYNAMIC;
5843179404Sobrien	  elf_data_symbol->section = elf_data_section;
5844179404Sobrien	}
5845179404Sobrien      /* This code used to do *secp = bfd_und_section_ptr if
5846179404Sobrien         info->shared.  I don't know why, and that doesn't make sense,
5847179404Sobrien         so I took it out.  */
5848179404Sobrien      *secp = elf_tdata (abfd)->elf_data_section;
5849179404Sobrien      break;
5850179404Sobrien
5851179404Sobrien    case SHN_MIPS_SUNDEFINED:
5852179404Sobrien      *secp = bfd_und_section_ptr;
5853179404Sobrien      break;
5854179404Sobrien    }
5855179404Sobrien
5856179404Sobrien  if (SGI_COMPAT (abfd)
5857179404Sobrien      && ! info->shared
5858179404Sobrien      && info->hash->creator == abfd->xvec
5859179404Sobrien      && strcmp (*namep, "__rld_obj_head") == 0)
5860179404Sobrien    {
5861179404Sobrien      struct elf_link_hash_entry *h;
5862179404Sobrien      struct bfd_link_hash_entry *bh;
5863179404Sobrien
5864179404Sobrien      /* Mark __rld_obj_head as dynamic.  */
5865179404Sobrien      bh = NULL;
5866179404Sobrien      if (! (_bfd_generic_link_add_one_symbol
5867179404Sobrien	     (info, abfd, *namep, BSF_GLOBAL, *secp, *valp, NULL, FALSE,
5868179404Sobrien	      get_elf_backend_data (abfd)->collect, &bh)))
5869179404Sobrien	return FALSE;
5870179404Sobrien
5871179404Sobrien      h = (struct elf_link_hash_entry *) bh;
5872218822Sdim      h->non_elf = 0;
5873218822Sdim      h->def_regular = 1;
5874179404Sobrien      h->type = STT_OBJECT;
5875179404Sobrien
5876179404Sobrien      if (! bfd_elf_link_record_dynamic_symbol (info, h))
5877179404Sobrien	return FALSE;
5878179404Sobrien
5879179404Sobrien      mips_elf_hash_table (info)->use_rld_obj_head = TRUE;
5880179404Sobrien    }
5881179404Sobrien
5882179404Sobrien  /* If this is a mips16 text symbol, add 1 to the value to make it
5883179404Sobrien     odd.  This will cause something like .word SYM to come up with
5884179404Sobrien     the right value when it is loaded into the PC.  */
5885179404Sobrien  if (sym->st_other == STO_MIPS16)
5886179404Sobrien    ++*valp;
5887179404Sobrien
5888179404Sobrien  return TRUE;
5889179404Sobrien}
5890179404Sobrien
5891179404Sobrien/* This hook function is called before the linker writes out a global
5892179404Sobrien   symbol.  We mark symbols as small common if appropriate.  This is
5893179404Sobrien   also where we undo the increment of the value for a mips16 symbol.  */
5894179404Sobrien
5895179404Sobrienbfd_boolean
5896179404Sobrien_bfd_mips_elf_link_output_symbol_hook
5897179404Sobrien  (struct bfd_link_info *info ATTRIBUTE_UNUSED,
5898179404Sobrien   const char *name ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym,
5899179404Sobrien   asection *input_sec, struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
5900179404Sobrien{
5901179404Sobrien  /* If we see a common symbol, which implies a relocatable link, then
5902179404Sobrien     if a symbol was small common in an input file, mark it as small
5903179404Sobrien     common in the output file.  */
5904179404Sobrien  if (sym->st_shndx == SHN_COMMON
5905179404Sobrien      && strcmp (input_sec->name, ".scommon") == 0)
5906179404Sobrien    sym->st_shndx = SHN_MIPS_SCOMMON;
5907179404Sobrien
5908218822Sdim  if (sym->st_other == STO_MIPS16)
5909218822Sdim    sym->st_value &= ~1;
5910179404Sobrien
5911179404Sobrien  return TRUE;
5912179404Sobrien}
5913179404Sobrien
5914179404Sobrien/* Functions for the dynamic linker.  */
5915179404Sobrien
5916179404Sobrien/* Create dynamic sections when linking against a dynamic object.  */
5917179404Sobrien
5918179404Sobrienbfd_boolean
5919179404Sobrien_bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
5920179404Sobrien{
5921179404Sobrien  struct elf_link_hash_entry *h;
5922179404Sobrien  struct bfd_link_hash_entry *bh;
5923179404Sobrien  flagword flags;
5924179404Sobrien  register asection *s;
5925179404Sobrien  const char * const *namep;
5926218822Sdim  struct mips_elf_link_hash_table *htab;
5927179404Sobrien
5928218822Sdim  htab = mips_elf_hash_table (info);
5929179404Sobrien  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
5930179404Sobrien	   | SEC_LINKER_CREATED | SEC_READONLY);
5931179404Sobrien
5932218822Sdim  /* The psABI requires a read-only .dynamic section, but the VxWorks
5933218822Sdim     EABI doesn't.  */
5934218822Sdim  if (!htab->is_vxworks)
5935179404Sobrien    {
5936218822Sdim      s = bfd_get_section_by_name (abfd, ".dynamic");
5937218822Sdim      if (s != NULL)
5938218822Sdim	{
5939218822Sdim	  if (! bfd_set_section_flags (abfd, s, flags))
5940218822Sdim	    return FALSE;
5941218822Sdim	}
5942179404Sobrien    }
5943179404Sobrien
5944179404Sobrien  /* We need to create .got section.  */
5945179404Sobrien  if (! mips_elf_create_got_section (abfd, info, FALSE))
5946179404Sobrien    return FALSE;
5947179404Sobrien
5948218822Sdim  if (! mips_elf_rel_dyn_section (info, TRUE))
5949179404Sobrien    return FALSE;
5950179404Sobrien
5951179404Sobrien  /* Create .stub section.  */
5952179404Sobrien  if (bfd_get_section_by_name (abfd,
5953179404Sobrien			       MIPS_ELF_STUB_SECTION_NAME (abfd)) == NULL)
5954179404Sobrien    {
5955218822Sdim      s = bfd_make_section_with_flags (abfd,
5956218822Sdim				       MIPS_ELF_STUB_SECTION_NAME (abfd),
5957218822Sdim				       flags | SEC_CODE);
5958179404Sobrien      if (s == NULL
5959179404Sobrien	  || ! bfd_set_section_alignment (abfd, s,
5960179404Sobrien					  MIPS_ELF_LOG_FILE_ALIGN (abfd)))
5961179404Sobrien	return FALSE;
5962179404Sobrien    }
5963179404Sobrien
5964179404Sobrien  if ((IRIX_COMPAT (abfd) == ict_irix5 || IRIX_COMPAT (abfd) == ict_none)
5965179404Sobrien      && !info->shared
5966179404Sobrien      && bfd_get_section_by_name (abfd, ".rld_map") == NULL)
5967179404Sobrien    {
5968218822Sdim      s = bfd_make_section_with_flags (abfd, ".rld_map",
5969218822Sdim				       flags &~ (flagword) SEC_READONLY);
5970179404Sobrien      if (s == NULL
5971179404Sobrien	  || ! bfd_set_section_alignment (abfd, s,
5972179404Sobrien					  MIPS_ELF_LOG_FILE_ALIGN (abfd)))
5973179404Sobrien	return FALSE;
5974179404Sobrien    }
5975179404Sobrien
5976179404Sobrien  /* On IRIX5, we adjust add some additional symbols and change the
5977179404Sobrien     alignments of several sections.  There is no ABI documentation
5978179404Sobrien     indicating that this is necessary on IRIX6, nor any evidence that
5979179404Sobrien     the linker takes such action.  */
5980179404Sobrien  if (IRIX_COMPAT (abfd) == ict_irix5)
5981179404Sobrien    {
5982179404Sobrien      for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
5983179404Sobrien	{
5984179404Sobrien	  bh = NULL;
5985179404Sobrien	  if (! (_bfd_generic_link_add_one_symbol
5986179404Sobrien		 (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr, 0,
5987179404Sobrien		  NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
5988179404Sobrien	    return FALSE;
5989179404Sobrien
5990179404Sobrien	  h = (struct elf_link_hash_entry *) bh;
5991218822Sdim	  h->non_elf = 0;
5992218822Sdim	  h->def_regular = 1;
5993179404Sobrien	  h->type = STT_SECTION;
5994179404Sobrien
5995179404Sobrien	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
5996179404Sobrien	    return FALSE;
5997179404Sobrien	}
5998179404Sobrien
5999179404Sobrien      /* We need to create a .compact_rel section.  */
6000179404Sobrien      if (SGI_COMPAT (abfd))
6001179404Sobrien	{
6002179404Sobrien	  if (!mips_elf_create_compact_rel_section (abfd, info))
6003179404Sobrien	    return FALSE;
6004179404Sobrien	}
6005179404Sobrien
6006179404Sobrien      /* Change alignments of some sections.  */
6007179404Sobrien      s = bfd_get_section_by_name (abfd, ".hash");
6008179404Sobrien      if (s != NULL)
6009179404Sobrien	bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
6010179404Sobrien      s = bfd_get_section_by_name (abfd, ".dynsym");
6011179404Sobrien      if (s != NULL)
6012179404Sobrien	bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
6013179404Sobrien      s = bfd_get_section_by_name (abfd, ".dynstr");
6014179404Sobrien      if (s != NULL)
6015179404Sobrien	bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
6016179404Sobrien      s = bfd_get_section_by_name (abfd, ".reginfo");
6017179404Sobrien      if (s != NULL)
6018179404Sobrien	bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
6019179404Sobrien      s = bfd_get_section_by_name (abfd, ".dynamic");
6020179404Sobrien      if (s != NULL)
6021179404Sobrien	bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
6022179404Sobrien    }
6023179404Sobrien
6024179404Sobrien  if (!info->shared)
6025179404Sobrien    {
6026179404Sobrien      const char *name;
6027179404Sobrien
6028179404Sobrien      name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
6029179404Sobrien      bh = NULL;
6030179404Sobrien      if (!(_bfd_generic_link_add_one_symbol
6031179404Sobrien	    (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
6032179404Sobrien	     NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
6033179404Sobrien	return FALSE;
6034179404Sobrien
6035179404Sobrien      h = (struct elf_link_hash_entry *) bh;
6036218822Sdim      h->non_elf = 0;
6037218822Sdim      h->def_regular = 1;
6038179404Sobrien      h->type = STT_SECTION;
6039179404Sobrien
6040179404Sobrien      if (! bfd_elf_link_record_dynamic_symbol (info, h))
6041179404Sobrien	return FALSE;
6042179404Sobrien
6043179404Sobrien      if (! mips_elf_hash_table (info)->use_rld_obj_head)
6044179404Sobrien	{
6045179404Sobrien	  /* __rld_map is a four byte word located in the .data section
6046179404Sobrien	     and is filled in by the rtld to contain a pointer to
6047179404Sobrien	     the _r_debug structure. Its symbol value will be set in
6048179404Sobrien	     _bfd_mips_elf_finish_dynamic_symbol.  */
6049179404Sobrien	  s = bfd_get_section_by_name (abfd, ".rld_map");
6050179404Sobrien	  BFD_ASSERT (s != NULL);
6051179404Sobrien
6052179404Sobrien	  name = SGI_COMPAT (abfd) ? "__rld_map" : "__RLD_MAP";
6053179404Sobrien	  bh = NULL;
6054179404Sobrien	  if (!(_bfd_generic_link_add_one_symbol
6055179404Sobrien		(info, abfd, name, BSF_GLOBAL, s, 0, NULL, FALSE,
6056179404Sobrien		 get_elf_backend_data (abfd)->collect, &bh)))
6057179404Sobrien	    return FALSE;
6058179404Sobrien
6059179404Sobrien	  h = (struct elf_link_hash_entry *) bh;
6060218822Sdim	  h->non_elf = 0;
6061218822Sdim	  h->def_regular = 1;
6062179404Sobrien	  h->type = STT_OBJECT;
6063179404Sobrien
6064179404Sobrien	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
6065179404Sobrien	    return FALSE;
6066179404Sobrien	}
6067179404Sobrien    }
6068179404Sobrien
6069218822Sdim  if (htab->is_vxworks)
6070218822Sdim    {
6071218822Sdim      /* Create the .plt, .rela.plt, .dynbss and .rela.bss sections.
6072218822Sdim	 Also create the _PROCEDURE_LINKAGE_TABLE symbol.  */
6073218822Sdim      if (!_bfd_elf_create_dynamic_sections (abfd, info))
6074218822Sdim	return FALSE;
6075218822Sdim
6076218822Sdim      /* Cache the sections created above.  */
6077218822Sdim      htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
6078218822Sdim      htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
6079218822Sdim      htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
6080218822Sdim      htab->splt = bfd_get_section_by_name (abfd, ".plt");
6081218822Sdim      if (!htab->sdynbss
6082218822Sdim	  || (!htab->srelbss && !info->shared)
6083218822Sdim	  || !htab->srelplt
6084218822Sdim	  || !htab->splt)
6085218822Sdim	abort ();
6086218822Sdim
6087218822Sdim      /* Do the usual VxWorks handling.  */
6088218822Sdim      if (!elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
6089218822Sdim	return FALSE;
6090218822Sdim
6091218822Sdim      /* Work out the PLT sizes.  */
6092218822Sdim      if (info->shared)
6093218822Sdim	{
6094218822Sdim	  htab->plt_header_size
6095218822Sdim	    = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
6096218822Sdim	  htab->plt_entry_size
6097218822Sdim	    = 4 * ARRAY_SIZE (mips_vxworks_shared_plt_entry);
6098218822Sdim	}
6099218822Sdim      else
6100218822Sdim	{
6101218822Sdim	  htab->plt_header_size
6102218822Sdim	    = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry);
6103218822Sdim	  htab->plt_entry_size
6104218822Sdim	    = 4 * ARRAY_SIZE (mips_vxworks_exec_plt_entry);
6105218822Sdim	}
6106218822Sdim    }
6107218822Sdim
6108179404Sobrien  return TRUE;
6109179404Sobrien}
6110179404Sobrien
6111179404Sobrien/* Look through the relocs for a section during the first phase, and
6112179404Sobrien   allocate space in the global offset table.  */
6113179404Sobrien
6114179404Sobrienbfd_boolean
6115179404Sobrien_bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
6116179404Sobrien			    asection *sec, const Elf_Internal_Rela *relocs)
6117179404Sobrien{
6118179404Sobrien  const char *name;
6119179404Sobrien  bfd *dynobj;
6120179404Sobrien  Elf_Internal_Shdr *symtab_hdr;
6121179404Sobrien  struct elf_link_hash_entry **sym_hashes;
6122179404Sobrien  struct mips_got_info *g;
6123179404Sobrien  size_t extsymoff;
6124179404Sobrien  const Elf_Internal_Rela *rel;
6125179404Sobrien  const Elf_Internal_Rela *rel_end;
6126179404Sobrien  asection *sgot;
6127179404Sobrien  asection *sreloc;
6128179404Sobrien  const struct elf_backend_data *bed;
6129218822Sdim  struct mips_elf_link_hash_table *htab;
6130179404Sobrien
6131179404Sobrien  if (info->relocatable)
6132179404Sobrien    return TRUE;
6133179404Sobrien
6134218822Sdim  htab = mips_elf_hash_table (info);
6135179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
6136179404Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
6137179404Sobrien  sym_hashes = elf_sym_hashes (abfd);
6138179404Sobrien  extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
6139179404Sobrien
6140179404Sobrien  /* Check for the mips16 stub sections.  */
6141179404Sobrien
6142179404Sobrien  name = bfd_get_section_name (abfd, sec);
6143218822Sdim  if (FN_STUB_P (name))
6144179404Sobrien    {
6145179404Sobrien      unsigned long r_symndx;
6146179404Sobrien
6147179404Sobrien      /* Look at the relocation information to figure out which symbol
6148179404Sobrien         this is for.  */
6149179404Sobrien
6150179404Sobrien      r_symndx = ELF_R_SYM (abfd, relocs->r_info);
6151179404Sobrien
6152179404Sobrien      if (r_symndx < extsymoff
6153179404Sobrien	  || sym_hashes[r_symndx - extsymoff] == NULL)
6154179404Sobrien	{
6155179404Sobrien	  asection *o;
6156179404Sobrien
6157179404Sobrien	  /* This stub is for a local symbol.  This stub will only be
6158179404Sobrien             needed if there is some relocation in this BFD, other
6159179404Sobrien             than a 16 bit function call, which refers to this symbol.  */
6160179404Sobrien	  for (o = abfd->sections; o != NULL; o = o->next)
6161179404Sobrien	    {
6162179404Sobrien	      Elf_Internal_Rela *sec_relocs;
6163179404Sobrien	      const Elf_Internal_Rela *r, *rend;
6164179404Sobrien
6165179404Sobrien	      /* We can ignore stub sections when looking for relocs.  */
6166179404Sobrien	      if ((o->flags & SEC_RELOC) == 0
6167179404Sobrien		  || o->reloc_count == 0
6168218822Sdim		  || mips16_stub_section_p (abfd, o))
6169179404Sobrien		continue;
6170179404Sobrien
6171179404Sobrien	      sec_relocs
6172179404Sobrien		= _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
6173179404Sobrien					     info->keep_memory);
6174179404Sobrien	      if (sec_relocs == NULL)
6175179404Sobrien		return FALSE;
6176179404Sobrien
6177179404Sobrien	      rend = sec_relocs + o->reloc_count;
6178179404Sobrien	      for (r = sec_relocs; r < rend; r++)
6179179404Sobrien		if (ELF_R_SYM (abfd, r->r_info) == r_symndx
6180179404Sobrien		    && ELF_R_TYPE (abfd, r->r_info) != R_MIPS16_26)
6181179404Sobrien		  break;
6182179404Sobrien
6183179404Sobrien	      if (elf_section_data (o)->relocs != sec_relocs)
6184179404Sobrien		free (sec_relocs);
6185179404Sobrien
6186179404Sobrien	      if (r < rend)
6187179404Sobrien		break;
6188179404Sobrien	    }
6189179404Sobrien
6190179404Sobrien	  if (o == NULL)
6191179404Sobrien	    {
6192179404Sobrien	      /* There is no non-call reloc for this stub, so we do
6193179404Sobrien                 not need it.  Since this function is called before
6194179404Sobrien                 the linker maps input sections to output sections, we
6195179404Sobrien                 can easily discard it by setting the SEC_EXCLUDE
6196179404Sobrien                 flag.  */
6197179404Sobrien	      sec->flags |= SEC_EXCLUDE;
6198179404Sobrien	      return TRUE;
6199179404Sobrien	    }
6200179404Sobrien
6201179404Sobrien	  /* Record this stub in an array of local symbol stubs for
6202179404Sobrien             this BFD.  */
6203179404Sobrien	  if (elf_tdata (abfd)->local_stubs == NULL)
6204179404Sobrien	    {
6205179404Sobrien	      unsigned long symcount;
6206179404Sobrien	      asection **n;
6207179404Sobrien	      bfd_size_type amt;
6208179404Sobrien
6209179404Sobrien	      if (elf_bad_symtab (abfd))
6210179404Sobrien		symcount = NUM_SHDR_ENTRIES (symtab_hdr);
6211179404Sobrien	      else
6212179404Sobrien		symcount = symtab_hdr->sh_info;
6213179404Sobrien	      amt = symcount * sizeof (asection *);
6214179404Sobrien	      n = bfd_zalloc (abfd, amt);
6215179404Sobrien	      if (n == NULL)
6216179404Sobrien		return FALSE;
6217179404Sobrien	      elf_tdata (abfd)->local_stubs = n;
6218179404Sobrien	    }
6219179404Sobrien
6220218822Sdim	  sec->flags |= SEC_KEEP;
6221179404Sobrien	  elf_tdata (abfd)->local_stubs[r_symndx] = sec;
6222179404Sobrien
6223179404Sobrien	  /* We don't need to set mips16_stubs_seen in this case.
6224179404Sobrien             That flag is used to see whether we need to look through
6225179404Sobrien             the global symbol table for stubs.  We don't need to set
6226179404Sobrien             it here, because we just have a local stub.  */
6227179404Sobrien	}
6228179404Sobrien      else
6229179404Sobrien	{
6230179404Sobrien	  struct mips_elf_link_hash_entry *h;
6231179404Sobrien
6232179404Sobrien	  h = ((struct mips_elf_link_hash_entry *)
6233179404Sobrien	       sym_hashes[r_symndx - extsymoff]);
6234179404Sobrien
6235218822Sdim	  while (h->root.root.type == bfd_link_hash_indirect
6236218822Sdim		 || h->root.root.type == bfd_link_hash_warning)
6237218822Sdim	    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
6238218822Sdim
6239179404Sobrien	  /* H is the symbol this stub is for.  */
6240179404Sobrien
6241218822Sdim	  /* If we already have an appropriate stub for this function, we
6242218822Sdim	     don't need another one, so we can discard this one.  Since
6243218822Sdim	     this function is called before the linker maps input sections
6244218822Sdim	     to output sections, we can easily discard it by setting the
6245218822Sdim	     SEC_EXCLUDE flag.  */
6246218822Sdim	  if (h->fn_stub != NULL)
6247218822Sdim	    {
6248218822Sdim	      sec->flags |= SEC_EXCLUDE;
6249218822Sdim	      return TRUE;
6250218822Sdim	    }
6251218822Sdim
6252218822Sdim	  sec->flags |= SEC_KEEP;
6253179404Sobrien	  h->fn_stub = sec;
6254179404Sobrien	  mips_elf_hash_table (info)->mips16_stubs_seen = TRUE;
6255179404Sobrien	}
6256179404Sobrien    }
6257218822Sdim  else if (CALL_STUB_P (name) || CALL_FP_STUB_P (name))
6258179404Sobrien    {
6259179404Sobrien      unsigned long r_symndx;
6260179404Sobrien      struct mips_elf_link_hash_entry *h;
6261179404Sobrien      asection **loc;
6262179404Sobrien
6263179404Sobrien      /* Look at the relocation information to figure out which symbol
6264179404Sobrien         this is for.  */
6265179404Sobrien
6266179404Sobrien      r_symndx = ELF_R_SYM (abfd, relocs->r_info);
6267179404Sobrien
6268179404Sobrien      if (r_symndx < extsymoff
6269179404Sobrien	  || sym_hashes[r_symndx - extsymoff] == NULL)
6270179404Sobrien	{
6271218822Sdim	  asection *o;
6272179404Sobrien
6273218822Sdim	  /* This stub is for a local symbol.  This stub will only be
6274218822Sdim             needed if there is some relocation (R_MIPS16_26) in this BFD
6275218822Sdim             that refers to this symbol.  */
6276218822Sdim	  for (o = abfd->sections; o != NULL; o = o->next)
6277218822Sdim	    {
6278218822Sdim	      Elf_Internal_Rela *sec_relocs;
6279218822Sdim	      const Elf_Internal_Rela *r, *rend;
6280179404Sobrien
6281218822Sdim	      /* We can ignore stub sections when looking for relocs.  */
6282218822Sdim	      if ((o->flags & SEC_RELOC) == 0
6283218822Sdim		  || o->reloc_count == 0
6284218822Sdim		  || mips16_stub_section_p (abfd, o))
6285218822Sdim		continue;
6286179404Sobrien
6287218822Sdim	      sec_relocs
6288218822Sdim		= _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
6289218822Sdim					     info->keep_memory);
6290218822Sdim	      if (sec_relocs == NULL)
6291218822Sdim		return FALSE;
6292218822Sdim
6293218822Sdim	      rend = sec_relocs + o->reloc_count;
6294218822Sdim	      for (r = sec_relocs; r < rend; r++)
6295218822Sdim		if (ELF_R_SYM (abfd, r->r_info) == r_symndx
6296218822Sdim		    && ELF_R_TYPE (abfd, r->r_info) == R_MIPS16_26)
6297218822Sdim		    break;
6298218822Sdim
6299218822Sdim	      if (elf_section_data (o)->relocs != sec_relocs)
6300218822Sdim		free (sec_relocs);
6301218822Sdim
6302218822Sdim	      if (r < rend)
6303218822Sdim		break;
6304218822Sdim	    }
6305218822Sdim
6306218822Sdim	  if (o == NULL)
6307218822Sdim	    {
6308218822Sdim	      /* There is no non-call reloc for this stub, so we do
6309218822Sdim                 not need it.  Since this function is called before
6310218822Sdim                 the linker maps input sections to output sections, we
6311218822Sdim                 can easily discard it by setting the SEC_EXCLUDE
6312218822Sdim                 flag.  */
6313218822Sdim	      sec->flags |= SEC_EXCLUDE;
6314218822Sdim	      return TRUE;
6315218822Sdim	    }
6316218822Sdim
6317218822Sdim	  /* Record this stub in an array of local symbol call_stubs for
6318218822Sdim             this BFD.  */
6319218822Sdim	  if (elf_tdata (abfd)->local_call_stubs == NULL)
6320218822Sdim	    {
6321218822Sdim	      unsigned long symcount;
6322218822Sdim	      asection **n;
6323218822Sdim	      bfd_size_type amt;
6324218822Sdim
6325218822Sdim	      if (elf_bad_symtab (abfd))
6326218822Sdim		symcount = NUM_SHDR_ENTRIES (symtab_hdr);
6327218822Sdim	      else
6328218822Sdim		symcount = symtab_hdr->sh_info;
6329218822Sdim	      amt = symcount * sizeof (asection *);
6330218822Sdim	      n = bfd_zalloc (abfd, amt);
6331218822Sdim	      if (n == NULL)
6332218822Sdim		return FALSE;
6333218822Sdim	      elf_tdata (abfd)->local_call_stubs = n;
6334218822Sdim	    }
6335218822Sdim
6336218822Sdim	  sec->flags |= SEC_KEEP;
6337218822Sdim	  elf_tdata (abfd)->local_call_stubs[r_symndx] = sec;
6338218822Sdim
6339218822Sdim	  /* We don't need to set mips16_stubs_seen in this case.
6340218822Sdim             That flag is used to see whether we need to look through
6341218822Sdim             the global symbol table for stubs.  We don't need to set
6342218822Sdim             it here, because we just have a local stub.  */
6343218822Sdim	}
6344179404Sobrien      else
6345218822Sdim	{
6346218822Sdim	  h = ((struct mips_elf_link_hash_entry *)
6347218822Sdim	       sym_hashes[r_symndx - extsymoff]);
6348218822Sdim
6349218822Sdim	  /* H is the symbol this stub is for.  */
6350218822Sdim
6351218822Sdim	  if (CALL_FP_STUB_P (name))
6352218822Sdim	    loc = &h->call_fp_stub;
6353218822Sdim	  else
6354218822Sdim	    loc = &h->call_stub;
6355218822Sdim
6356218822Sdim	  /* If we already have an appropriate stub for this function, we
6357218822Sdim	     don't need another one, so we can discard this one.  Since
6358218822Sdim	     this function is called before the linker maps input sections
6359218822Sdim	     to output sections, we can easily discard it by setting the
6360218822Sdim	     SEC_EXCLUDE flag.  */
6361218822Sdim	  if (*loc != NULL)
6362218822Sdim	    {
6363218822Sdim	      sec->flags |= SEC_EXCLUDE;
6364218822Sdim	      return TRUE;
6365218822Sdim	    }
6366179404Sobrien
6367218822Sdim	  sec->flags |= SEC_KEEP;
6368218822Sdim	  *loc = sec;
6369218822Sdim	  mips_elf_hash_table (info)->mips16_stubs_seen = TRUE;
6370179404Sobrien	}
6371179404Sobrien    }
6372179404Sobrien
6373179404Sobrien  if (dynobj == NULL)
6374179404Sobrien    {
6375179404Sobrien      sgot = NULL;
6376179404Sobrien      g = NULL;
6377179404Sobrien    }
6378179404Sobrien  else
6379179404Sobrien    {
6380179404Sobrien      sgot = mips_elf_got_section (dynobj, FALSE);
6381179404Sobrien      if (sgot == NULL)
6382179404Sobrien	g = NULL;
6383179404Sobrien      else
6384179404Sobrien	{
6385179404Sobrien	  BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
6386179404Sobrien	  g = mips_elf_section_data (sgot)->u.got_info;
6387179404Sobrien	  BFD_ASSERT (g != NULL);
6388179404Sobrien	}
6389179404Sobrien    }
6390179404Sobrien
6391179404Sobrien  sreloc = NULL;
6392179404Sobrien  bed = get_elf_backend_data (abfd);
6393179404Sobrien  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
6394179404Sobrien  for (rel = relocs; rel < rel_end; ++rel)
6395179404Sobrien    {
6396179404Sobrien      unsigned long r_symndx;
6397179404Sobrien      unsigned int r_type;
6398179404Sobrien      struct elf_link_hash_entry *h;
6399179404Sobrien
6400179404Sobrien      r_symndx = ELF_R_SYM (abfd, rel->r_info);
6401179404Sobrien      r_type = ELF_R_TYPE (abfd, rel->r_info);
6402179404Sobrien
6403179404Sobrien      if (r_symndx < extsymoff)
6404179404Sobrien	h = NULL;
6405179404Sobrien      else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
6406179404Sobrien	{
6407179404Sobrien	  (*_bfd_error_handler)
6408218822Sdim	    (_("%B: Malformed reloc detected for section %s"),
6409218822Sdim	     abfd, name);
6410179404Sobrien	  bfd_set_error (bfd_error_bad_value);
6411179404Sobrien	  return FALSE;
6412179404Sobrien	}
6413179404Sobrien      else
6414179404Sobrien	{
6415179404Sobrien	  h = sym_hashes[r_symndx - extsymoff];
6416179404Sobrien
6417179404Sobrien	  /* This may be an indirect symbol created because of a version.  */
6418179404Sobrien	  if (h != NULL)
6419179404Sobrien	    {
6420179404Sobrien	      while (h->root.type == bfd_link_hash_indirect)
6421179404Sobrien		h = (struct elf_link_hash_entry *) h->root.u.i.link;
6422179404Sobrien	    }
6423179404Sobrien	}
6424179404Sobrien
6425179404Sobrien      /* Some relocs require a global offset table.  */
6426179404Sobrien      if (dynobj == NULL || sgot == NULL)
6427179404Sobrien	{
6428179404Sobrien	  switch (r_type)
6429179404Sobrien	    {
6430179404Sobrien	    case R_MIPS_GOT16:
6431179404Sobrien	    case R_MIPS_CALL16:
6432179404Sobrien	    case R_MIPS_CALL_HI16:
6433179404Sobrien	    case R_MIPS_CALL_LO16:
6434179404Sobrien	    case R_MIPS_GOT_HI16:
6435179404Sobrien	    case R_MIPS_GOT_LO16:
6436179404Sobrien	    case R_MIPS_GOT_PAGE:
6437179404Sobrien	    case R_MIPS_GOT_OFST:
6438179404Sobrien	    case R_MIPS_GOT_DISP:
6439218822Sdim	    case R_MIPS_TLS_GOTTPREL:
6440218822Sdim	    case R_MIPS_TLS_GD:
6441218822Sdim	    case R_MIPS_TLS_LDM:
6442179404Sobrien	      if (dynobj == NULL)
6443179404Sobrien		elf_hash_table (info)->dynobj = dynobj = abfd;
6444179404Sobrien	      if (! mips_elf_create_got_section (dynobj, info, FALSE))
6445179404Sobrien		return FALSE;
6446179404Sobrien	      g = mips_elf_got_info (dynobj, &sgot);
6447218822Sdim	      if (htab->is_vxworks && !info->shared)
6448218822Sdim		{
6449218822Sdim		  (*_bfd_error_handler)
6450218822Sdim		    (_("%B: GOT reloc at 0x%lx not expected in executables"),
6451218822Sdim		     abfd, (unsigned long) rel->r_offset);
6452218822Sdim		  bfd_set_error (bfd_error_bad_value);
6453218822Sdim		  return FALSE;
6454218822Sdim		}
6455179404Sobrien	      break;
6456179404Sobrien
6457179404Sobrien	    case R_MIPS_32:
6458179404Sobrien	    case R_MIPS_REL32:
6459179404Sobrien	    case R_MIPS_64:
6460218822Sdim	      /* In VxWorks executables, references to external symbols
6461218822Sdim		 are handled using copy relocs or PLT stubs, so there's
6462218822Sdim		 no need to add a dynamic relocation here.  */
6463179404Sobrien	      if (dynobj == NULL
6464218822Sdim		  && (info->shared || (h != NULL && !htab->is_vxworks))
6465179404Sobrien		  && (sec->flags & SEC_ALLOC) != 0)
6466179404Sobrien		elf_hash_table (info)->dynobj = dynobj = abfd;
6467179404Sobrien	      break;
6468179404Sobrien
6469179404Sobrien	    default:
6470179404Sobrien	      break;
6471179404Sobrien	    }
6472179404Sobrien	}
6473179404Sobrien
6474218822Sdim      if (h)
6475179404Sobrien	{
6476218822Sdim	  ((struct mips_elf_link_hash_entry *) h)->is_relocation_target = TRUE;
6477218822Sdim
6478218822Sdim	  /* Relocations against the special VxWorks __GOTT_BASE__ and
6479218822Sdim	     __GOTT_INDEX__ symbols must be left to the loader.  Allocate
6480218822Sdim	     room for them in .rela.dyn.  */
6481218822Sdim	  if (is_gott_symbol (info, h))
6482218822Sdim	    {
6483218822Sdim	      if (sreloc == NULL)
6484218822Sdim		{
6485218822Sdim		  sreloc = mips_elf_rel_dyn_section (info, TRUE);
6486218822Sdim		  if (sreloc == NULL)
6487218822Sdim		    return FALSE;
6488218822Sdim		}
6489218822Sdim	      mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
6490218822Sdim	      if (MIPS_ELF_READONLY_SECTION (sec))
6491218822Sdim		/* We tell the dynamic linker that there are
6492218822Sdim		   relocations against the text segment.  */
6493218822Sdim		info->flags |= DF_TEXTREL;
6494218822Sdim	    }
6495218822Sdim	}
6496218822Sdim      else if (r_type == R_MIPS_CALL_LO16
6497218822Sdim	       || r_type == R_MIPS_GOT_LO16
6498218822Sdim	       || r_type == R_MIPS_GOT_DISP
6499218822Sdim	       || (r_type == R_MIPS_GOT16 && htab->is_vxworks))
6500218822Sdim	{
6501179404Sobrien	  /* We may need a local GOT entry for this relocation.  We
6502179404Sobrien	     don't count R_MIPS_GOT_PAGE because we can estimate the
6503179404Sobrien	     maximum number of pages needed by looking at the size of
6504179404Sobrien	     the segment.  Similar comments apply to R_MIPS_GOT16 and
6505218822Sdim	     R_MIPS_CALL16, except on VxWorks, where GOT relocations
6506218822Sdim	     always evaluate to "G".  We don't count R_MIPS_GOT_HI16, or
6507179404Sobrien	     R_MIPS_CALL_HI16 because these are always followed by an
6508179404Sobrien	     R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.  */
6509179404Sobrien	  if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
6510218822Sdim						  rel->r_addend, g, 0))
6511179404Sobrien	    return FALSE;
6512179404Sobrien	}
6513179404Sobrien
6514179404Sobrien      switch (r_type)
6515179404Sobrien	{
6516179404Sobrien	case R_MIPS_CALL16:
6517179404Sobrien	  if (h == NULL)
6518179404Sobrien	    {
6519179404Sobrien	      (*_bfd_error_handler)
6520218822Sdim		(_("%B: CALL16 reloc at 0x%lx not against global symbol"),
6521218822Sdim		 abfd, (unsigned long) rel->r_offset);
6522179404Sobrien	      bfd_set_error (bfd_error_bad_value);
6523179404Sobrien	      return FALSE;
6524179404Sobrien	    }
6525179404Sobrien	  /* Fall through.  */
6526179404Sobrien
6527179404Sobrien	case R_MIPS_CALL_HI16:
6528179404Sobrien	case R_MIPS_CALL_LO16:
6529179404Sobrien	  if (h != NULL)
6530179404Sobrien	    {
6531218822Sdim	      /* VxWorks call relocations point the function's .got.plt
6532218822Sdim		 entry, which will be allocated by adjust_dynamic_symbol.
6533218822Sdim		 Otherwise, this symbol requires a global GOT entry.  */
6534218822Sdim	      if (!htab->is_vxworks
6535218822Sdim		  && !mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
6536179404Sobrien		return FALSE;
6537179404Sobrien
6538179404Sobrien	      /* We need a stub, not a plt entry for the undefined
6539179404Sobrien		 function.  But we record it as if it needs plt.  See
6540179404Sobrien		 _bfd_elf_adjust_dynamic_symbol.  */
6541218822Sdim	      h->needs_plt = 1;
6542179404Sobrien	      h->type = STT_FUNC;
6543179404Sobrien	    }
6544179404Sobrien	  break;
6545179404Sobrien
6546179404Sobrien	case R_MIPS_GOT_PAGE:
6547179404Sobrien	  /* If this is a global, overridable symbol, GOT_PAGE will
6548179404Sobrien	     decay to GOT_DISP, so we'll need a GOT entry for it.  */
6549179404Sobrien	  if (h == NULL)
6550179404Sobrien	    break;
6551179404Sobrien	  else
6552179404Sobrien	    {
6553179404Sobrien	      struct mips_elf_link_hash_entry *hmips =
6554179404Sobrien		(struct mips_elf_link_hash_entry *) h;
6555179404Sobrien
6556179404Sobrien	      while (hmips->root.root.type == bfd_link_hash_indirect
6557179404Sobrien		     || hmips->root.root.type == bfd_link_hash_warning)
6558179404Sobrien		hmips = (struct mips_elf_link_hash_entry *)
6559179404Sobrien		  hmips->root.root.u.i.link;
6560179404Sobrien
6561218822Sdim	      if (hmips->root.def_regular
6562179404Sobrien		  && ! (info->shared && ! info->symbolic
6563218822Sdim			&& ! hmips->root.forced_local))
6564179404Sobrien		break;
6565179404Sobrien	    }
6566179404Sobrien	  /* Fall through.  */
6567179404Sobrien
6568179404Sobrien	case R_MIPS_GOT16:
6569179404Sobrien	case R_MIPS_GOT_HI16:
6570179404Sobrien	case R_MIPS_GOT_LO16:
6571179404Sobrien	case R_MIPS_GOT_DISP:
6572218822Sdim	  if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
6573179404Sobrien	    return FALSE;
6574179404Sobrien	  break;
6575179404Sobrien
6576218822Sdim	case R_MIPS_TLS_GOTTPREL:
6577218822Sdim	  if (info->shared)
6578218822Sdim	    info->flags |= DF_STATIC_TLS;
6579218822Sdim	  /* Fall through */
6580218822Sdim
6581218822Sdim	case R_MIPS_TLS_LDM:
6582218822Sdim	  if (r_type == R_MIPS_TLS_LDM)
6583218822Sdim	    {
6584218822Sdim	      r_symndx = 0;
6585218822Sdim	      h = NULL;
6586218822Sdim	    }
6587218822Sdim	  /* Fall through */
6588218822Sdim
6589218822Sdim	case R_MIPS_TLS_GD:
6590218822Sdim	  /* This symbol requires a global offset table entry, or two
6591218822Sdim	     for TLS GD relocations.  */
6592218822Sdim	  {
6593218822Sdim	    unsigned char flag = (r_type == R_MIPS_TLS_GD
6594218822Sdim				  ? GOT_TLS_GD
6595218822Sdim				  : r_type == R_MIPS_TLS_LDM
6596218822Sdim				  ? GOT_TLS_LDM
6597218822Sdim				  : GOT_TLS_IE);
6598218822Sdim	    if (h != NULL)
6599218822Sdim	      {
6600218822Sdim		struct mips_elf_link_hash_entry *hmips =
6601218822Sdim		  (struct mips_elf_link_hash_entry *) h;
6602218822Sdim		hmips->tls_type |= flag;
6603218822Sdim
6604218822Sdim		if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g, flag))
6605218822Sdim		  return FALSE;
6606218822Sdim	      }
6607218822Sdim	    else
6608218822Sdim	      {
6609218822Sdim		BFD_ASSERT (flag == GOT_TLS_LDM || r_symndx != 0);
6610218822Sdim
6611218822Sdim		if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
6612218822Sdim							rel->r_addend, g, flag))
6613218822Sdim		  return FALSE;
6614218822Sdim	      }
6615218822Sdim	  }
6616218822Sdim	  break;
6617218822Sdim
6618179404Sobrien	case R_MIPS_32:
6619179404Sobrien	case R_MIPS_REL32:
6620179404Sobrien	case R_MIPS_64:
6621218822Sdim	  /* In VxWorks executables, references to external symbols
6622218822Sdim	     are handled using copy relocs or PLT stubs, so there's
6623218822Sdim	     no need to add a .rela.dyn entry for this relocation.  */
6624218822Sdim	  if ((info->shared || (h != NULL && !htab->is_vxworks))
6625179404Sobrien	      && (sec->flags & SEC_ALLOC) != 0)
6626179404Sobrien	    {
6627179404Sobrien	      if (sreloc == NULL)
6628179404Sobrien		{
6629218822Sdim		  sreloc = mips_elf_rel_dyn_section (info, TRUE);
6630179404Sobrien		  if (sreloc == NULL)
6631179404Sobrien		    return FALSE;
6632179404Sobrien		}
6633179404Sobrien	      if (info->shared)
6634179404Sobrien		{
6635179404Sobrien		  /* When creating a shared object, we must copy these
6636179404Sobrien		     reloc types into the output file as R_MIPS_REL32
6637218822Sdim		     relocs.  Make room for this reloc in .rel(a).dyn.  */
6638218822Sdim		  mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
6639218822Sdim		  if (MIPS_ELF_READONLY_SECTION (sec))
6640179404Sobrien		    /* We tell the dynamic linker that there are
6641179404Sobrien		       relocations against the text segment.  */
6642179404Sobrien		    info->flags |= DF_TEXTREL;
6643179404Sobrien		}
6644179404Sobrien	      else
6645179404Sobrien		{
6646179404Sobrien		  struct mips_elf_link_hash_entry *hmips;
6647179404Sobrien
6648179404Sobrien		  /* We only need to copy this reloc if the symbol is
6649179404Sobrien                     defined in a dynamic object.  */
6650179404Sobrien		  hmips = (struct mips_elf_link_hash_entry *) h;
6651179404Sobrien		  ++hmips->possibly_dynamic_relocs;
6652218822Sdim		  if (MIPS_ELF_READONLY_SECTION (sec))
6653179404Sobrien		    /* We need it to tell the dynamic linker if there
6654179404Sobrien		       are relocations against the text segment.  */
6655179404Sobrien		    hmips->readonly_reloc = TRUE;
6656179404Sobrien		}
6657179404Sobrien
6658179404Sobrien	      /* Even though we don't directly need a GOT entry for
6659179404Sobrien		 this symbol, a symbol must have a dynamic symbol
6660179404Sobrien		 table index greater that DT_MIPS_GOTSYM if there are
6661218822Sdim		 dynamic relocations against it.  This does not apply
6662218822Sdim		 to VxWorks, which does not have the usual coupling
6663218822Sdim		 between global GOT entries and .dynsym entries.  */
6664218822Sdim	      if (h != NULL && !htab->is_vxworks)
6665179404Sobrien		{
6666179404Sobrien		  if (dynobj == NULL)
6667179404Sobrien		    elf_hash_table (info)->dynobj = dynobj = abfd;
6668179404Sobrien		  if (! mips_elf_create_got_section (dynobj, info, TRUE))
6669179404Sobrien		    return FALSE;
6670179404Sobrien		  g = mips_elf_got_info (dynobj, &sgot);
6671218822Sdim		  if (! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
6672179404Sobrien		    return FALSE;
6673179404Sobrien		}
6674179404Sobrien	    }
6675179404Sobrien
6676179404Sobrien	  if (SGI_COMPAT (abfd))
6677179404Sobrien	    mips_elf_hash_table (info)->compact_rel_size +=
6678179404Sobrien	      sizeof (Elf32_External_crinfo);
6679179404Sobrien	  break;
6680179404Sobrien
6681218822Sdim	case R_MIPS_PC16:
6682218822Sdim	  if (h)
6683218822Sdim	    ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
6684218822Sdim	  break;
6685218822Sdim
6686179404Sobrien	case R_MIPS_26:
6687218822Sdim	  if (h)
6688218822Sdim	    ((struct mips_elf_link_hash_entry *) h)->is_branch_target = TRUE;
6689218822Sdim	  /* Fall through.  */
6690218822Sdim
6691179404Sobrien	case R_MIPS_GPREL16:
6692179404Sobrien	case R_MIPS_LITERAL:
6693179404Sobrien	case R_MIPS_GPREL32:
6694179404Sobrien	  if (SGI_COMPAT (abfd))
6695179404Sobrien	    mips_elf_hash_table (info)->compact_rel_size +=
6696179404Sobrien	      sizeof (Elf32_External_crinfo);
6697179404Sobrien	  break;
6698179404Sobrien
6699179404Sobrien	  /* This relocation describes the C++ object vtable hierarchy.
6700179404Sobrien	     Reconstruct it for later use during GC.  */
6701179404Sobrien	case R_MIPS_GNU_VTINHERIT:
6702179404Sobrien	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
6703179404Sobrien	    return FALSE;
6704179404Sobrien	  break;
6705179404Sobrien
6706179404Sobrien	  /* This relocation describes which C++ vtable entries are actually
6707179404Sobrien	     used.  Record for later use during GC.  */
6708179404Sobrien	case R_MIPS_GNU_VTENTRY:
6709179404Sobrien	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
6710179404Sobrien	    return FALSE;
6711179404Sobrien	  break;
6712179404Sobrien
6713179404Sobrien	default:
6714179404Sobrien	  break;
6715179404Sobrien	}
6716179404Sobrien
6717179404Sobrien      /* We must not create a stub for a symbol that has relocations
6718218822Sdim	 related to taking the function's address.  This doesn't apply to
6719218822Sdim	 VxWorks, where CALL relocs refer to a .got.plt entry instead of
6720218822Sdim	 a normal .got entry.  */
6721218822Sdim      if (!htab->is_vxworks && h != NULL)
6722218822Sdim	switch (r_type)
6723218822Sdim	  {
6724218822Sdim	  default:
6725218822Sdim	    ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
6726218822Sdim	    break;
6727218822Sdim	  case R_MIPS_CALL16:
6728218822Sdim	  case R_MIPS_CALL_HI16:
6729218822Sdim	  case R_MIPS_CALL_LO16:
6730218822Sdim	  case R_MIPS_JALR:
6731218822Sdim	    break;
6732218822Sdim	  }
6733179404Sobrien
6734179404Sobrien      /* If this reloc is not a 16 bit call, and it has a global
6735179404Sobrien         symbol, then we will need the fn_stub if there is one.
6736179404Sobrien         References from a stub section do not count.  */
6737179404Sobrien      if (h != NULL
6738179404Sobrien	  && r_type != R_MIPS16_26
6739218822Sdim	  && !mips16_stub_section_p (abfd, sec))
6740179404Sobrien	{
6741179404Sobrien	  struct mips_elf_link_hash_entry *mh;
6742179404Sobrien
6743179404Sobrien	  mh = (struct mips_elf_link_hash_entry *) h;
6744179404Sobrien	  mh->need_fn_stub = TRUE;
6745179404Sobrien	}
6746179404Sobrien    }
6747179404Sobrien
6748179404Sobrien  return TRUE;
6749179404Sobrien}
6750179404Sobrien
6751179404Sobrienbfd_boolean
6752179404Sobrien_bfd_mips_relax_section (bfd *abfd, asection *sec,
6753179404Sobrien			 struct bfd_link_info *link_info,
6754179404Sobrien			 bfd_boolean *again)
6755179404Sobrien{
6756179404Sobrien  Elf_Internal_Rela *internal_relocs;
6757179404Sobrien  Elf_Internal_Rela *irel, *irelend;
6758179404Sobrien  Elf_Internal_Shdr *symtab_hdr;
6759179404Sobrien  bfd_byte *contents = NULL;
6760179404Sobrien  size_t extsymoff;
6761179404Sobrien  bfd_boolean changed_contents = FALSE;
6762179404Sobrien  bfd_vma sec_start = sec->output_section->vma + sec->output_offset;
6763179404Sobrien  Elf_Internal_Sym *isymbuf = NULL;
6764179404Sobrien
6765179404Sobrien  /* We are not currently changing any sizes, so only one pass.  */
6766179404Sobrien  *again = FALSE;
6767179404Sobrien
6768179404Sobrien  if (link_info->relocatable)
6769179404Sobrien    return TRUE;
6770179404Sobrien
6771179404Sobrien  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
6772179404Sobrien					       link_info->keep_memory);
6773179404Sobrien  if (internal_relocs == NULL)
6774179404Sobrien    return TRUE;
6775179404Sobrien
6776179404Sobrien  irelend = internal_relocs + sec->reloc_count
6777179404Sobrien    * get_elf_backend_data (abfd)->s->int_rels_per_ext_rel;
6778179404Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
6779179404Sobrien  extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
6780179404Sobrien
6781179404Sobrien  for (irel = internal_relocs; irel < irelend; irel++)
6782179404Sobrien    {
6783179404Sobrien      bfd_vma symval;
6784179404Sobrien      bfd_signed_vma sym_offset;
6785179404Sobrien      unsigned int r_type;
6786179404Sobrien      unsigned long r_symndx;
6787179404Sobrien      asection *sym_sec;
6788179404Sobrien      unsigned long instruction;
6789179404Sobrien
6790179404Sobrien      /* Turn jalr into bgezal, and jr into beq, if they're marked
6791179404Sobrien	 with a JALR relocation, that indicate where they jump to.
6792179404Sobrien	 This saves some pipeline bubbles.  */
6793179404Sobrien      r_type = ELF_R_TYPE (abfd, irel->r_info);
6794179404Sobrien      if (r_type != R_MIPS_JALR)
6795179404Sobrien	continue;
6796179404Sobrien
6797179404Sobrien      r_symndx = ELF_R_SYM (abfd, irel->r_info);
6798179404Sobrien      /* Compute the address of the jump target.  */
6799179404Sobrien      if (r_symndx >= extsymoff)
6800179404Sobrien	{
6801179404Sobrien	  struct mips_elf_link_hash_entry *h
6802179404Sobrien	    = ((struct mips_elf_link_hash_entry *)
6803179404Sobrien	       elf_sym_hashes (abfd) [r_symndx - extsymoff]);
6804179404Sobrien
6805179404Sobrien	  while (h->root.root.type == bfd_link_hash_indirect
6806179404Sobrien		 || h->root.root.type == bfd_link_hash_warning)
6807179404Sobrien	    h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
6808179404Sobrien
6809179404Sobrien	  /* If a symbol is undefined, or if it may be overridden,
6810179404Sobrien	     skip it.  */
6811179404Sobrien	  if (! ((h->root.root.type == bfd_link_hash_defined
6812179404Sobrien		  || h->root.root.type == bfd_link_hash_defweak)
6813179404Sobrien		 && h->root.root.u.def.section)
6814179404Sobrien	      || (link_info->shared && ! link_info->symbolic
6815218822Sdim		  && !h->root.forced_local))
6816179404Sobrien	    continue;
6817179404Sobrien
6818179404Sobrien	  sym_sec = h->root.root.u.def.section;
6819179404Sobrien	  if (sym_sec->output_section)
6820179404Sobrien	    symval = (h->root.root.u.def.value
6821179404Sobrien		      + sym_sec->output_section->vma
6822179404Sobrien		      + sym_sec->output_offset);
6823179404Sobrien	  else
6824179404Sobrien	    symval = h->root.root.u.def.value;
6825179404Sobrien	}
6826179404Sobrien      else
6827179404Sobrien	{
6828179404Sobrien	  Elf_Internal_Sym *isym;
6829179404Sobrien
6830179404Sobrien	  /* Read this BFD's symbols if we haven't done so already.  */
6831179404Sobrien	  if (isymbuf == NULL && symtab_hdr->sh_info != 0)
6832179404Sobrien	    {
6833179404Sobrien	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
6834179404Sobrien	      if (isymbuf == NULL)
6835179404Sobrien		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
6836179404Sobrien						symtab_hdr->sh_info, 0,
6837179404Sobrien						NULL, NULL, NULL);
6838179404Sobrien	      if (isymbuf == NULL)
6839179404Sobrien		goto relax_return;
6840179404Sobrien	    }
6841179404Sobrien
6842179404Sobrien	  isym = isymbuf + r_symndx;
6843179404Sobrien	  if (isym->st_shndx == SHN_UNDEF)
6844179404Sobrien	    continue;
6845179404Sobrien	  else if (isym->st_shndx == SHN_ABS)
6846179404Sobrien	    sym_sec = bfd_abs_section_ptr;
6847179404Sobrien	  else if (isym->st_shndx == SHN_COMMON)
6848179404Sobrien	    sym_sec = bfd_com_section_ptr;
6849179404Sobrien	  else
6850179404Sobrien	    sym_sec
6851179404Sobrien	      = bfd_section_from_elf_index (abfd, isym->st_shndx);
6852179404Sobrien	  symval = isym->st_value
6853179404Sobrien	    + sym_sec->output_section->vma
6854179404Sobrien	    + sym_sec->output_offset;
6855179404Sobrien	}
6856179404Sobrien
6857179404Sobrien      /* Compute branch offset, from delay slot of the jump to the
6858179404Sobrien	 branch target.  */
6859179404Sobrien      sym_offset = (symval + irel->r_addend)
6860179404Sobrien	- (sec_start + irel->r_offset + 4);
6861179404Sobrien
6862179404Sobrien      /* Branch offset must be properly aligned.  */
6863179404Sobrien      if ((sym_offset & 3) != 0)
6864179404Sobrien	continue;
6865179404Sobrien
6866179404Sobrien      sym_offset >>= 2;
6867179404Sobrien
6868179404Sobrien      /* Check that it's in range.  */
6869179404Sobrien      if (sym_offset < -0x8000 || sym_offset >= 0x8000)
6870179404Sobrien	continue;
6871179404Sobrien
6872179404Sobrien      /* Get the section contents if we haven't done so already.  */
6873179404Sobrien      if (contents == NULL)
6874179404Sobrien	{
6875179404Sobrien	  /* Get cached copy if it exists.  */
6876179404Sobrien	  if (elf_section_data (sec)->this_hdr.contents != NULL)
6877179404Sobrien	    contents = elf_section_data (sec)->this_hdr.contents;
6878179404Sobrien	  else
6879179404Sobrien	    {
6880218822Sdim	      if (!bfd_malloc_and_get_section (abfd, sec, &contents))
6881179404Sobrien		goto relax_return;
6882179404Sobrien	    }
6883179404Sobrien	}
6884179404Sobrien
6885179404Sobrien      instruction = bfd_get_32 (abfd, contents + irel->r_offset);
6886179404Sobrien
6887179404Sobrien      /* If it was jalr <reg>, turn it into bgezal $zero, <target>.  */
6888179404Sobrien      if ((instruction & 0xfc1fffff) == 0x0000f809)
6889179404Sobrien	instruction = 0x04110000;
6890179404Sobrien      /* If it was jr <reg>, turn it into b <target>.  */
6891179404Sobrien      else if ((instruction & 0xfc1fffff) == 0x00000008)
6892179404Sobrien	instruction = 0x10000000;
6893179404Sobrien      else
6894179404Sobrien	continue;
6895179404Sobrien
6896179404Sobrien      instruction |= (sym_offset & 0xffff);
6897179404Sobrien      bfd_put_32 (abfd, instruction, contents + irel->r_offset);
6898179404Sobrien      changed_contents = TRUE;
6899179404Sobrien    }
6900179404Sobrien
6901179404Sobrien  if (contents != NULL
6902179404Sobrien      && elf_section_data (sec)->this_hdr.contents != contents)
6903179404Sobrien    {
6904179404Sobrien      if (!changed_contents && !link_info->keep_memory)
6905179404Sobrien        free (contents);
6906179404Sobrien      else
6907179404Sobrien        {
6908179404Sobrien          /* Cache the section contents for elf_link_input_bfd.  */
6909179404Sobrien          elf_section_data (sec)->this_hdr.contents = contents;
6910179404Sobrien        }
6911179404Sobrien    }
6912179404Sobrien  return TRUE;
6913179404Sobrien
6914179404Sobrien relax_return:
6915218822Sdim  if (contents != NULL
6916218822Sdim      && elf_section_data (sec)->this_hdr.contents != contents)
6917218822Sdim    free (contents);
6918179404Sobrien  return FALSE;
6919179404Sobrien}
6920179404Sobrien
6921179404Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a
6922179404Sobrien   regular object.  The current definition is in some section of the
6923179404Sobrien   dynamic object, but we're not including those sections.  We have to
6924179404Sobrien   change the definition to something the rest of the link can
6925179404Sobrien   understand.  */
6926179404Sobrien
6927179404Sobrienbfd_boolean
6928179404Sobrien_bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
6929179404Sobrien				     struct elf_link_hash_entry *h)
6930179404Sobrien{
6931179404Sobrien  bfd *dynobj;
6932179404Sobrien  struct mips_elf_link_hash_entry *hmips;
6933179404Sobrien  asection *s;
6934218822Sdim  struct mips_elf_link_hash_table *htab;
6935179404Sobrien
6936218822Sdim  htab = mips_elf_hash_table (info);
6937179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
6938179404Sobrien
6939179404Sobrien  /* Make sure we know what is going on here.  */
6940179404Sobrien  BFD_ASSERT (dynobj != NULL
6941218822Sdim	      && (h->needs_plt
6942218822Sdim		  || h->u.weakdef != NULL
6943218822Sdim		  || (h->def_dynamic
6944218822Sdim		      && h->ref_regular
6945218822Sdim		      && !h->def_regular)));
6946179404Sobrien
6947179404Sobrien  /* If this symbol is defined in a dynamic object, we need to copy
6948179404Sobrien     any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
6949179404Sobrien     file.  */
6950179404Sobrien  hmips = (struct mips_elf_link_hash_entry *) h;
6951179404Sobrien  if (! info->relocatable
6952179404Sobrien      && hmips->possibly_dynamic_relocs != 0
6953179404Sobrien      && (h->root.type == bfd_link_hash_defweak
6954218822Sdim	  || !h->def_regular))
6955179404Sobrien    {
6956218822Sdim      mips_elf_allocate_dynamic_relocations
6957218822Sdim	(dynobj, info, hmips->possibly_dynamic_relocs);
6958179404Sobrien      if (hmips->readonly_reloc)
6959179404Sobrien	/* We tell the dynamic linker that there are relocations
6960179404Sobrien	   against the text segment.  */
6961179404Sobrien	info->flags |= DF_TEXTREL;
6962179404Sobrien    }
6963179404Sobrien
6964179404Sobrien  /* For a function, create a stub, if allowed.  */
6965179404Sobrien  if (! hmips->no_fn_stub
6966218822Sdim      && h->needs_plt)
6967179404Sobrien    {
6968179404Sobrien      if (! elf_hash_table (info)->dynamic_sections_created)
6969179404Sobrien	return TRUE;
6970179404Sobrien
6971179404Sobrien      /* If this symbol is not defined in a regular file, then set
6972179404Sobrien	 the symbol to the stub location.  This is required to make
6973179404Sobrien	 function pointers compare as equal between the normal
6974179404Sobrien	 executable and the shared library.  */
6975218822Sdim      if (!h->def_regular)
6976179404Sobrien	{
6977179404Sobrien	  /* We need .stub section.  */
6978179404Sobrien	  s = bfd_get_section_by_name (dynobj,
6979179404Sobrien				       MIPS_ELF_STUB_SECTION_NAME (dynobj));
6980179404Sobrien	  BFD_ASSERT (s != NULL);
6981179404Sobrien
6982179404Sobrien	  h->root.u.def.section = s;
6983218822Sdim	  h->root.u.def.value = s->size;
6984179404Sobrien
6985179404Sobrien	  /* XXX Write this stub address somewhere.  */
6986218822Sdim	  h->plt.offset = s->size;
6987179404Sobrien
6988179404Sobrien	  /* Make room for this stub code.  */
6989218822Sdim	  s->size += htab->function_stub_size;
6990179404Sobrien
6991179404Sobrien	  /* The last half word of the stub will be filled with the index
6992179404Sobrien	     of this symbol in .dynsym section.  */
6993179404Sobrien	  return TRUE;
6994179404Sobrien	}
6995179404Sobrien    }
6996179404Sobrien  else if ((h->type == STT_FUNC)
6997218822Sdim	   && !h->needs_plt)
6998179404Sobrien    {
6999179404Sobrien      /* This will set the entry for this symbol in the GOT to 0, and
7000179404Sobrien         the dynamic linker will take care of this.  */
7001179404Sobrien      h->root.u.def.value = 0;
7002179404Sobrien      return TRUE;
7003179404Sobrien    }
7004179404Sobrien
7005179404Sobrien  /* If this is a weak symbol, and there is a real definition, the
7006179404Sobrien     processor independent code will have arranged for us to see the
7007179404Sobrien     real definition first, and we can just use the same value.  */
7008218822Sdim  if (h->u.weakdef != NULL)
7009179404Sobrien    {
7010218822Sdim      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
7011218822Sdim		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
7012218822Sdim      h->root.u.def.section = h->u.weakdef->root.u.def.section;
7013218822Sdim      h->root.u.def.value = h->u.weakdef->root.u.def.value;
7014179404Sobrien      return TRUE;
7015179404Sobrien    }
7016179404Sobrien
7017179404Sobrien  /* This is a reference to a symbol defined by a dynamic object which
7018179404Sobrien     is not a function.  */
7019179404Sobrien
7020179404Sobrien  return TRUE;
7021179404Sobrien}
7022218822Sdim
7023218822Sdim/* Likewise, for VxWorks.  */
7024218822Sdim
7025218822Sdimbfd_boolean
7026218822Sdim_bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
7027218822Sdim					 struct elf_link_hash_entry *h)
7028218822Sdim{
7029218822Sdim  bfd *dynobj;
7030218822Sdim  struct mips_elf_link_hash_entry *hmips;
7031218822Sdim  struct mips_elf_link_hash_table *htab;
7032218822Sdim
7033218822Sdim  htab = mips_elf_hash_table (info);
7034218822Sdim  dynobj = elf_hash_table (info)->dynobj;
7035218822Sdim  hmips = (struct mips_elf_link_hash_entry *) h;
7036218822Sdim
7037218822Sdim  /* Make sure we know what is going on here.  */
7038218822Sdim  BFD_ASSERT (dynobj != NULL
7039218822Sdim	      && (h->needs_plt
7040218822Sdim		  || h->needs_copy
7041218822Sdim		  || h->u.weakdef != NULL
7042218822Sdim		  || (h->def_dynamic
7043218822Sdim		      && h->ref_regular
7044218822Sdim		      && !h->def_regular)));
7045218822Sdim
7046218822Sdim  /* If the symbol is defined by a dynamic object, we need a PLT stub if
7047218822Sdim     either (a) we want to branch to the symbol or (b) we're linking an
7048218822Sdim     executable that needs a canonical function address.  In the latter
7049218822Sdim     case, the canonical address will be the address of the executable's
7050218822Sdim     load stub.  */
7051218822Sdim  if ((hmips->is_branch_target
7052218822Sdim       || (!info->shared
7053218822Sdim	   && h->type == STT_FUNC
7054218822Sdim	   && hmips->is_relocation_target))
7055218822Sdim      && h->def_dynamic
7056218822Sdim      && h->ref_regular
7057218822Sdim      && !h->def_regular
7058218822Sdim      && !h->forced_local)
7059218822Sdim    h->needs_plt = 1;
7060218822Sdim
7061218822Sdim  /* Locally-binding symbols do not need a PLT stub; we can refer to
7062218822Sdim     the functions directly.  */
7063218822Sdim  else if (h->needs_plt
7064218822Sdim	   && (SYMBOL_CALLS_LOCAL (info, h)
7065218822Sdim	       || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
7066218822Sdim		   && h->root.type == bfd_link_hash_undefweak)))
7067218822Sdim    {
7068218822Sdim      h->needs_plt = 0;
7069218822Sdim      return TRUE;
7070218822Sdim    }
7071218822Sdim
7072218822Sdim  if (h->needs_plt)
7073218822Sdim    {
7074218822Sdim      /* If this is the first symbol to need a PLT entry, allocate room
7075218822Sdim	 for the header, and for the header's .rela.plt.unloaded entries.  */
7076218822Sdim      if (htab->splt->size == 0)
7077218822Sdim	{
7078218822Sdim	  htab->splt->size += htab->plt_header_size;
7079218822Sdim	  if (!info->shared)
7080218822Sdim	    htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela);
7081218822Sdim	}
7082218822Sdim
7083218822Sdim      /* Assign the next .plt entry to this symbol.  */
7084218822Sdim      h->plt.offset = htab->splt->size;
7085218822Sdim      htab->splt->size += htab->plt_entry_size;
7086218822Sdim
7087218822Sdim      /* If the output file has no definition of the symbol, set the
7088218822Sdim	 symbol's value to the address of the stub.  For executables,
7089218822Sdim	 point at the PLT load stub rather than the lazy resolution stub;
7090218822Sdim	 this stub will become the canonical function address.  */
7091218822Sdim      if (!h->def_regular)
7092218822Sdim	{
7093218822Sdim	  h->root.u.def.section = htab->splt;
7094218822Sdim	  h->root.u.def.value = h->plt.offset;
7095218822Sdim	  if (!info->shared)
7096218822Sdim	    h->root.u.def.value += 8;
7097218822Sdim	}
7098218822Sdim
7099218822Sdim      /* Make room for the .got.plt entry and the R_JUMP_SLOT relocation.  */
7100218822Sdim      htab->sgotplt->size += 4;
7101218822Sdim      htab->srelplt->size += sizeof (Elf32_External_Rela);
7102218822Sdim
7103218822Sdim      /* Make room for the .rela.plt.unloaded relocations.  */
7104218822Sdim      if (!info->shared)
7105218822Sdim	htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela);
7106218822Sdim
7107218822Sdim      return TRUE;
7108218822Sdim    }
7109218822Sdim
7110218822Sdim  /* If a function symbol is defined by a dynamic object, and we do not
7111218822Sdim     need a PLT stub for it, the symbol's value should be zero.  */
7112218822Sdim  if (h->type == STT_FUNC
7113218822Sdim      && h->def_dynamic
7114218822Sdim      && h->ref_regular
7115218822Sdim      && !h->def_regular)
7116218822Sdim    {
7117218822Sdim      h->root.u.def.value = 0;
7118218822Sdim      return TRUE;
7119218822Sdim    }
7120218822Sdim
7121218822Sdim  /* If this is a weak symbol, and there is a real definition, the
7122218822Sdim     processor independent code will have arranged for us to see the
7123218822Sdim     real definition first, and we can just use the same value.  */
7124218822Sdim  if (h->u.weakdef != NULL)
7125218822Sdim    {
7126218822Sdim      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
7127218822Sdim		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
7128218822Sdim      h->root.u.def.section = h->u.weakdef->root.u.def.section;
7129218822Sdim      h->root.u.def.value = h->u.weakdef->root.u.def.value;
7130218822Sdim      return TRUE;
7131218822Sdim    }
7132218822Sdim
7133218822Sdim  /* This is a reference to a symbol defined by a dynamic object which
7134218822Sdim     is not a function.  */
7135218822Sdim  if (info->shared)
7136218822Sdim    return TRUE;
7137218822Sdim
7138218822Sdim  /* We must allocate the symbol in our .dynbss section, which will
7139218822Sdim     become part of the .bss section of the executable.  There will be
7140218822Sdim     an entry for this symbol in the .dynsym section.  The dynamic
7141218822Sdim     object will contain position independent code, so all references
7142218822Sdim     from the dynamic object to this symbol will go through the global
7143218822Sdim     offset table.  The dynamic linker will use the .dynsym entry to
7144218822Sdim     determine the address it must put in the global offset table, so
7145218822Sdim     both the dynamic object and the regular object will refer to the
7146218822Sdim     same memory location for the variable.  */
7147218822Sdim
7148218822Sdim  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
7149218822Sdim    {
7150218822Sdim      htab->srelbss->size += sizeof (Elf32_External_Rela);
7151218822Sdim      h->needs_copy = 1;
7152218822Sdim    }
7153218822Sdim
7154218822Sdim  return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss);
7155218822Sdim}
7156179404Sobrien
7157218822Sdim/* Return the number of dynamic section symbols required by OUTPUT_BFD.
7158218822Sdim   The number might be exact or a worst-case estimate, depending on how
7159218822Sdim   much information is available to elf_backend_omit_section_dynsym at
7160218822Sdim   the current linking stage.  */
7161218822Sdim
7162218822Sdimstatic bfd_size_type
7163218822Sdimcount_section_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
7164218822Sdim{
7165218822Sdim  bfd_size_type count;
7166218822Sdim
7167218822Sdim  count = 0;
7168218822Sdim  if (info->shared || elf_hash_table (info)->is_relocatable_executable)
7169218822Sdim    {
7170218822Sdim      asection *p;
7171218822Sdim      const struct elf_backend_data *bed;
7172218822Sdim
7173218822Sdim      bed = get_elf_backend_data (output_bfd);
7174218822Sdim      for (p = output_bfd->sections; p ; p = p->next)
7175218822Sdim	if ((p->flags & SEC_EXCLUDE) == 0
7176218822Sdim	    && (p->flags & SEC_ALLOC) != 0
7177218822Sdim	    && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
7178218822Sdim	  ++count;
7179218822Sdim    }
7180218822Sdim  return count;
7181218822Sdim}
7182218822Sdim
7183179404Sobrien/* This function is called after all the input files have been read,
7184179404Sobrien   and the input sections have been assigned to output sections.  We
7185179404Sobrien   check for any mips16 stub sections that we can discard.  */
7186179404Sobrien
7187179404Sobrienbfd_boolean
7188179404Sobrien_bfd_mips_elf_always_size_sections (bfd *output_bfd,
7189179404Sobrien				    struct bfd_link_info *info)
7190179404Sobrien{
7191179404Sobrien  asection *ri;
7192179404Sobrien
7193179404Sobrien  bfd *dynobj;
7194179404Sobrien  asection *s;
7195179404Sobrien  struct mips_got_info *g;
7196179404Sobrien  int i;
7197179404Sobrien  bfd_size_type loadable_size = 0;
7198179404Sobrien  bfd_size_type local_gotno;
7199218822Sdim  bfd_size_type dynsymcount;
7200179404Sobrien  bfd *sub;
7201218822Sdim  struct mips_elf_count_tls_arg count_tls_arg;
7202218822Sdim  struct mips_elf_link_hash_table *htab;
7203179404Sobrien
7204218822Sdim  htab = mips_elf_hash_table (info);
7205218822Sdim
7206179404Sobrien  /* The .reginfo section has a fixed size.  */
7207179404Sobrien  ri = bfd_get_section_by_name (output_bfd, ".reginfo");
7208179404Sobrien  if (ri != NULL)
7209179404Sobrien    bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
7210179404Sobrien
7211179404Sobrien  if (! (info->relocatable
7212179404Sobrien	 || ! mips_elf_hash_table (info)->mips16_stubs_seen))
7213179404Sobrien    mips_elf_link_hash_traverse (mips_elf_hash_table (info),
7214179404Sobrien				 mips_elf_check_mips16_stubs, NULL);
7215179404Sobrien
7216179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
7217179404Sobrien  if (dynobj == NULL)
7218179404Sobrien    /* Relocatable links don't have it.  */
7219179404Sobrien    return TRUE;
7220179404Sobrien
7221179404Sobrien  g = mips_elf_got_info (dynobj, &s);
7222179404Sobrien  if (s == NULL)
7223179404Sobrien    return TRUE;
7224179404Sobrien
7225179404Sobrien  /* Calculate the total loadable size of the output.  That
7226179404Sobrien     will give us the maximum number of GOT_PAGE entries
7227179404Sobrien     required.  */
7228179404Sobrien  for (sub = info->input_bfds; sub; sub = sub->link_next)
7229179404Sobrien    {
7230179404Sobrien      asection *subsection;
7231179404Sobrien
7232179404Sobrien      for (subsection = sub->sections;
7233179404Sobrien	   subsection;
7234179404Sobrien	   subsection = subsection->next)
7235179404Sobrien	{
7236179404Sobrien	  if ((subsection->flags & SEC_ALLOC) == 0)
7237179404Sobrien	    continue;
7238218822Sdim	  loadable_size += ((subsection->size + 0xf)
7239179404Sobrien			    &~ (bfd_size_type) 0xf);
7240179404Sobrien	}
7241179404Sobrien    }
7242179404Sobrien
7243179404Sobrien  /* There has to be a global GOT entry for every symbol with
7244179404Sobrien     a dynamic symbol table index of DT_MIPS_GOTSYM or
7245179404Sobrien     higher.  Therefore, it make sense to put those symbols
7246179404Sobrien     that need GOT entries at the end of the symbol table.  We
7247179404Sobrien     do that here.  */
7248179404Sobrien  if (! mips_elf_sort_hash_table (info, 1))
7249179404Sobrien    return FALSE;
7250179404Sobrien
7251179404Sobrien  if (g->global_gotsym != NULL)
7252179404Sobrien    i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
7253179404Sobrien  else
7254179404Sobrien    /* If there are no global symbols, or none requiring
7255179404Sobrien       relocations, then GLOBAL_GOTSYM will be NULL.  */
7256179404Sobrien    i = 0;
7257179404Sobrien
7258218822Sdim  /* Get a worst-case estimate of the number of dynamic symbols needed.
7259218822Sdim     At this point, dynsymcount does not account for section symbols
7260218822Sdim     and count_section_dynsyms may overestimate the number that will
7261218822Sdim     be needed.  */
7262218822Sdim  dynsymcount = (elf_hash_table (info)->dynsymcount
7263218822Sdim		 + count_section_dynsyms (output_bfd, info));
7264218822Sdim
7265218822Sdim  /* Determine the size of one stub entry.  */
7266218822Sdim  htab->function_stub_size = (dynsymcount > 0x10000
7267218822Sdim			      ? MIPS_FUNCTION_STUB_BIG_SIZE
7268218822Sdim			      : MIPS_FUNCTION_STUB_NORMAL_SIZE);
7269218822Sdim
7270179404Sobrien  /* In the worst case, we'll get one stub per dynamic symbol, plus
7271179404Sobrien     one to account for the dummy entry at the end required by IRIX
7272179404Sobrien     rld.  */
7273218822Sdim  loadable_size += htab->function_stub_size * (i + 1);
7274179404Sobrien
7275218822Sdim  if (htab->is_vxworks)
7276218822Sdim    /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
7277218822Sdim       relocations against local symbols evaluate to "G", and the EABI does
7278218822Sdim       not include R_MIPS_GOT_PAGE.  */
7279218822Sdim    local_gotno = 0;
7280218822Sdim  else
7281218822Sdim    /* Assume there are two loadable segments consisting of contiguous
7282218822Sdim       sections.  Is 5 enough?  */
7283218822Sdim    local_gotno = (loadable_size >> 16) + 5;
7284179404Sobrien
7285179404Sobrien  g->local_gotno += local_gotno;
7286218822Sdim  s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
7287179404Sobrien
7288179404Sobrien  g->global_gotno = i;
7289218822Sdim  s->size += i * MIPS_ELF_GOT_SIZE (output_bfd);
7290179404Sobrien
7291218822Sdim  /* We need to calculate tls_gotno for global symbols at this point
7292218822Sdim     instead of building it up earlier, to avoid doublecounting
7293218822Sdim     entries for one global symbol from multiple input files.  */
7294218822Sdim  count_tls_arg.info = info;
7295218822Sdim  count_tls_arg.needed = 0;
7296218822Sdim  elf_link_hash_traverse (elf_hash_table (info),
7297218822Sdim			  mips_elf_count_global_tls_entries,
7298218822Sdim			  &count_tls_arg);
7299218822Sdim  g->tls_gotno += count_tls_arg.needed;
7300218822Sdim  s->size += g->tls_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
7301179404Sobrien
7302218822Sdim  mips_elf_resolve_final_got_entries (g);
7303218822Sdim
7304218822Sdim  /* VxWorks does not support multiple GOTs.  It initializes $gp to
7305218822Sdim     __GOTT_BASE__[__GOTT_INDEX__], the value of which is set by the
7306218822Sdim     dynamic loader.  */
7307218822Sdim  if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
7308218822Sdim    {
7309218822Sdim      if (! mips_elf_multi_got (output_bfd, info, g, s, local_gotno))
7310218822Sdim	return FALSE;
7311218822Sdim    }
7312218822Sdim  else
7313218822Sdim    {
7314218822Sdim      /* Set up TLS entries for the first GOT.  */
7315218822Sdim      g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
7316218822Sdim      htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
7317218822Sdim    }
7318218822Sdim
7319179404Sobrien  return TRUE;
7320179404Sobrien}
7321179404Sobrien
7322179404Sobrien/* Set the sizes of the dynamic sections.  */
7323179404Sobrien
7324179404Sobrienbfd_boolean
7325179404Sobrien_bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
7326179404Sobrien				     struct bfd_link_info *info)
7327179404Sobrien{
7328179404Sobrien  bfd *dynobj;
7329218822Sdim  asection *s, *sreldyn;
7330179404Sobrien  bfd_boolean reltext;
7331218822Sdim  struct mips_elf_link_hash_table *htab;
7332179404Sobrien
7333218822Sdim  htab = mips_elf_hash_table (info);
7334179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
7335179404Sobrien  BFD_ASSERT (dynobj != NULL);
7336179404Sobrien
7337179404Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
7338179404Sobrien    {
7339179404Sobrien      /* Set the contents of the .interp section to the interpreter.  */
7340179404Sobrien      if (info->executable)
7341179404Sobrien	{
7342179404Sobrien	  s = bfd_get_section_by_name (dynobj, ".interp");
7343179404Sobrien	  BFD_ASSERT (s != NULL);
7344218822Sdim	  s->size
7345179404Sobrien	    = strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1;
7346179404Sobrien	  s->contents
7347179404Sobrien	    = (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
7348179404Sobrien	}
7349179404Sobrien    }
7350179404Sobrien
7351179404Sobrien  /* The check_relocs and adjust_dynamic_symbol entry points have
7352179404Sobrien     determined the sizes of the various dynamic sections.  Allocate
7353179404Sobrien     memory for them.  */
7354179404Sobrien  reltext = FALSE;
7355218822Sdim  sreldyn = NULL;
7356179404Sobrien  for (s = dynobj->sections; s != NULL; s = s->next)
7357179404Sobrien    {
7358179404Sobrien      const char *name;
7359179404Sobrien
7360179404Sobrien      /* It's OK to base decisions on the section name, because none
7361179404Sobrien	 of the dynobj section names depend upon the input files.  */
7362179404Sobrien      name = bfd_get_section_name (dynobj, s);
7363179404Sobrien
7364179404Sobrien      if ((s->flags & SEC_LINKER_CREATED) == 0)
7365179404Sobrien	continue;
7366179404Sobrien
7367218822Sdim      if (CONST_STRNEQ (name, ".rel"))
7368179404Sobrien	{
7369218822Sdim	  if (s->size != 0)
7370179404Sobrien	    {
7371179404Sobrien	      const char *outname;
7372179404Sobrien	      asection *target;
7373179404Sobrien
7374179404Sobrien	      /* If this relocation section applies to a read only
7375179404Sobrien                 section, then we probably need a DT_TEXTREL entry.
7376218822Sdim                 If the relocation section is .rel(a).dyn, we always
7377179404Sobrien                 assert a DT_TEXTREL entry rather than testing whether
7378179404Sobrien                 there exists a relocation to a read only section or
7379179404Sobrien                 not.  */
7380179404Sobrien	      outname = bfd_get_section_name (output_bfd,
7381179404Sobrien					      s->output_section);
7382179404Sobrien	      target = bfd_get_section_by_name (output_bfd, outname + 4);
7383179404Sobrien	      if ((target != NULL
7384179404Sobrien		   && (target->flags & SEC_READONLY) != 0
7385179404Sobrien		   && (target->flags & SEC_ALLOC) != 0)
7386218822Sdim		  || strcmp (outname, MIPS_ELF_REL_DYN_NAME (info)) == 0)
7387179404Sobrien		reltext = TRUE;
7388179404Sobrien
7389179404Sobrien	      /* We use the reloc_count field as a counter if we need
7390179404Sobrien		 to copy relocs into the output file.  */
7391218822Sdim	      if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) != 0)
7392179404Sobrien		s->reloc_count = 0;
7393179404Sobrien
7394179404Sobrien	      /* If combreloc is enabled, elf_link_sort_relocs() will
7395179404Sobrien		 sort relocations, but in a different way than we do,
7396179404Sobrien		 and before we're done creating relocations.  Also, it
7397179404Sobrien		 will move them around between input sections'
7398179404Sobrien		 relocation's contents, so our sorting would be
7399179404Sobrien		 broken, so don't let it run.  */
7400179404Sobrien	      info->combreloc = 0;
7401179404Sobrien	    }
7402179404Sobrien	}
7403218822Sdim      else if (htab->is_vxworks && strcmp (name, ".got") == 0)
7404179404Sobrien	{
7405218822Sdim	  /* Executables do not need a GOT.  */
7406218822Sdim	  if (info->shared)
7407218822Sdim	    {
7408218822Sdim	      /* Allocate relocations for all but the reserved entries.  */
7409218822Sdim	      struct mips_got_info *g;
7410218822Sdim	      unsigned int count;
7411218822Sdim
7412218822Sdim	      g = mips_elf_got_info (dynobj, NULL);
7413218822Sdim	      count = (g->global_gotno
7414218822Sdim		       + g->local_gotno
7415218822Sdim		       - MIPS_RESERVED_GOTNO (info));
7416218822Sdim	      mips_elf_allocate_dynamic_relocations (dynobj, info, count);
7417218822Sdim	    }
7418218822Sdim	}
7419218822Sdim      else if (!htab->is_vxworks && CONST_STRNEQ (name, ".got"))
7420218822Sdim	{
7421179404Sobrien	  /* _bfd_mips_elf_always_size_sections() has already done
7422179404Sobrien	     most of the work, but some symbols may have been mapped
7423179404Sobrien	     to versions that we must now resolve in the got_entries
7424179404Sobrien	     hash tables.  */
7425179404Sobrien	  struct mips_got_info *gg = mips_elf_got_info (dynobj, NULL);
7426179404Sobrien	  struct mips_got_info *g = gg;
7427179404Sobrien	  struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
7428179404Sobrien	  unsigned int needed_relocs = 0;
7429179404Sobrien
7430179404Sobrien	  if (gg->next)
7431179404Sobrien	    {
7432179404Sobrien	      set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
7433179404Sobrien	      set_got_offset_arg.info = info;
7434179404Sobrien
7435218822Sdim	      /* NOTE 2005-02-03: How can this call, or the next, ever
7436218822Sdim		 find any indirect entries to resolve?  They were all
7437218822Sdim		 resolved in mips_elf_multi_got.  */
7438179404Sobrien	      mips_elf_resolve_final_got_entries (gg);
7439179404Sobrien	      for (g = gg->next; g && g->next != gg; g = g->next)
7440179404Sobrien		{
7441179404Sobrien		  unsigned int save_assign;
7442179404Sobrien
7443179404Sobrien		  mips_elf_resolve_final_got_entries (g);
7444179404Sobrien
7445179404Sobrien		  /* Assign offsets to global GOT entries.  */
7446179404Sobrien		  save_assign = g->assigned_gotno;
7447179404Sobrien		  g->assigned_gotno = g->local_gotno;
7448179404Sobrien		  set_got_offset_arg.g = g;
7449179404Sobrien		  set_got_offset_arg.needed_relocs = 0;
7450179404Sobrien		  htab_traverse (g->got_entries,
7451179404Sobrien				 mips_elf_set_global_got_offset,
7452179404Sobrien				 &set_got_offset_arg);
7453179404Sobrien		  needed_relocs += set_got_offset_arg.needed_relocs;
7454179404Sobrien		  BFD_ASSERT (g->assigned_gotno - g->local_gotno
7455179404Sobrien			      <= g->global_gotno);
7456179404Sobrien
7457179404Sobrien		  g->assigned_gotno = save_assign;
7458179404Sobrien		  if (info->shared)
7459179404Sobrien		    {
7460179404Sobrien		      needed_relocs += g->local_gotno - g->assigned_gotno;
7461179404Sobrien		      BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
7462179404Sobrien				  + g->next->global_gotno
7463218822Sdim				  + g->next->tls_gotno
7464218822Sdim				  + MIPS_RESERVED_GOTNO (info));
7465179404Sobrien		    }
7466179404Sobrien		}
7467218822Sdim	    }
7468218822Sdim	  else
7469218822Sdim	    {
7470218822Sdim	      struct mips_elf_count_tls_arg arg;
7471218822Sdim	      arg.info = info;
7472218822Sdim	      arg.needed = 0;
7473179404Sobrien
7474218822Sdim	      htab_traverse (gg->got_entries, mips_elf_count_local_tls_relocs,
7475218822Sdim			     &arg);
7476218822Sdim	      elf_link_hash_traverse (elf_hash_table (info),
7477218822Sdim				      mips_elf_count_global_tls_relocs,
7478218822Sdim				      &arg);
7479218822Sdim
7480218822Sdim	      needed_relocs += arg.needed;
7481179404Sobrien	    }
7482218822Sdim
7483218822Sdim	  if (needed_relocs)
7484218822Sdim	    mips_elf_allocate_dynamic_relocations (dynobj, info,
7485218822Sdim						   needed_relocs);
7486179404Sobrien	}
7487179404Sobrien      else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
7488179404Sobrien	{
7489179404Sobrien	  /* IRIX rld assumes that the function stub isn't at the end
7490218822Sdim	     of .text section.  So put a dummy.  XXX  */
7491218822Sdim	  s->size += htab->function_stub_size;
7492179404Sobrien	}
7493179404Sobrien      else if (! info->shared
7494179404Sobrien	       && ! mips_elf_hash_table (info)->use_rld_obj_head
7495218822Sdim	       && CONST_STRNEQ (name, ".rld_map"))
7496179404Sobrien	{
7497218822Sdim	  /* We add a room for __rld_map.  It will be filled in by the
7498179404Sobrien	     rtld to contain a pointer to the _r_debug structure.  */
7499255982Semaste	  s->size += MIPS_ELF_RLD_MAP_SIZE (output_bfd);
7500179404Sobrien	}
7501179404Sobrien      else if (SGI_COMPAT (output_bfd)
7502218822Sdim	       && CONST_STRNEQ (name, ".compact_rel"))
7503218822Sdim	s->size += mips_elf_hash_table (info)->compact_rel_size;
7504218822Sdim      else if (! CONST_STRNEQ (name, ".init")
7505218822Sdim	       && s != htab->sgotplt
7506218822Sdim	       && s != htab->splt)
7507179404Sobrien	{
7508179404Sobrien	  /* It's not one of our sections, so don't allocate space.  */
7509179404Sobrien	  continue;
7510179404Sobrien	}
7511179404Sobrien
7512218822Sdim      if (s->size == 0)
7513179404Sobrien	{
7514218822Sdim	  s->flags |= SEC_EXCLUDE;
7515179404Sobrien	  continue;
7516179404Sobrien	}
7517179404Sobrien
7518218822Sdim      if ((s->flags & SEC_HAS_CONTENTS) == 0)
7519218822Sdim	continue;
7520218822Sdim
7521218822Sdim      /* Allocate memory for this section last, since we may increase its
7522218822Sdim	 size above.  */
7523218822Sdim      if (strcmp (name, MIPS_ELF_REL_DYN_NAME (info)) == 0)
7524218822Sdim	{
7525218822Sdim	  sreldyn = s;
7526218822Sdim	  continue;
7527218822Sdim	}
7528218822Sdim
7529179404Sobrien      /* Allocate memory for the section contents.  */
7530218822Sdim      s->contents = bfd_zalloc (dynobj, s->size);
7531218822Sdim      if (s->contents == NULL)
7532179404Sobrien	{
7533179404Sobrien	  bfd_set_error (bfd_error_no_memory);
7534179404Sobrien	  return FALSE;
7535179404Sobrien	}
7536179404Sobrien    }
7537179404Sobrien
7538218822Sdim  /* Allocate memory for the .rel(a).dyn section.  */
7539218822Sdim  if (sreldyn != NULL)
7540218822Sdim    {
7541218822Sdim      sreldyn->contents = bfd_zalloc (dynobj, sreldyn->size);
7542218822Sdim      if (sreldyn->contents == NULL)
7543218822Sdim	{
7544218822Sdim	  bfd_set_error (bfd_error_no_memory);
7545218822Sdim	  return FALSE;
7546218822Sdim	}
7547218822Sdim    }
7548218822Sdim
7549179404Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
7550179404Sobrien    {
7551179404Sobrien      /* Add some entries to the .dynamic section.  We fill in the
7552179404Sobrien	 values later, in _bfd_mips_elf_finish_dynamic_sections, but we
7553179404Sobrien	 must add the entries now so that we get the correct size for
7554218822Sdim	 the .dynamic section.  */
7555218822Sdim
7556218822Sdim      /* SGI object has the equivalence of DT_DEBUG in the
7557218822Sdim	 DT_MIPS_RLD_MAP entry.  This must come first because glibc
7558218822Sdim	 only fills in DT_MIPS_RLD_MAP (not DT_DEBUG) and GDB only
7559218822Sdim	 looks at the first one it sees.  */
7560218822Sdim      if (!info->shared
7561218822Sdim	  && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
7562218822Sdim	return FALSE;
7563218822Sdim
7564218822Sdim      /* The DT_DEBUG entry may be filled in by the dynamic linker and
7565218822Sdim	 used by the debugger.  */
7566218822Sdim      if (info->executable
7567218822Sdim	  && !SGI_COMPAT (output_bfd)
7568218822Sdim	  && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
7569218822Sdim	return FALSE;
7570218822Sdim
7571218822Sdim      if (reltext && (SGI_COMPAT (output_bfd) || htab->is_vxworks))
7572218822Sdim	info->flags |= DF_TEXTREL;
7573218822Sdim
7574218822Sdim      if ((info->flags & DF_TEXTREL) != 0)
7575179404Sobrien	{
7576218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
7577179404Sobrien	    return FALSE;
7578218822Sdim
7579218822Sdim	  /* Clear the DF_TEXTREL flag.  It will be set again if we
7580218822Sdim	     write out an actual text relocation; we may not, because
7581218822Sdim	     at this point we do not know whether e.g. any .eh_frame
7582218822Sdim	     absolute relocations have been converted to PC-relative.  */
7583218822Sdim	  info->flags &= ~DF_TEXTREL;
7584218822Sdim	}
7585218822Sdim
7586218822Sdim      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
7587218822Sdim	return FALSE;
7588218822Sdim
7589218822Sdim      if (htab->is_vxworks)
7590218822Sdim	{
7591218822Sdim	  /* VxWorks uses .rela.dyn instead of .rel.dyn.  It does not
7592218822Sdim	     use any of the DT_MIPS_* tags.  */
7593218822Sdim	  if (mips_elf_rel_dyn_section (info, FALSE))
7594179404Sobrien	    {
7595218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELA, 0))
7596179404Sobrien		return FALSE;
7597218822Sdim
7598218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELASZ, 0))
7599218822Sdim		return FALSE;
7600218822Sdim
7601218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELAENT, 0))
7602218822Sdim		return FALSE;
7603179404Sobrien	    }
7604218822Sdim	  if (htab->splt->size > 0)
7605218822Sdim	    {
7606218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0))
7607218822Sdim		return FALSE;
7608218822Sdim
7609218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_JMPREL, 0))
7610218822Sdim		return FALSE;
7611218822Sdim
7612218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTRELSZ, 0))
7613218822Sdim		return FALSE;
7614218822Sdim	    }
7615179404Sobrien	}
7616179404Sobrien      else
7617179404Sobrien	{
7618218822Sdim	  if (mips_elf_rel_dyn_section (info, FALSE))
7619179404Sobrien	    {
7620218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
7621179404Sobrien		return FALSE;
7622218822Sdim
7623218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
7624218822Sdim		return FALSE;
7625218822Sdim
7626218822Sdim	      if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
7627218822Sdim		return FALSE;
7628179404Sobrien	    }
7629179404Sobrien
7630218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
7631218822Sdim	    return FALSE;
7632179404Sobrien
7633218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_FLAGS, 0))
7634179404Sobrien	    return FALSE;
7635179404Sobrien
7636218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_BASE_ADDRESS, 0))
7637218822Sdim	    return FALSE;
7638179404Sobrien
7639218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LOCAL_GOTNO, 0))
7640179404Sobrien	    return FALSE;
7641179404Sobrien
7642218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_SYMTABNO, 0))
7643179404Sobrien	    return FALSE;
7644179404Sobrien
7645218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_UNREFEXTNO, 0))
7646179404Sobrien	    return FALSE;
7647179404Sobrien
7648218822Sdim	  if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0))
7649218822Sdim	    return FALSE;
7650179404Sobrien
7651218822Sdim	  if (IRIX_COMPAT (dynobj) == ict_irix5
7652218822Sdim	      && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0))
7653218822Sdim	    return FALSE;
7654179404Sobrien
7655218822Sdim	  if (IRIX_COMPAT (dynobj) == ict_irix6
7656218822Sdim	      && (bfd_get_section_by_name
7657218822Sdim		  (dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
7658218822Sdim	      && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
7659218822Sdim	    return FALSE;
7660218822Sdim	}
7661218822Sdim    }
7662179404Sobrien
7663218822Sdim  return TRUE;
7664218822Sdim}
7665218822Sdim
7666218822Sdim/* REL is a relocation in INPUT_BFD that is being copied to OUTPUT_BFD.
7667218822Sdim   Adjust its R_ADDEND field so that it is correct for the output file.
7668218822Sdim   LOCAL_SYMS and LOCAL_SECTIONS are arrays of INPUT_BFD's local symbols
7669218822Sdim   and sections respectively; both use symbol indexes.  */
7670179404Sobrien
7671218822Sdimstatic void
7672218822Sdimmips_elf_adjust_addend (bfd *output_bfd, struct bfd_link_info *info,
7673218822Sdim			bfd *input_bfd, Elf_Internal_Sym *local_syms,
7674218822Sdim			asection **local_sections, Elf_Internal_Rela *rel)
7675218822Sdim{
7676218822Sdim  unsigned int r_type, r_symndx;
7677218822Sdim  Elf_Internal_Sym *sym;
7678218822Sdim  asection *sec;
7679179404Sobrien
7680218822Sdim  if (mips_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE))
7681218822Sdim    {
7682218822Sdim      r_type = ELF_R_TYPE (output_bfd, rel->r_info);
7683218822Sdim      if (r_type == R_MIPS16_GPREL
7684218822Sdim	  || r_type == R_MIPS_GPREL16
7685218822Sdim	  || r_type == R_MIPS_GPREL32
7686218822Sdim	  || r_type == R_MIPS_LITERAL)
7687218822Sdim	{
7688218822Sdim	  rel->r_addend += _bfd_get_gp_value (input_bfd);
7689218822Sdim	  rel->r_addend -= _bfd_get_gp_value (output_bfd);
7690218822Sdim	}
7691179404Sobrien
7692218822Sdim      r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
7693218822Sdim      sym = local_syms + r_symndx;
7694179404Sobrien
7695218822Sdim      /* Adjust REL's addend to account for section merging.  */
7696218822Sdim      if (!info->relocatable)
7697218822Sdim	{
7698218822Sdim	  sec = local_sections[r_symndx];
7699218822Sdim	  _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
7700218822Sdim	}
7701179404Sobrien
7702218822Sdim      /* This would normally be done by the rela_normal code in elflink.c.  */
7703218822Sdim      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
7704218822Sdim	rel->r_addend += local_sections[r_symndx]->output_offset;
7705179404Sobrien    }
7706218822Sdim}
7707179404Sobrien
7708179404Sobrien/* Relocate a MIPS ELF section.  */
7709179404Sobrien
7710179404Sobrienbfd_boolean
7711179404Sobrien_bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
7712179404Sobrien				bfd *input_bfd, asection *input_section,
7713179404Sobrien				bfd_byte *contents, Elf_Internal_Rela *relocs,
7714179404Sobrien				Elf_Internal_Sym *local_syms,
7715179404Sobrien				asection **local_sections)
7716179404Sobrien{
7717179404Sobrien  Elf_Internal_Rela *rel;
7718179404Sobrien  const Elf_Internal_Rela *relend;
7719179404Sobrien  bfd_vma addend = 0;
7720179404Sobrien  bfd_boolean use_saved_addend_p = FALSE;
7721179404Sobrien  const struct elf_backend_data *bed;
7722179404Sobrien
7723179404Sobrien  bed = get_elf_backend_data (output_bfd);
7724179404Sobrien  relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
7725179404Sobrien  for (rel = relocs; rel < relend; ++rel)
7726179404Sobrien    {
7727179404Sobrien      const char *name;
7728218822Sdim      bfd_vma value = 0;
7729179404Sobrien      reloc_howto_type *howto;
7730179404Sobrien      bfd_boolean require_jalx;
7731179404Sobrien      /* TRUE if the relocation is a RELA relocation, rather than a
7732179404Sobrien         REL relocation.  */
7733179404Sobrien      bfd_boolean rela_relocation_p = TRUE;
7734179404Sobrien      unsigned int r_type = ELF_R_TYPE (output_bfd, rel->r_info);
7735179404Sobrien      const char *msg;
7736218822Sdim      unsigned long r_symndx;
7737218822Sdim      asection *sec;
7738218822Sdim      Elf_Internal_Shdr *symtab_hdr;
7739218822Sdim      struct elf_link_hash_entry *h;
7740179404Sobrien
7741179404Sobrien      /* Find the relocation howto for this relocation.  */
7742218822Sdim      howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type,
7743218822Sdim				       NEWABI_P (input_bfd)
7744218822Sdim				       && (MIPS_RELOC_RELA_P
7745218822Sdim					   (input_bfd, input_section,
7746218822Sdim					    rel - relocs)));
7747218822Sdim
7748218822Sdim      r_symndx = ELF_R_SYM (input_bfd, rel->r_info);
7749218822Sdim      symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
7750218822Sdim      if (mips_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE))
7751218822Sdim	{
7752218822Sdim	  sec = local_sections[r_symndx];
7753218822Sdim	  h = NULL;
7754218822Sdim	}
7755218822Sdim      else
7756218822Sdim	{
7757218822Sdim	  unsigned long extsymoff;
7758218822Sdim
7759218822Sdim	  extsymoff = 0;
7760218822Sdim	  if (!elf_bad_symtab (input_bfd))
7761218822Sdim	    extsymoff = symtab_hdr->sh_info;
7762218822Sdim	  h = elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
7763218822Sdim	  while (h->root.type == bfd_link_hash_indirect
7764218822Sdim		 || h->root.type == bfd_link_hash_warning)
7765218822Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
7766218822Sdim
7767218822Sdim	  sec = NULL;
7768218822Sdim	  if (h->root.type == bfd_link_hash_defined
7769218822Sdim	      || h->root.type == bfd_link_hash_defweak)
7770218822Sdim	    sec = h->root.u.def.section;
7771218822Sdim	}
7772218822Sdim
7773218822Sdim      if (sec != NULL && elf_discarded_section (sec))
7774218822Sdim	{
7775218822Sdim	  /* For relocs against symbols from removed linkonce sections,
7776218822Sdim	     or sections discarded by a linker script, we just want the
7777218822Sdim	     section contents zeroed.  Avoid any special processing.  */
7778218822Sdim	  _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
7779218822Sdim	  rel->r_info = 0;
7780218822Sdim	  rel->r_addend = 0;
7781218822Sdim	  continue;
7782218822Sdim	}
7783218822Sdim
7784179404Sobrien      if (r_type == R_MIPS_64 && ! NEWABI_P (input_bfd))
7785179404Sobrien	{
7786179404Sobrien	  /* Some 32-bit code uses R_MIPS_64.  In particular, people use
7787179404Sobrien	     64-bit code, but make sure all their addresses are in the
7788179404Sobrien	     lowermost or uppermost 32-bit section of the 64-bit address
7789179404Sobrien	     space.  Thus, when they use an R_MIPS_64 they mean what is
7790179404Sobrien	     usually meant by R_MIPS_32, with the exception that the
7791179404Sobrien	     stored value is sign-extended to 64 bits.  */
7792179404Sobrien	  howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, R_MIPS_32, FALSE);
7793179404Sobrien
7794179404Sobrien	  /* On big-endian systems, we need to lie about the position
7795179404Sobrien	     of the reloc.  */
7796179404Sobrien	  if (bfd_big_endian (input_bfd))
7797179404Sobrien	    rel->r_offset += 4;
7798179404Sobrien	}
7799179404Sobrien
7800179404Sobrien      if (!use_saved_addend_p)
7801179404Sobrien	{
7802179404Sobrien	  Elf_Internal_Shdr *rel_hdr;
7803179404Sobrien
7804179404Sobrien	  /* If these relocations were originally of the REL variety,
7805179404Sobrien	     we must pull the addend out of the field that will be
7806179404Sobrien	     relocated.  Otherwise, we simply use the contents of the
7807179404Sobrien	     RELA relocation.  To determine which flavor or relocation
7808179404Sobrien	     this is, we depend on the fact that the INPUT_SECTION's
7809179404Sobrien	     REL_HDR is read before its REL_HDR2.  */
7810179404Sobrien	  rel_hdr = &elf_section_data (input_section)->rel_hdr;
7811179404Sobrien	  if ((size_t) (rel - relocs)
7812179404Sobrien	      >= (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel))
7813179404Sobrien	    rel_hdr = elf_section_data (input_section)->rel_hdr2;
7814179404Sobrien	  if (rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (input_bfd))
7815179404Sobrien	    {
7816218822Sdim	      bfd_byte *location = contents + rel->r_offset;
7817218822Sdim
7818179404Sobrien	      /* Note that this is a REL relocation.  */
7819179404Sobrien	      rela_relocation_p = FALSE;
7820179404Sobrien
7821179404Sobrien	      /* Get the addend, which is stored in the input file.  */
7822218822Sdim	      _bfd_mips16_elf_reloc_unshuffle (input_bfd, r_type, FALSE,
7823218822Sdim					       location);
7824179404Sobrien	      addend = mips_elf_obtain_contents (howto, rel, input_bfd,
7825179404Sobrien						 contents);
7826218822Sdim	      _bfd_mips16_elf_reloc_shuffle(input_bfd, r_type, FALSE,
7827218822Sdim					    location);
7828218822Sdim
7829179404Sobrien	      addend &= howto->src_mask;
7830179404Sobrien
7831179404Sobrien	      /* For some kinds of relocations, the ADDEND is a
7832179404Sobrien		 combination of the addend stored in two different
7833179404Sobrien		 relocations.   */
7834218822Sdim	      if (r_type == R_MIPS_HI16 || r_type == R_MIPS16_HI16
7835179404Sobrien		  || (r_type == R_MIPS_GOT16
7836179404Sobrien		      && mips_elf_local_relocation_p (input_bfd, rel,
7837179404Sobrien						      local_sections, FALSE)))
7838179404Sobrien		{
7839179404Sobrien		  const Elf_Internal_Rela *lo16_relocation;
7840179404Sobrien		  reloc_howto_type *lo16_howto;
7841218822Sdim		  int lo16_type;
7842179404Sobrien
7843218822Sdim		  if (r_type == R_MIPS16_HI16)
7844218822Sdim		    lo16_type = R_MIPS16_LO16;
7845218822Sdim		  else
7846218822Sdim		    lo16_type = R_MIPS_LO16;
7847218822Sdim
7848179404Sobrien		  /* The combined value is the sum of the HI16 addend,
7849179404Sobrien		     left-shifted by sixteen bits, and the LO16
7850179404Sobrien		     addend, sign extended.  (Usually, the code does
7851179404Sobrien		     a `lui' of the HI16 value, and then an `addiu' of
7852179404Sobrien		     the LO16 value.)
7853179404Sobrien
7854218822Sdim		     Scan ahead to find a matching LO16 relocation.
7855218822Sdim
7856218822Sdim		     According to the MIPS ELF ABI, the R_MIPS_LO16
7857218822Sdim		     relocation must be immediately following.
7858218822Sdim		     However, for the IRIX6 ABI, the next relocation
7859218822Sdim		     may be a composed relocation consisting of
7860218822Sdim		     several relocations for the same address.  In
7861218822Sdim		     that case, the R_MIPS_LO16 relocation may occur
7862218822Sdim		     as one of these.  We permit a similar extension
7863218822Sdim		     in general, as that is useful for GCC.
7864218822Sdim
7865218822Sdim		     In some cases GCC dead code elimination removes
7866218822Sdim		     the LO16 but keeps the corresponding HI16.  This
7867218822Sdim		     is strictly speaking a violation of the ABI but
7868218822Sdim		     not immediately harmful.  */
7869218822Sdim		  lo16_relocation = mips_elf_next_relocation (input_bfd,
7870218822Sdim							      lo16_type,
7871179404Sobrien							      rel, relend);
7872179404Sobrien		  if (lo16_relocation == NULL)
7873218822Sdim		    {
7874218822Sdim		      const char *name;
7875179404Sobrien
7876218822Sdim		      if (h)
7877218822Sdim			name = h->root.root.string;
7878218822Sdim		      else
7879218822Sdim			name = bfd_elf_sym_name (input_bfd, symtab_hdr,
7880218822Sdim						 local_syms + r_symndx,
7881218822Sdim						 sec);
7882218822Sdim		      (*_bfd_error_handler)
7883218822Sdim			(_("%B: Can't find matching LO16 reloc against `%s' for %s at 0x%lx in section `%A'"),
7884218822Sdim			 input_bfd, input_section, name, howto->name,
7885218822Sdim			 rel->r_offset);
7886218822Sdim		    }
7887218822Sdim		  else
7888218822Sdim		    {
7889218822Sdim		      bfd_byte *lo16_location;
7890218822Sdim		      bfd_vma l;
7891179404Sobrien
7892218822Sdim		      lo16_location = contents + lo16_relocation->r_offset;
7893179404Sobrien
7894218822Sdim		      /* Obtain the addend kept there.  */
7895218822Sdim		      lo16_howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd,
7896218822Sdim							    lo16_type, FALSE);
7897218822Sdim		      _bfd_mips16_elf_reloc_unshuffle (input_bfd, lo16_type,
7898218822Sdim						       FALSE, lo16_location);
7899218822Sdim		      l = mips_elf_obtain_contents (lo16_howto,
7900218822Sdim						    lo16_relocation,
7901218822Sdim						    input_bfd, contents);
7902218822Sdim		      _bfd_mips16_elf_reloc_shuffle (input_bfd, lo16_type,
7903218822Sdim						     FALSE, lo16_location);
7904218822Sdim		      l &= lo16_howto->src_mask;
7905218822Sdim		      l <<= lo16_howto->rightshift;
7906218822Sdim		      l = _bfd_mips_elf_sign_extend (l, 16);
7907179404Sobrien
7908218822Sdim		      addend <<= 16;
7909218822Sdim
7910218822Sdim		      /* Compute the combined addend.  */
7911218822Sdim		      addend += l;
7912218822Sdim		    }
7913179404Sobrien		}
7914179404Sobrien	      else
7915179404Sobrien		addend <<= howto->rightshift;
7916179404Sobrien	    }
7917179404Sobrien	  else
7918179404Sobrien	    addend = rel->r_addend;
7919218822Sdim	  mips_elf_adjust_addend (output_bfd, info, input_bfd,
7920218822Sdim				  local_syms, local_sections, rel);
7921179404Sobrien	}
7922179404Sobrien
7923179404Sobrien      if (info->relocatable)
7924179404Sobrien	{
7925179404Sobrien	  if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd)
7926179404Sobrien	      && bfd_big_endian (input_bfd))
7927179404Sobrien	    rel->r_offset -= 4;
7928179404Sobrien
7929218822Sdim	  if (!rela_relocation_p && rel->r_addend)
7930179404Sobrien	    {
7931218822Sdim	      addend += rel->r_addend;
7932179404Sobrien	      if (r_type == R_MIPS_HI16
7933218822Sdim		  || r_type == R_MIPS_GOT16)
7934179404Sobrien		addend = mips_elf_high (addend);
7935179404Sobrien	      else if (r_type == R_MIPS_HIGHER)
7936179404Sobrien		addend = mips_elf_higher (addend);
7937179404Sobrien	      else if (r_type == R_MIPS_HIGHEST)
7938179404Sobrien		addend = mips_elf_highest (addend);
7939179404Sobrien	      else
7940179404Sobrien		addend >>= howto->rightshift;
7941179404Sobrien
7942179404Sobrien	      /* We use the source mask, rather than the destination
7943179404Sobrien		 mask because the place to which we are writing will be
7944179404Sobrien		 source of the addend in the final link.  */
7945179404Sobrien	      addend &= howto->src_mask;
7946179404Sobrien
7947179404Sobrien	      if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
7948179404Sobrien		/* See the comment above about using R_MIPS_64 in the 32-bit
7949179404Sobrien		   ABI.  Here, we need to update the addend.  It would be
7950179404Sobrien		   possible to get away with just using the R_MIPS_32 reloc
7951179404Sobrien		   but for endianness.  */
7952179404Sobrien		{
7953179404Sobrien		  bfd_vma sign_bits;
7954179404Sobrien		  bfd_vma low_bits;
7955179404Sobrien		  bfd_vma high_bits;
7956179404Sobrien
7957179404Sobrien		  if (addend & ((bfd_vma) 1 << 31))
7958179404Sobrien#ifdef BFD64
7959179404Sobrien		    sign_bits = ((bfd_vma) 1 << 32) - 1;
7960179404Sobrien#else
7961179404Sobrien		    sign_bits = -1;
7962179404Sobrien#endif
7963179404Sobrien		  else
7964179404Sobrien		    sign_bits = 0;
7965179404Sobrien
7966179404Sobrien		  /* If we don't know that we have a 64-bit type,
7967179404Sobrien		     do two separate stores.  */
7968179404Sobrien		  if (bfd_big_endian (input_bfd))
7969179404Sobrien		    {
7970179404Sobrien		      /* Store the sign-bits (which are most significant)
7971179404Sobrien			 first.  */
7972179404Sobrien		      low_bits = sign_bits;
7973179404Sobrien		      high_bits = addend;
7974179404Sobrien		    }
7975179404Sobrien		  else
7976179404Sobrien		    {
7977179404Sobrien		      low_bits = addend;
7978179404Sobrien		      high_bits = sign_bits;
7979179404Sobrien		    }
7980179404Sobrien		  bfd_put_32 (input_bfd, low_bits,
7981179404Sobrien			      contents + rel->r_offset);
7982179404Sobrien		  bfd_put_32 (input_bfd, high_bits,
7983179404Sobrien			      contents + rel->r_offset + 4);
7984179404Sobrien		  continue;
7985179404Sobrien		}
7986179404Sobrien
7987179404Sobrien	      if (! mips_elf_perform_relocation (info, howto, rel, addend,
7988179404Sobrien						 input_bfd, input_section,
7989179404Sobrien						 contents, FALSE))
7990179404Sobrien		return FALSE;
7991179404Sobrien	    }
7992179404Sobrien
7993179404Sobrien	  /* Go on to the next relocation.  */
7994179404Sobrien	  continue;
7995179404Sobrien	}
7996179404Sobrien
7997179404Sobrien      /* In the N32 and 64-bit ABIs there may be multiple consecutive
7998179404Sobrien	 relocations for the same offset.  In that case we are
7999179404Sobrien	 supposed to treat the output of each relocation as the addend
8000179404Sobrien	 for the next.  */
8001179404Sobrien      if (rel + 1 < relend
8002179404Sobrien	  && rel->r_offset == rel[1].r_offset
8003179404Sobrien	  && ELF_R_TYPE (input_bfd, rel[1].r_info) != R_MIPS_NONE)
8004179404Sobrien	use_saved_addend_p = TRUE;
8005179404Sobrien      else
8006179404Sobrien	use_saved_addend_p = FALSE;
8007179404Sobrien
8008179404Sobrien      /* Figure out what value we are supposed to relocate.  */
8009179404Sobrien      switch (mips_elf_calculate_relocation (output_bfd, input_bfd,
8010179404Sobrien					     input_section, info, rel,
8011179404Sobrien					     addend, howto, local_syms,
8012179404Sobrien					     local_sections, &value,
8013179404Sobrien					     &name, &require_jalx,
8014179404Sobrien					     use_saved_addend_p))
8015179404Sobrien	{
8016179404Sobrien	case bfd_reloc_continue:
8017179404Sobrien	  /* There's nothing to do.  */
8018179404Sobrien	  continue;
8019179404Sobrien
8020179404Sobrien	case bfd_reloc_undefined:
8021179404Sobrien	  /* mips_elf_calculate_relocation already called the
8022179404Sobrien	     undefined_symbol callback.  There's no real point in
8023179404Sobrien	     trying to perform the relocation at this point, so we
8024179404Sobrien	     just skip ahead to the next relocation.  */
8025179404Sobrien	  continue;
8026179404Sobrien
8027179404Sobrien	case bfd_reloc_notsupported:
8028179404Sobrien	  msg = _("internal error: unsupported relocation error");
8029179404Sobrien	  info->callbacks->warning
8030179404Sobrien	    (info, msg, name, input_bfd, input_section, rel->r_offset);
8031179404Sobrien	  return FALSE;
8032179404Sobrien
8033179404Sobrien	case bfd_reloc_overflow:
8034179404Sobrien	  if (use_saved_addend_p)
8035179404Sobrien	    /* Ignore overflow until we reach the last relocation for
8036179404Sobrien	       a given location.  */
8037179404Sobrien	    ;
8038179404Sobrien	  else
8039179404Sobrien	    {
8040179404Sobrien	      BFD_ASSERT (name != NULL);
8041179404Sobrien	      if (! ((*info->callbacks->reloc_overflow)
8042218822Sdim		     (info, NULL, name, howto->name, (bfd_vma) 0,
8043179404Sobrien		      input_bfd, input_section, rel->r_offset)))
8044179404Sobrien		return FALSE;
8045179404Sobrien	    }
8046179404Sobrien	  break;
8047179404Sobrien
8048179404Sobrien	case bfd_reloc_ok:
8049179404Sobrien	  break;
8050179404Sobrien
8051179404Sobrien	default:
8052179404Sobrien	  abort ();
8053179404Sobrien	  break;
8054179404Sobrien	}
8055179404Sobrien
8056179404Sobrien      /* If we've got another relocation for the address, keep going
8057179404Sobrien	 until we reach the last one.  */
8058179404Sobrien      if (use_saved_addend_p)
8059179404Sobrien	{
8060179404Sobrien	  addend = value;
8061179404Sobrien	  continue;
8062179404Sobrien	}
8063179404Sobrien
8064179404Sobrien      if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
8065179404Sobrien	/* See the comment above about using R_MIPS_64 in the 32-bit
8066179404Sobrien	   ABI.  Until now, we've been using the HOWTO for R_MIPS_32;
8067179404Sobrien	   that calculated the right value.  Now, however, we
8068179404Sobrien	   sign-extend the 32-bit result to 64-bits, and store it as a
8069179404Sobrien	   64-bit value.  We are especially generous here in that we
8070179404Sobrien	   go to extreme lengths to support this usage on systems with
8071179404Sobrien	   only a 32-bit VMA.  */
8072179404Sobrien	{
8073179404Sobrien	  bfd_vma sign_bits;
8074179404Sobrien	  bfd_vma low_bits;
8075179404Sobrien	  bfd_vma high_bits;
8076179404Sobrien
8077179404Sobrien	  if (value & ((bfd_vma) 1 << 31))
8078179404Sobrien#ifdef BFD64
8079179404Sobrien	    sign_bits = ((bfd_vma) 1 << 32) - 1;
8080179404Sobrien#else
8081179404Sobrien	    sign_bits = -1;
8082179404Sobrien#endif
8083179404Sobrien	  else
8084179404Sobrien	    sign_bits = 0;
8085179404Sobrien
8086179404Sobrien	  /* If we don't know that we have a 64-bit type,
8087179404Sobrien	     do two separate stores.  */
8088179404Sobrien	  if (bfd_big_endian (input_bfd))
8089179404Sobrien	    {
8090179404Sobrien	      /* Undo what we did above.  */
8091179404Sobrien	      rel->r_offset -= 4;
8092179404Sobrien	      /* Store the sign-bits (which are most significant)
8093179404Sobrien		 first.  */
8094179404Sobrien	      low_bits = sign_bits;
8095179404Sobrien	      high_bits = value;
8096179404Sobrien	    }
8097179404Sobrien	  else
8098179404Sobrien	    {
8099179404Sobrien	      low_bits = value;
8100179404Sobrien	      high_bits = sign_bits;
8101179404Sobrien	    }
8102179404Sobrien	  bfd_put_32 (input_bfd, low_bits,
8103179404Sobrien		      contents + rel->r_offset);
8104179404Sobrien	  bfd_put_32 (input_bfd, high_bits,
8105179404Sobrien		      contents + rel->r_offset + 4);
8106179404Sobrien	  continue;
8107179404Sobrien	}
8108179404Sobrien
8109179404Sobrien      /* Actually perform the relocation.  */
8110179404Sobrien      if (! mips_elf_perform_relocation (info, howto, rel, value,
8111179404Sobrien					 input_bfd, input_section,
8112179404Sobrien					 contents, require_jalx))
8113179404Sobrien	return FALSE;
8114179404Sobrien    }
8115179404Sobrien
8116179404Sobrien  return TRUE;
8117179404Sobrien}
8118179404Sobrien
8119179404Sobrien/* If NAME is one of the special IRIX6 symbols defined by the linker,
8120179404Sobrien   adjust it appropriately now.  */
8121179404Sobrien
8122179404Sobrienstatic void
8123179404Sobrienmips_elf_irix6_finish_dynamic_symbol (bfd *abfd ATTRIBUTE_UNUSED,
8124179404Sobrien				      const char *name, Elf_Internal_Sym *sym)
8125179404Sobrien{
8126179404Sobrien  /* The linker script takes care of providing names and values for
8127179404Sobrien     these, but we must place them into the right sections.  */
8128179404Sobrien  static const char* const text_section_symbols[] = {
8129179404Sobrien    "_ftext",
8130179404Sobrien    "_etext",
8131179404Sobrien    "__dso_displacement",
8132179404Sobrien    "__elf_header",
8133179404Sobrien    "__program_header_table",
8134179404Sobrien    NULL
8135179404Sobrien  };
8136179404Sobrien
8137179404Sobrien  static const char* const data_section_symbols[] = {
8138179404Sobrien    "_fdata",
8139179404Sobrien    "_edata",
8140179404Sobrien    "_end",
8141179404Sobrien    "_fbss",
8142179404Sobrien    NULL
8143179404Sobrien  };
8144179404Sobrien
8145179404Sobrien  const char* const *p;
8146179404Sobrien  int i;
8147179404Sobrien
8148179404Sobrien  for (i = 0; i < 2; ++i)
8149179404Sobrien    for (p = (i == 0) ? text_section_symbols : data_section_symbols;
8150179404Sobrien	 *p;
8151179404Sobrien	 ++p)
8152179404Sobrien      if (strcmp (*p, name) == 0)
8153179404Sobrien	{
8154179404Sobrien	  /* All of these symbols are given type STT_SECTION by the
8155179404Sobrien	     IRIX6 linker.  */
8156179404Sobrien	  sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
8157179404Sobrien	  sym->st_other = STO_PROTECTED;
8158179404Sobrien
8159179404Sobrien	  /* The IRIX linker puts these symbols in special sections.  */
8160179404Sobrien	  if (i == 0)
8161179404Sobrien	    sym->st_shndx = SHN_MIPS_TEXT;
8162179404Sobrien	  else
8163179404Sobrien	    sym->st_shndx = SHN_MIPS_DATA;
8164179404Sobrien
8165179404Sobrien	  break;
8166179404Sobrien	}
8167179404Sobrien}
8168179404Sobrien
8169179404Sobrien/* Finish up dynamic symbol handling.  We set the contents of various
8170179404Sobrien   dynamic sections here.  */
8171179404Sobrien
8172179404Sobrienbfd_boolean
8173179404Sobrien_bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
8174179404Sobrien				     struct bfd_link_info *info,
8175179404Sobrien				     struct elf_link_hash_entry *h,
8176179404Sobrien				     Elf_Internal_Sym *sym)
8177179404Sobrien{
8178179404Sobrien  bfd *dynobj;
8179179404Sobrien  asection *sgot;
8180179404Sobrien  struct mips_got_info *g, *gg;
8181179404Sobrien  const char *name;
8182218822Sdim  int idx;
8183218822Sdim  struct mips_elf_link_hash_table *htab;
8184179404Sobrien
8185218822Sdim  htab = mips_elf_hash_table (info);
8186179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
8187179404Sobrien
8188218822Sdim  if (h->plt.offset != MINUS_ONE)
8189179404Sobrien    {
8190179404Sobrien      asection *s;
8191218822Sdim      bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE];
8192179404Sobrien
8193179404Sobrien      /* This symbol has a stub.  Set it up.  */
8194179404Sobrien
8195179404Sobrien      BFD_ASSERT (h->dynindx != -1);
8196179404Sobrien
8197179404Sobrien      s = bfd_get_section_by_name (dynobj,
8198179404Sobrien				   MIPS_ELF_STUB_SECTION_NAME (dynobj));
8199179404Sobrien      BFD_ASSERT (s != NULL);
8200179404Sobrien
8201218822Sdim      BFD_ASSERT ((htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
8202218822Sdim                  || (h->dynindx <= 0xffff));
8203218822Sdim
8204218822Sdim      /* Values up to 2^31 - 1 are allowed.  Larger values would cause
8205218822Sdim	 sign extension at runtime in the stub, resulting in a negative
8206218822Sdim	 index value.  */
8207218822Sdim      if (h->dynindx & ~0x7fffffff)
8208179404Sobrien	return FALSE;
8209179404Sobrien
8210179404Sobrien      /* Fill the stub.  */
8211218822Sdim      idx = 0;
8212218822Sdim      bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub + idx);
8213218822Sdim      idx += 4;
8214218822Sdim      bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
8215218822Sdim      idx += 4;
8216218822Sdim      if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
8217218822Sdim        {
8218218822Sdim          bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16) & 0x7fff),
8219218822Sdim                      stub + idx);
8220218822Sdim          idx += 4;
8221218822Sdim        }
8222218822Sdim      bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
8223218822Sdim      idx += 4;
8224179404Sobrien
8225218822Sdim      /* If a large stub is not required and sign extension is not a
8226218822Sdim         problem, then use legacy code in the stub.  */
8227218822Sdim      if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
8228218822Sdim	bfd_put_32 (output_bfd, STUB_ORI (h->dynindx & 0xffff), stub + idx);
8229218822Sdim      else if (h->dynindx & ~0x7fff)
8230218822Sdim        bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
8231218822Sdim      else
8232218822Sdim        bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
8233218822Sdim		    stub + idx);
8234179404Sobrien
8235218822Sdim      BFD_ASSERT (h->plt.offset <= s->size);
8236218822Sdim      memcpy (s->contents + h->plt.offset, stub, htab->function_stub_size);
8237218822Sdim
8238179404Sobrien      /* Mark the symbol as undefined.  plt.offset != -1 occurs
8239179404Sobrien	 only for the referenced symbol.  */
8240179404Sobrien      sym->st_shndx = SHN_UNDEF;
8241179404Sobrien
8242179404Sobrien      /* The run-time linker uses the st_value field of the symbol
8243179404Sobrien	 to reset the global offset table entry for this external
8244179404Sobrien	 to its stub address when unlinking a shared object.  */
8245218822Sdim      sym->st_value = (s->output_section->vma + s->output_offset
8246218822Sdim		       + h->plt.offset);
8247179404Sobrien    }
8248179404Sobrien
8249179404Sobrien  BFD_ASSERT (h->dynindx != -1
8250218822Sdim	      || h->forced_local);
8251179404Sobrien
8252179404Sobrien  sgot = mips_elf_got_section (dynobj, FALSE);
8253179404Sobrien  BFD_ASSERT (sgot != NULL);
8254179404Sobrien  BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
8255179404Sobrien  g = mips_elf_section_data (sgot)->u.got_info;
8256179404Sobrien  BFD_ASSERT (g != NULL);
8257179404Sobrien
8258179404Sobrien  /* Run through the global symbol table, creating GOT entries for all
8259179404Sobrien     the symbols that need them.  */
8260179404Sobrien  if (g->global_gotsym != NULL
8261179404Sobrien      && h->dynindx >= g->global_gotsym->dynindx)
8262179404Sobrien    {
8263179404Sobrien      bfd_vma offset;
8264179404Sobrien      bfd_vma value;
8265179404Sobrien
8266179404Sobrien      value = sym->st_value;
8267218822Sdim      offset = mips_elf_global_got_index (dynobj, output_bfd, h, R_MIPS_GOT16, info);
8268179404Sobrien      MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
8269179404Sobrien    }
8270179404Sobrien
8271218822Sdim  if (g->next && h->dynindx != -1 && h->type != STT_TLS)
8272179404Sobrien    {
8273179404Sobrien      struct mips_got_entry e, *p;
8274179404Sobrien      bfd_vma entry;
8275179404Sobrien      bfd_vma offset;
8276179404Sobrien
8277179404Sobrien      gg = g;
8278179404Sobrien
8279179404Sobrien      e.abfd = output_bfd;
8280179404Sobrien      e.symndx = -1;
8281179404Sobrien      e.d.h = (struct mips_elf_link_hash_entry *)h;
8282218822Sdim      e.tls_type = 0;
8283179404Sobrien
8284179404Sobrien      for (g = g->next; g->next != gg; g = g->next)
8285179404Sobrien	{
8286179404Sobrien	  if (g->got_entries
8287179404Sobrien	      && (p = (struct mips_got_entry *) htab_find (g->got_entries,
8288179404Sobrien							   &e)))
8289179404Sobrien	    {
8290179404Sobrien	      offset = p->gotidx;
8291179404Sobrien	      if (info->shared
8292179404Sobrien		  || (elf_hash_table (info)->dynamic_sections_created
8293179404Sobrien		      && p->d.h != NULL
8294218822Sdim		      && p->d.h->root.def_dynamic
8295218822Sdim		      && !p->d.h->root.def_regular))
8296179404Sobrien		{
8297179404Sobrien		  /* Create an R_MIPS_REL32 relocation for this entry.  Due to
8298179404Sobrien		     the various compatibility problems, it's easier to mock
8299179404Sobrien		     up an R_MIPS_32 or R_MIPS_64 relocation and leave
8300179404Sobrien		     mips_elf_create_dynamic_relocation to calculate the
8301179404Sobrien		     appropriate addend.  */
8302179404Sobrien		  Elf_Internal_Rela rel[3];
8303179404Sobrien
8304179404Sobrien		  memset (rel, 0, sizeof (rel));
8305179404Sobrien		  if (ABI_64_P (output_bfd))
8306179404Sobrien		    rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
8307179404Sobrien		  else
8308179404Sobrien		    rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
8309179404Sobrien		  rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
8310179404Sobrien
8311179404Sobrien		  entry = 0;
8312179404Sobrien		  if (! (mips_elf_create_dynamic_relocation
8313179404Sobrien			 (output_bfd, info, rel,
8314179404Sobrien			  e.d.h, NULL, sym->st_value, &entry, sgot)))
8315179404Sobrien		    return FALSE;
8316179404Sobrien		}
8317179404Sobrien	      else
8318179404Sobrien		entry = sym->st_value;
8319179404Sobrien	      MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
8320179404Sobrien	    }
8321179404Sobrien	}
8322179404Sobrien    }
8323179404Sobrien
8324179404Sobrien  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
8325179404Sobrien  name = h->root.root.string;
8326179404Sobrien  if (strcmp (name, "_DYNAMIC") == 0
8327218822Sdim      || h == elf_hash_table (info)->hgot)
8328179404Sobrien    sym->st_shndx = SHN_ABS;
8329179404Sobrien  else if (strcmp (name, "_DYNAMIC_LINK") == 0
8330179404Sobrien	   || strcmp (name, "_DYNAMIC_LINKING") == 0)
8331179404Sobrien    {
8332179404Sobrien      sym->st_shndx = SHN_ABS;
8333179404Sobrien      sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
8334179404Sobrien      sym->st_value = 1;
8335179404Sobrien    }
8336179404Sobrien  else if (strcmp (name, "_gp_disp") == 0 && ! NEWABI_P (output_bfd))
8337179404Sobrien    {
8338179404Sobrien      sym->st_shndx = SHN_ABS;
8339179404Sobrien      sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
8340179404Sobrien      sym->st_value = elf_gp (output_bfd);
8341179404Sobrien    }
8342179404Sobrien  else if (SGI_COMPAT (output_bfd))
8343179404Sobrien    {
8344179404Sobrien      if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
8345179404Sobrien	  || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
8346179404Sobrien	{
8347179404Sobrien	  sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
8348179404Sobrien	  sym->st_other = STO_PROTECTED;
8349179404Sobrien	  sym->st_value = 0;
8350179404Sobrien	  sym->st_shndx = SHN_MIPS_DATA;
8351179404Sobrien	}
8352179404Sobrien      else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
8353179404Sobrien	{
8354179404Sobrien	  sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
8355179404Sobrien	  sym->st_other = STO_PROTECTED;
8356179404Sobrien	  sym->st_value = mips_elf_hash_table (info)->procedure_count;
8357179404Sobrien	  sym->st_shndx = SHN_ABS;
8358179404Sobrien	}
8359179404Sobrien      else if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS)
8360179404Sobrien	{
8361179404Sobrien	  if (h->type == STT_FUNC)
8362179404Sobrien	    sym->st_shndx = SHN_MIPS_TEXT;
8363179404Sobrien	  else if (h->type == STT_OBJECT)
8364179404Sobrien	    sym->st_shndx = SHN_MIPS_DATA;
8365179404Sobrien	}
8366179404Sobrien    }
8367179404Sobrien
8368179404Sobrien  /* Handle the IRIX6-specific symbols.  */
8369179404Sobrien  if (IRIX_COMPAT (output_bfd) == ict_irix6)
8370179404Sobrien    mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);
8371179404Sobrien
8372179404Sobrien  if (! info->shared)
8373179404Sobrien    {
8374179404Sobrien      if (! mips_elf_hash_table (info)->use_rld_obj_head
8375179404Sobrien	  && (strcmp (name, "__rld_map") == 0
8376179404Sobrien	      || strcmp (name, "__RLD_MAP") == 0))
8377179404Sobrien	{
8378179404Sobrien	  asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
8379179404Sobrien	  BFD_ASSERT (s != NULL);
8380179404Sobrien	  sym->st_value = s->output_section->vma + s->output_offset;
8381179404Sobrien	  bfd_put_32 (output_bfd, 0, s->contents);
8382179404Sobrien	  if (mips_elf_hash_table (info)->rld_value == 0)
8383179404Sobrien	    mips_elf_hash_table (info)->rld_value = sym->st_value;
8384179404Sobrien	}
8385179404Sobrien      else if (mips_elf_hash_table (info)->use_rld_obj_head
8386179404Sobrien	       && strcmp (name, "__rld_obj_head") == 0)
8387179404Sobrien	{
8388179404Sobrien	  /* IRIX6 does not use a .rld_map section.  */
8389179404Sobrien	  if (IRIX_COMPAT (output_bfd) == ict_irix5
8390179404Sobrien              || IRIX_COMPAT (output_bfd) == ict_none)
8391179404Sobrien	    BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map")
8392179404Sobrien			!= NULL);
8393179404Sobrien	  mips_elf_hash_table (info)->rld_value = sym->st_value;
8394179404Sobrien	}
8395179404Sobrien    }
8396179404Sobrien
8397179404Sobrien  /* If this is a mips16 symbol, force the value to be even.  */
8398218822Sdim  if (sym->st_other == STO_MIPS16)
8399218822Sdim    sym->st_value &= ~1;
8400179404Sobrien
8401179404Sobrien  return TRUE;
8402179404Sobrien}
8403179404Sobrien
8404218822Sdim/* Likewise, for VxWorks.  */
8405218822Sdim
8406218822Sdimbfd_boolean
8407218822Sdim_bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
8408218822Sdim					 struct bfd_link_info *info,
8409218822Sdim					 struct elf_link_hash_entry *h,
8410218822Sdim					 Elf_Internal_Sym *sym)
8411218822Sdim{
8412218822Sdim  bfd *dynobj;
8413218822Sdim  asection *sgot;
8414218822Sdim  struct mips_got_info *g;
8415218822Sdim  struct mips_elf_link_hash_table *htab;
8416218822Sdim
8417218822Sdim  htab = mips_elf_hash_table (info);
8418218822Sdim  dynobj = elf_hash_table (info)->dynobj;
8419218822Sdim
8420218822Sdim  if (h->plt.offset != (bfd_vma) -1)
8421218822Sdim    {
8422218822Sdim      bfd_byte *loc;
8423218822Sdim      bfd_vma plt_address, plt_index, got_address, got_offset, branch_offset;
8424218822Sdim      Elf_Internal_Rela rel;
8425218822Sdim      static const bfd_vma *plt_entry;
8426218822Sdim
8427218822Sdim      BFD_ASSERT (h->dynindx != -1);
8428218822Sdim      BFD_ASSERT (htab->splt != NULL);
8429218822Sdim      BFD_ASSERT (h->plt.offset <= htab->splt->size);
8430218822Sdim
8431218822Sdim      /* Calculate the address of the .plt entry.  */
8432218822Sdim      plt_address = (htab->splt->output_section->vma
8433218822Sdim		     + htab->splt->output_offset
8434218822Sdim		     + h->plt.offset);
8435218822Sdim
8436218822Sdim      /* Calculate the index of the entry.  */
8437218822Sdim      plt_index = ((h->plt.offset - htab->plt_header_size)
8438218822Sdim		   / htab->plt_entry_size);
8439218822Sdim
8440218822Sdim      /* Calculate the address of the .got.plt entry.  */
8441218822Sdim      got_address = (htab->sgotplt->output_section->vma
8442218822Sdim		     + htab->sgotplt->output_offset
8443218822Sdim		     + plt_index * 4);
8444218822Sdim
8445218822Sdim      /* Calculate the offset of the .got.plt entry from
8446218822Sdim	 _GLOBAL_OFFSET_TABLE_.  */
8447218822Sdim      got_offset = mips_elf_gotplt_index (info, h);
8448218822Sdim
8449218822Sdim      /* Calculate the offset for the branch at the start of the PLT
8450218822Sdim	 entry.  The branch jumps to the beginning of .plt.  */
8451218822Sdim      branch_offset = -(h->plt.offset / 4 + 1) & 0xffff;
8452218822Sdim
8453218822Sdim      /* Fill in the initial value of the .got.plt entry.  */
8454218822Sdim      bfd_put_32 (output_bfd, plt_address,
8455218822Sdim		  htab->sgotplt->contents + plt_index * 4);
8456218822Sdim
8457218822Sdim      /* Find out where the .plt entry should go.  */
8458218822Sdim      loc = htab->splt->contents + h->plt.offset;
8459218822Sdim
8460218822Sdim      if (info->shared)
8461218822Sdim	{
8462218822Sdim	  plt_entry = mips_vxworks_shared_plt_entry;
8463218822Sdim	  bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
8464218822Sdim	  bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4);
8465218822Sdim	}
8466218822Sdim      else
8467218822Sdim	{
8468218822Sdim	  bfd_vma got_address_high, got_address_low;
8469218822Sdim
8470218822Sdim	  plt_entry = mips_vxworks_exec_plt_entry;
8471218822Sdim	  got_address_high = ((got_address + 0x8000) >> 16) & 0xffff;
8472218822Sdim	  got_address_low = got_address & 0xffff;
8473218822Sdim
8474218822Sdim	  bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
8475218822Sdim	  bfd_put_32 (output_bfd, plt_entry[1] | plt_index, loc + 4);
8476218822Sdim	  bfd_put_32 (output_bfd, plt_entry[2] | got_address_high, loc + 8);
8477218822Sdim	  bfd_put_32 (output_bfd, plt_entry[3] | got_address_low, loc + 12);
8478218822Sdim	  bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
8479218822Sdim	  bfd_put_32 (output_bfd, plt_entry[5], loc + 20);
8480218822Sdim	  bfd_put_32 (output_bfd, plt_entry[6], loc + 24);
8481218822Sdim	  bfd_put_32 (output_bfd, plt_entry[7], loc + 28);
8482218822Sdim
8483218822Sdim	  loc = (htab->srelplt2->contents
8484218822Sdim		 + (plt_index * 3 + 2) * sizeof (Elf32_External_Rela));
8485218822Sdim
8486218822Sdim	  /* Emit a relocation for the .got.plt entry.  */
8487218822Sdim	  rel.r_offset = got_address;
8488218822Sdim	  rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32);
8489218822Sdim	  rel.r_addend = h->plt.offset;
8490218822Sdim	  bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8491218822Sdim
8492218822Sdim	  /* Emit a relocation for the lui of %hi(<.got.plt slot>).  */
8493218822Sdim	  loc += sizeof (Elf32_External_Rela);
8494218822Sdim	  rel.r_offset = plt_address + 8;
8495218822Sdim	  rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
8496218822Sdim	  rel.r_addend = got_offset;
8497218822Sdim	  bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8498218822Sdim
8499218822Sdim	  /* Emit a relocation for the addiu of %lo(<.got.plt slot>).  */
8500218822Sdim	  loc += sizeof (Elf32_External_Rela);
8501218822Sdim	  rel.r_offset += 4;
8502218822Sdim	  rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
8503218822Sdim	  bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8504218822Sdim	}
8505218822Sdim
8506218822Sdim      /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
8507218822Sdim      loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rela);
8508218822Sdim      rel.r_offset = got_address;
8509218822Sdim      rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT);
8510218822Sdim      rel.r_addend = 0;
8511218822Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8512218822Sdim
8513218822Sdim      if (!h->def_regular)
8514218822Sdim	sym->st_shndx = SHN_UNDEF;
8515218822Sdim    }
8516218822Sdim
8517218822Sdim  BFD_ASSERT (h->dynindx != -1 || h->forced_local);
8518218822Sdim
8519218822Sdim  sgot = mips_elf_got_section (dynobj, FALSE);
8520218822Sdim  BFD_ASSERT (sgot != NULL);
8521218822Sdim  BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
8522218822Sdim  g = mips_elf_section_data (sgot)->u.got_info;
8523218822Sdim  BFD_ASSERT (g != NULL);
8524218822Sdim
8525218822Sdim  /* See if this symbol has an entry in the GOT.  */
8526218822Sdim  if (g->global_gotsym != NULL
8527218822Sdim      && h->dynindx >= g->global_gotsym->dynindx)
8528218822Sdim    {
8529218822Sdim      bfd_vma offset;
8530218822Sdim      Elf_Internal_Rela outrel;
8531218822Sdim      bfd_byte *loc;
8532218822Sdim      asection *s;
8533218822Sdim
8534218822Sdim      /* Install the symbol value in the GOT.   */
8535218822Sdim      offset = mips_elf_global_got_index (dynobj, output_bfd, h,
8536218822Sdim					  R_MIPS_GOT16, info);
8537218822Sdim      MIPS_ELF_PUT_WORD (output_bfd, sym->st_value, sgot->contents + offset);
8538218822Sdim
8539218822Sdim      /* Add a dynamic relocation for it.  */
8540218822Sdim      s = mips_elf_rel_dyn_section (info, FALSE);
8541218822Sdim      loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
8542218822Sdim      outrel.r_offset = (sgot->output_section->vma
8543218822Sdim			 + sgot->output_offset
8544218822Sdim			 + offset);
8545218822Sdim      outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_32);
8546218822Sdim      outrel.r_addend = 0;
8547218822Sdim      bfd_elf32_swap_reloca_out (dynobj, &outrel, loc);
8548218822Sdim    }
8549218822Sdim
8550218822Sdim  /* Emit a copy reloc, if needed.  */
8551218822Sdim  if (h->needs_copy)
8552218822Sdim    {
8553218822Sdim      Elf_Internal_Rela rel;
8554218822Sdim
8555218822Sdim      BFD_ASSERT (h->dynindx != -1);
8556218822Sdim
8557218822Sdim      rel.r_offset = (h->root.u.def.section->output_section->vma
8558218822Sdim		      + h->root.u.def.section->output_offset
8559218822Sdim		      + h->root.u.def.value);
8560218822Sdim      rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY);
8561218822Sdim      rel.r_addend = 0;
8562218822Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rel,
8563218822Sdim				 htab->srelbss->contents
8564218822Sdim				 + (htab->srelbss->reloc_count
8565218822Sdim				    * sizeof (Elf32_External_Rela)));
8566218822Sdim      ++htab->srelbss->reloc_count;
8567218822Sdim    }
8568218822Sdim
8569218822Sdim  /* If this is a mips16 symbol, force the value to be even.  */
8570218822Sdim  if (sym->st_other == STO_MIPS16)
8571218822Sdim    sym->st_value &= ~1;
8572218822Sdim
8573218822Sdim  return TRUE;
8574218822Sdim}
8575218822Sdim
8576218822Sdim/* Install the PLT header for a VxWorks executable and finalize the
8577218822Sdim   contents of .rela.plt.unloaded.  */
8578218822Sdim
8579218822Sdimstatic void
8580218822Sdimmips_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
8581218822Sdim{
8582218822Sdim  Elf_Internal_Rela rela;
8583218822Sdim  bfd_byte *loc;
8584218822Sdim  bfd_vma got_value, got_value_high, got_value_low, plt_address;
8585218822Sdim  static const bfd_vma *plt_entry;
8586218822Sdim  struct mips_elf_link_hash_table *htab;
8587218822Sdim
8588218822Sdim  htab = mips_elf_hash_table (info);
8589218822Sdim  plt_entry = mips_vxworks_exec_plt0_entry;
8590218822Sdim
8591218822Sdim  /* Calculate the value of _GLOBAL_OFFSET_TABLE_.  */
8592218822Sdim  got_value = (htab->root.hgot->root.u.def.section->output_section->vma
8593218822Sdim	       + htab->root.hgot->root.u.def.section->output_offset
8594218822Sdim	       + htab->root.hgot->root.u.def.value);
8595218822Sdim
8596218822Sdim  got_value_high = ((got_value + 0x8000) >> 16) & 0xffff;
8597218822Sdim  got_value_low = got_value & 0xffff;
8598218822Sdim
8599218822Sdim  /* Calculate the address of the PLT header.  */
8600218822Sdim  plt_address = htab->splt->output_section->vma + htab->splt->output_offset;
8601218822Sdim
8602218822Sdim  /* Install the PLT header.  */
8603218822Sdim  loc = htab->splt->contents;
8604218822Sdim  bfd_put_32 (output_bfd, plt_entry[0] | got_value_high, loc);
8605218822Sdim  bfd_put_32 (output_bfd, plt_entry[1] | got_value_low, loc + 4);
8606218822Sdim  bfd_put_32 (output_bfd, plt_entry[2], loc + 8);
8607218822Sdim  bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
8608218822Sdim  bfd_put_32 (output_bfd, plt_entry[4], loc + 16);
8609218822Sdim  bfd_put_32 (output_bfd, plt_entry[5], loc + 20);
8610218822Sdim
8611218822Sdim  /* Output the relocation for the lui of %hi(_GLOBAL_OFFSET_TABLE_).  */
8612218822Sdim  loc = htab->srelplt2->contents;
8613218822Sdim  rela.r_offset = plt_address;
8614218822Sdim  rela.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
8615218822Sdim  rela.r_addend = 0;
8616218822Sdim  bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
8617218822Sdim  loc += sizeof (Elf32_External_Rela);
8618218822Sdim
8619218822Sdim  /* Output the relocation for the following addiu of
8620218822Sdim     %lo(_GLOBAL_OFFSET_TABLE_).  */
8621218822Sdim  rela.r_offset += 4;
8622218822Sdim  rela.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
8623218822Sdim  bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
8624218822Sdim  loc += sizeof (Elf32_External_Rela);
8625218822Sdim
8626218822Sdim  /* Fix up the remaining relocations.  They may have the wrong
8627218822Sdim     symbol index for _G_O_T_ or _P_L_T_ depending on the order
8628218822Sdim     in which symbols were output.  */
8629218822Sdim  while (loc < htab->srelplt2->contents + htab->srelplt2->size)
8630218822Sdim    {
8631218822Sdim      Elf_Internal_Rela rel;
8632218822Sdim
8633218822Sdim      bfd_elf32_swap_reloca_in (output_bfd, loc, &rel);
8634218822Sdim      rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_MIPS_32);
8635218822Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8636218822Sdim      loc += sizeof (Elf32_External_Rela);
8637218822Sdim
8638218822Sdim      bfd_elf32_swap_reloca_in (output_bfd, loc, &rel);
8639218822Sdim      rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_HI16);
8640218822Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8641218822Sdim      loc += sizeof (Elf32_External_Rela);
8642218822Sdim
8643218822Sdim      bfd_elf32_swap_reloca_in (output_bfd, loc, &rel);
8644218822Sdim      rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_MIPS_LO16);
8645218822Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
8646218822Sdim      loc += sizeof (Elf32_External_Rela);
8647218822Sdim    }
8648218822Sdim}
8649218822Sdim
8650218822Sdim/* Install the PLT header for a VxWorks shared library.  */
8651218822Sdim
8652218822Sdimstatic void
8653218822Sdimmips_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info)
8654218822Sdim{
8655218822Sdim  unsigned int i;
8656218822Sdim  struct mips_elf_link_hash_table *htab;
8657218822Sdim
8658218822Sdim  htab = mips_elf_hash_table (info);
8659218822Sdim
8660218822Sdim  /* We just need to copy the entry byte-by-byte.  */
8661218822Sdim  for (i = 0; i < ARRAY_SIZE (mips_vxworks_shared_plt0_entry); i++)
8662218822Sdim    bfd_put_32 (output_bfd, mips_vxworks_shared_plt0_entry[i],
8663218822Sdim		htab->splt->contents + i * 4);
8664218822Sdim}
8665218822Sdim
8666179404Sobrien/* Finish up the dynamic sections.  */
8667179404Sobrien
8668179404Sobrienbfd_boolean
8669179404Sobrien_bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
8670179404Sobrien				       struct bfd_link_info *info)
8671179404Sobrien{
8672179404Sobrien  bfd *dynobj;
8673179404Sobrien  asection *sdyn;
8674179404Sobrien  asection *sgot;
8675179404Sobrien  struct mips_got_info *gg, *g;
8676218822Sdim  struct mips_elf_link_hash_table *htab;
8677179404Sobrien
8678218822Sdim  htab = mips_elf_hash_table (info);
8679179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
8680179404Sobrien
8681179404Sobrien  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
8682179404Sobrien
8683179404Sobrien  sgot = mips_elf_got_section (dynobj, FALSE);
8684179404Sobrien  if (sgot == NULL)
8685179404Sobrien    gg = g = NULL;
8686179404Sobrien  else
8687179404Sobrien    {
8688179404Sobrien      BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
8689179404Sobrien      gg = mips_elf_section_data (sgot)->u.got_info;
8690179404Sobrien      BFD_ASSERT (gg != NULL);
8691179404Sobrien      g = mips_elf_got_for_ibfd (gg, output_bfd);
8692179404Sobrien      BFD_ASSERT (g != NULL);
8693179404Sobrien    }
8694179404Sobrien
8695179404Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
8696179404Sobrien    {
8697179404Sobrien      bfd_byte *b;
8698218822Sdim      int dyn_to_skip = 0, dyn_skipped = 0;
8699179404Sobrien
8700179404Sobrien      BFD_ASSERT (sdyn != NULL);
8701179404Sobrien      BFD_ASSERT (g != NULL);
8702179404Sobrien
8703179404Sobrien      for (b = sdyn->contents;
8704218822Sdim	   b < sdyn->contents + sdyn->size;
8705179404Sobrien	   b += MIPS_ELF_DYN_SIZE (dynobj))
8706179404Sobrien	{
8707179404Sobrien	  Elf_Internal_Dyn dyn;
8708179404Sobrien	  const char *name;
8709179404Sobrien	  size_t elemsize;
8710179404Sobrien	  asection *s;
8711179404Sobrien	  bfd_boolean swap_out_p;
8712179404Sobrien
8713179404Sobrien	  /* Read in the current dynamic entry.  */
8714179404Sobrien	  (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
8715179404Sobrien
8716179404Sobrien	  /* Assume that we're going to modify it and write it out.  */
8717179404Sobrien	  swap_out_p = TRUE;
8718179404Sobrien
8719179404Sobrien	  switch (dyn.d_tag)
8720179404Sobrien	    {
8721179404Sobrien	    case DT_RELENT:
8722179404Sobrien	      dyn.d_un.d_val = MIPS_ELF_REL_SIZE (dynobj);
8723179404Sobrien	      break;
8724179404Sobrien
8725218822Sdim	    case DT_RELAENT:
8726218822Sdim	      BFD_ASSERT (htab->is_vxworks);
8727218822Sdim	      dyn.d_un.d_val = MIPS_ELF_RELA_SIZE (dynobj);
8728218822Sdim	      break;
8729218822Sdim
8730179404Sobrien	    case DT_STRSZ:
8731179404Sobrien	      /* Rewrite DT_STRSZ.  */
8732179404Sobrien	      dyn.d_un.d_val =
8733179404Sobrien		_bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
8734179404Sobrien	      break;
8735179404Sobrien
8736179404Sobrien	    case DT_PLTGOT:
8737179404Sobrien	      name = ".got";
8738218822Sdim	      if (htab->is_vxworks)
8739218822Sdim		{
8740218822Sdim		  /* _GLOBAL_OFFSET_TABLE_ is defined to be the beginning
8741218822Sdim		     of the ".got" section in DYNOBJ.  */
8742218822Sdim		  s = bfd_get_section_by_name (dynobj, name);
8743218822Sdim		  BFD_ASSERT (s != NULL);
8744218822Sdim		  dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
8745218822Sdim		}
8746218822Sdim	      else
8747218822Sdim		{
8748218822Sdim		  s = bfd_get_section_by_name (output_bfd, name);
8749218822Sdim		  BFD_ASSERT (s != NULL);
8750218822Sdim		  dyn.d_un.d_ptr = s->vma;
8751218822Sdim		}
8752179404Sobrien	      break;
8753179404Sobrien
8754179404Sobrien	    case DT_MIPS_RLD_VERSION:
8755179404Sobrien	      dyn.d_un.d_val = 1; /* XXX */
8756179404Sobrien	      break;
8757179404Sobrien
8758179404Sobrien	    case DT_MIPS_FLAGS:
8759179404Sobrien	      dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
8760179404Sobrien	      break;
8761179404Sobrien
8762179404Sobrien	    case DT_MIPS_TIME_STAMP:
8763218822Sdim	      {
8764218822Sdim		time_t t;
8765218822Sdim		time (&t);
8766218822Sdim		dyn.d_un.d_val = t;
8767218822Sdim	      }
8768179404Sobrien	      break;
8769179404Sobrien
8770179404Sobrien	    case DT_MIPS_ICHECKSUM:
8771179404Sobrien	      /* XXX FIXME: */
8772179404Sobrien	      swap_out_p = FALSE;
8773179404Sobrien	      break;
8774179404Sobrien
8775179404Sobrien	    case DT_MIPS_IVERSION:
8776179404Sobrien	      /* XXX FIXME: */
8777179404Sobrien	      swap_out_p = FALSE;
8778179404Sobrien	      break;
8779179404Sobrien
8780179404Sobrien	    case DT_MIPS_BASE_ADDRESS:
8781179404Sobrien	      s = output_bfd->sections;
8782179404Sobrien	      BFD_ASSERT (s != NULL);
8783179404Sobrien	      dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
8784179404Sobrien	      break;
8785179404Sobrien
8786179404Sobrien	    case DT_MIPS_LOCAL_GOTNO:
8787179404Sobrien	      dyn.d_un.d_val = g->local_gotno;
8788179404Sobrien	      break;
8789179404Sobrien
8790179404Sobrien	    case DT_MIPS_UNREFEXTNO:
8791179404Sobrien	      /* The index into the dynamic symbol table which is the
8792179404Sobrien		 entry of the first external symbol that is not
8793179404Sobrien		 referenced within the same object.  */
8794179404Sobrien	      dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
8795179404Sobrien	      break;
8796179404Sobrien
8797179404Sobrien	    case DT_MIPS_GOTSYM:
8798179404Sobrien	      if (gg->global_gotsym)
8799179404Sobrien		{
8800179404Sobrien		  dyn.d_un.d_val = gg->global_gotsym->dynindx;
8801179404Sobrien		  break;
8802179404Sobrien		}
8803179404Sobrien	      /* In case if we don't have global got symbols we default
8804179404Sobrien		 to setting DT_MIPS_GOTSYM to the same value as
8805179404Sobrien		 DT_MIPS_SYMTABNO, so we just fall through.  */
8806179404Sobrien
8807179404Sobrien	    case DT_MIPS_SYMTABNO:
8808179404Sobrien	      name = ".dynsym";
8809179404Sobrien	      elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
8810179404Sobrien	      s = bfd_get_section_by_name (output_bfd, name);
8811179404Sobrien	      BFD_ASSERT (s != NULL);
8812179404Sobrien
8813218822Sdim	      dyn.d_un.d_val = s->size / elemsize;
8814179404Sobrien	      break;
8815179404Sobrien
8816179404Sobrien	    case DT_MIPS_HIPAGENO:
8817218822Sdim	      dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO (info);
8818179404Sobrien	      break;
8819179404Sobrien
8820179404Sobrien	    case DT_MIPS_RLD_MAP:
8821179404Sobrien	      dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value;
8822179404Sobrien	      break;
8823179404Sobrien
8824179404Sobrien	    case DT_MIPS_OPTIONS:
8825179404Sobrien	      s = (bfd_get_section_by_name
8826179404Sobrien		   (output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
8827179404Sobrien	      dyn.d_un.d_ptr = s->vma;
8828179404Sobrien	      break;
8829179404Sobrien
8830218822Sdim	    case DT_RELASZ:
8831218822Sdim	      BFD_ASSERT (htab->is_vxworks);
8832218822Sdim	      /* The count does not include the JUMP_SLOT relocations.  */
8833218822Sdim	      if (htab->srelplt)
8834218822Sdim		dyn.d_un.d_val -= htab->srelplt->size;
8835179404Sobrien	      break;
8836179404Sobrien
8837218822Sdim	    case DT_PLTREL:
8838218822Sdim	      BFD_ASSERT (htab->is_vxworks);
8839218822Sdim	      dyn.d_un.d_val = DT_RELA;
8840218822Sdim	      break;
8841218822Sdim
8842218822Sdim	    case DT_PLTRELSZ:
8843218822Sdim	      BFD_ASSERT (htab->is_vxworks);
8844218822Sdim	      dyn.d_un.d_val = htab->srelplt->size;
8845218822Sdim	      break;
8846218822Sdim
8847218822Sdim	    case DT_JMPREL:
8848218822Sdim	      BFD_ASSERT (htab->is_vxworks);
8849218822Sdim	      dyn.d_un.d_val = (htab->srelplt->output_section->vma
8850218822Sdim				+ htab->srelplt->output_offset);
8851218822Sdim	      break;
8852218822Sdim
8853218822Sdim	    case DT_TEXTREL:
8854218822Sdim	      /* If we didn't need any text relocations after all, delete
8855218822Sdim		 the dynamic tag.  */
8856218822Sdim	      if (!(info->flags & DF_TEXTREL))
8857218822Sdim		{
8858218822Sdim		  dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj);
8859218822Sdim		  swap_out_p = FALSE;
8860218822Sdim		}
8861218822Sdim	      break;
8862218822Sdim
8863218822Sdim	    case DT_FLAGS:
8864218822Sdim	      /* If we didn't need any text relocations after all, clear
8865218822Sdim		 DF_TEXTREL from DT_FLAGS.  */
8866218822Sdim	      if (!(info->flags & DF_TEXTREL))
8867218822Sdim		dyn.d_un.d_val &= ~DF_TEXTREL;
8868218822Sdim	      else
8869218822Sdim		swap_out_p = FALSE;
8870218822Sdim	      break;
8871218822Sdim
8872179404Sobrien	    default:
8873179404Sobrien	      swap_out_p = FALSE;
8874179404Sobrien	      break;
8875179404Sobrien	    }
8876179404Sobrien
8877218822Sdim	  if (swap_out_p || dyn_skipped)
8878179404Sobrien	    (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
8879218822Sdim	      (dynobj, &dyn, b - dyn_skipped);
8880218822Sdim
8881218822Sdim	  if (dyn_to_skip)
8882218822Sdim	    {
8883218822Sdim	      dyn_skipped += dyn_to_skip;
8884218822Sdim	      dyn_to_skip = 0;
8885218822Sdim	    }
8886179404Sobrien	}
8887218822Sdim
8888218822Sdim      /* Wipe out any trailing entries if we shifted down a dynamic tag.  */
8889218822Sdim      if (dyn_skipped > 0)
8890218822Sdim	memset (b - dyn_skipped, 0, dyn_skipped);
8891179404Sobrien    }
8892179404Sobrien
8893218822Sdim  if (sgot != NULL && sgot->size > 0)
8894179404Sobrien    {
8895218822Sdim      if (htab->is_vxworks)
8896218822Sdim	{
8897218822Sdim	  /* The first entry of the global offset table points to the
8898218822Sdim	     ".dynamic" section.  The second is initialized by the
8899218822Sdim	     loader and contains the shared library identifier.
8900218822Sdim	     The third is also initialized by the loader and points
8901218822Sdim	     to the lazy resolution stub.  */
8902218822Sdim	  MIPS_ELF_PUT_WORD (output_bfd,
8903218822Sdim			     sdyn->output_offset + sdyn->output_section->vma,
8904218822Sdim			     sgot->contents);
8905218822Sdim	  MIPS_ELF_PUT_WORD (output_bfd, 0,
8906218822Sdim			     sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
8907218822Sdim	  MIPS_ELF_PUT_WORD (output_bfd, 0,
8908218822Sdim			     sgot->contents
8909218822Sdim			     + 2 * MIPS_ELF_GOT_SIZE (output_bfd));
8910218822Sdim	}
8911218822Sdim      else
8912218822Sdim	{
8913218822Sdim	  /* The first entry of the global offset table will be filled at
8914218822Sdim	     runtime. The second entry will be used by some runtime loaders.
8915218822Sdim	     This isn't the case of IRIX rld.  */
8916218822Sdim	  MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
8917218822Sdim	  MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
8918218822Sdim			     sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
8919218822Sdim	}
8920218822Sdim
8921218822Sdim      elf_section_data (sgot->output_section)->this_hdr.sh_entsize
8922218822Sdim	 = MIPS_ELF_GOT_SIZE (output_bfd);
8923179404Sobrien    }
8924179404Sobrien
8925179404Sobrien  /* Generate dynamic relocations for the non-primary gots.  */
8926179404Sobrien  if (gg != NULL && gg->next)
8927179404Sobrien    {
8928179404Sobrien      Elf_Internal_Rela rel[3];
8929179404Sobrien      bfd_vma addend = 0;
8930179404Sobrien
8931179404Sobrien      memset (rel, 0, sizeof (rel));
8932179404Sobrien      rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);
8933179404Sobrien
8934179404Sobrien      for (g = gg->next; g->next != gg; g = g->next)
8935179404Sobrien	{
8936218822Sdim	  bfd_vma index = g->next->local_gotno + g->next->global_gotno
8937218822Sdim	    + g->next->tls_gotno;
8938179404Sobrien
8939179404Sobrien	  MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents
8940179404Sobrien			     + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
8941179404Sobrien	  MIPS_ELF_PUT_WORD (output_bfd, 0x80000000, sgot->contents
8942179404Sobrien			     + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
8943179404Sobrien
8944179404Sobrien	  if (! info->shared)
8945179404Sobrien	    continue;
8946179404Sobrien
8947179404Sobrien	  while (index < g->assigned_gotno)
8948179404Sobrien	    {
8949179404Sobrien	      rel[0].r_offset = rel[1].r_offset = rel[2].r_offset
8950179404Sobrien		= index++ * MIPS_ELF_GOT_SIZE (output_bfd);
8951179404Sobrien	      if (!(mips_elf_create_dynamic_relocation
8952179404Sobrien		    (output_bfd, info, rel, NULL,
8953179404Sobrien		     bfd_abs_section_ptr,
8954179404Sobrien		     0, &addend, sgot)))
8955179404Sobrien		return FALSE;
8956179404Sobrien	      BFD_ASSERT (addend == 0);
8957179404Sobrien	    }
8958179404Sobrien	}
8959179404Sobrien    }
8960179404Sobrien
8961218822Sdim  /* The generation of dynamic relocations for the non-primary gots
8962218822Sdim     adds more dynamic relocations.  We cannot count them until
8963218822Sdim     here.  */
8964218822Sdim
8965218822Sdim  if (elf_hash_table (info)->dynamic_sections_created)
8966218822Sdim    {
8967218822Sdim      bfd_byte *b;
8968218822Sdim      bfd_boolean swap_out_p;
8969218822Sdim
8970218822Sdim      BFD_ASSERT (sdyn != NULL);
8971218822Sdim
8972218822Sdim      for (b = sdyn->contents;
8973218822Sdim	   b < sdyn->contents + sdyn->size;
8974218822Sdim	   b += MIPS_ELF_DYN_SIZE (dynobj))
8975218822Sdim	{
8976218822Sdim	  Elf_Internal_Dyn dyn;
8977218822Sdim	  asection *s;
8978218822Sdim
8979218822Sdim	  /* Read in the current dynamic entry.  */
8980218822Sdim	  (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
8981218822Sdim
8982218822Sdim	  /* Assume that we're going to modify it and write it out.  */
8983218822Sdim	  swap_out_p = TRUE;
8984218822Sdim
8985218822Sdim	  switch (dyn.d_tag)
8986218822Sdim	    {
8987218822Sdim	    case DT_RELSZ:
8988218822Sdim	      /* Reduce DT_RELSZ to account for any relocations we
8989218822Sdim		 decided not to make.  This is for the n64 irix rld,
8990218822Sdim		 which doesn't seem to apply any relocations if there
8991218822Sdim		 are trailing null entries.  */
8992218822Sdim	      s = mips_elf_rel_dyn_section (info, FALSE);
8993218822Sdim	      dyn.d_un.d_val = (s->reloc_count
8994218822Sdim				* (ABI_64_P (output_bfd)
8995218822Sdim				   ? sizeof (Elf64_Mips_External_Rel)
8996218822Sdim				   : sizeof (Elf32_External_Rel)));
8997218822Sdim	      /* Adjust the section size too.  Tools like the prelinker
8998218822Sdim		 can reasonably expect the values to the same.  */
8999218822Sdim	      elf_section_data (s->output_section)->this_hdr.sh_size
9000218822Sdim		= dyn.d_un.d_val;
9001218822Sdim	      break;
9002218822Sdim
9003218822Sdim	    default:
9004218822Sdim	      swap_out_p = FALSE;
9005218822Sdim	      break;
9006218822Sdim	    }
9007218822Sdim
9008218822Sdim	  if (swap_out_p)
9009218822Sdim	    (*get_elf_backend_data (dynobj)->s->swap_dyn_out)
9010218822Sdim	      (dynobj, &dyn, b);
9011218822Sdim	}
9012218822Sdim    }
9013218822Sdim
9014179404Sobrien  {
9015179404Sobrien    asection *s;
9016179404Sobrien    Elf32_compact_rel cpt;
9017179404Sobrien
9018179404Sobrien    if (SGI_COMPAT (output_bfd))
9019179404Sobrien      {
9020179404Sobrien	/* Write .compact_rel section out.  */
9021179404Sobrien	s = bfd_get_section_by_name (dynobj, ".compact_rel");
9022179404Sobrien	if (s != NULL)
9023179404Sobrien	  {
9024179404Sobrien	    cpt.id1 = 1;
9025179404Sobrien	    cpt.num = s->reloc_count;
9026179404Sobrien	    cpt.id2 = 2;
9027179404Sobrien	    cpt.offset = (s->output_section->filepos
9028179404Sobrien			  + sizeof (Elf32_External_compact_rel));
9029179404Sobrien	    cpt.reserved0 = 0;
9030179404Sobrien	    cpt.reserved1 = 0;
9031179404Sobrien	    bfd_elf32_swap_compact_rel_out (output_bfd, &cpt,
9032179404Sobrien					    ((Elf32_External_compact_rel *)
9033179404Sobrien					     s->contents));
9034179404Sobrien
9035179404Sobrien	    /* Clean up a dummy stub function entry in .text.  */
9036179404Sobrien	    s = bfd_get_section_by_name (dynobj,
9037179404Sobrien					 MIPS_ELF_STUB_SECTION_NAME (dynobj));
9038179404Sobrien	    if (s != NULL)
9039179404Sobrien	      {
9040179404Sobrien		file_ptr dummy_offset;
9041179404Sobrien
9042218822Sdim		BFD_ASSERT (s->size >= htab->function_stub_size);
9043218822Sdim		dummy_offset = s->size - htab->function_stub_size;
9044179404Sobrien		memset (s->contents + dummy_offset, 0,
9045218822Sdim			htab->function_stub_size);
9046179404Sobrien	      }
9047179404Sobrien	  }
9048179404Sobrien      }
9049179404Sobrien
9050218822Sdim    /* The psABI says that the dynamic relocations must be sorted in
9051218822Sdim       increasing order of r_symndx.  The VxWorks EABI doesn't require
9052218822Sdim       this, and because the code below handles REL rather than RELA
9053218822Sdim       relocations, using it for VxWorks would be outright harmful.  */
9054218822Sdim    if (!htab->is_vxworks)
9055179404Sobrien      {
9056218822Sdim	s = mips_elf_rel_dyn_section (info, FALSE);
9057218822Sdim	if (s != NULL
9058218822Sdim	    && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
9059218822Sdim	  {
9060218822Sdim	    reldyn_sorting_bfd = output_bfd;
9061179404Sobrien
9062218822Sdim	    if (ABI_64_P (output_bfd))
9063218822Sdim	      qsort ((Elf64_External_Rel *) s->contents + 1,
9064218822Sdim		     s->reloc_count - 1, sizeof (Elf64_Mips_External_Rel),
9065218822Sdim		     sort_dynamic_relocs_64);
9066218822Sdim	    else
9067218822Sdim	      qsort ((Elf32_External_Rel *) s->contents + 1,
9068218822Sdim		     s->reloc_count - 1, sizeof (Elf32_External_Rel),
9069218822Sdim		     sort_dynamic_relocs);
9070218822Sdim	  }
9071179404Sobrien      }
9072179404Sobrien  }
9073179404Sobrien
9074218822Sdim  if (htab->is_vxworks && htab->splt->size > 0)
9075218822Sdim    {
9076218822Sdim      if (info->shared)
9077218822Sdim	mips_vxworks_finish_shared_plt (output_bfd, info);
9078218822Sdim      else
9079218822Sdim	mips_vxworks_finish_exec_plt (output_bfd, info);
9080218822Sdim    }
9081179404Sobrien  return TRUE;
9082179404Sobrien}
9083179404Sobrien
9084179404Sobrien
9085179404Sobrien/* Set ABFD's EF_MIPS_ARCH and EF_MIPS_MACH flags.  */
9086179404Sobrien
9087179404Sobrienstatic void
9088179404Sobrienmips_set_isa_flags (bfd *abfd)
9089179404Sobrien{
9090179404Sobrien  flagword val;
9091179404Sobrien
9092179404Sobrien  switch (bfd_get_mach (abfd))
9093179404Sobrien    {
9094179404Sobrien    default:
9095179404Sobrien    case bfd_mach_mips3000:
9096179404Sobrien      val = E_MIPS_ARCH_1;
9097179404Sobrien      break;
9098179404Sobrien
9099179404Sobrien    case bfd_mach_mips3900:
9100179404Sobrien      val = E_MIPS_ARCH_1 | E_MIPS_MACH_3900;
9101179404Sobrien      break;
9102179404Sobrien
9103179404Sobrien    case bfd_mach_mips6000:
9104179404Sobrien      val = E_MIPS_ARCH_2;
9105179404Sobrien      break;
9106179404Sobrien
9107179404Sobrien    case bfd_mach_mips4000:
9108179404Sobrien    case bfd_mach_mips4300:
9109179404Sobrien    case bfd_mach_mips4400:
9110179404Sobrien    case bfd_mach_mips4600:
9111179404Sobrien      val = E_MIPS_ARCH_3;
9112179404Sobrien      break;
9113179404Sobrien
9114179404Sobrien    case bfd_mach_mips4010:
9115179404Sobrien      val = E_MIPS_ARCH_3 | E_MIPS_MACH_4010;
9116179404Sobrien      break;
9117179404Sobrien
9118179404Sobrien    case bfd_mach_mips4100:
9119179404Sobrien      val = E_MIPS_ARCH_3 | E_MIPS_MACH_4100;
9120179404Sobrien      break;
9121179404Sobrien
9122179404Sobrien    case bfd_mach_mips4111:
9123179404Sobrien      val = E_MIPS_ARCH_3 | E_MIPS_MACH_4111;
9124179404Sobrien      break;
9125179404Sobrien
9126179404Sobrien    case bfd_mach_mips4120:
9127179404Sobrien      val = E_MIPS_ARCH_3 | E_MIPS_MACH_4120;
9128179404Sobrien      break;
9129179404Sobrien
9130179404Sobrien    case bfd_mach_mips4650:
9131179404Sobrien      val = E_MIPS_ARCH_3 | E_MIPS_MACH_4650;
9132179404Sobrien      break;
9133179404Sobrien
9134179404Sobrien    case bfd_mach_mips5400:
9135179404Sobrien      val = E_MIPS_ARCH_4 | E_MIPS_MACH_5400;
9136179404Sobrien      break;
9137179404Sobrien
9138179404Sobrien    case bfd_mach_mips5500:
9139179404Sobrien      val = E_MIPS_ARCH_4 | E_MIPS_MACH_5500;
9140179404Sobrien      break;
9141179404Sobrien
9142208737Sjmallett    case bfd_mach_mips9000:
9143208737Sjmallett      val = E_MIPS_ARCH_4 | E_MIPS_MACH_9000;
9144208737Sjmallett      break;
9145208737Sjmallett
9146179404Sobrien    case bfd_mach_mips5000:
9147179404Sobrien    case bfd_mach_mips7000:
9148179404Sobrien    case bfd_mach_mips8000:
9149179404Sobrien    case bfd_mach_mips10000:
9150179404Sobrien    case bfd_mach_mips12000:
9151179404Sobrien      val = E_MIPS_ARCH_4;
9152179404Sobrien      break;
9153179404Sobrien
9154179404Sobrien    case bfd_mach_mips5:
9155179404Sobrien      val = E_MIPS_ARCH_5;
9156179404Sobrien      break;
9157179404Sobrien
9158208737Sjmallett    case bfd_mach_mips_octeon:
9159208737Sjmallett      val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON;
9160208737Sjmallett      break;
9161208737Sjmallett
9162179404Sobrien    case bfd_mach_mips_sb1:
9163179404Sobrien      val = E_MIPS_ARCH_64 | E_MIPS_MACH_SB1;
9164179404Sobrien      break;
9165179404Sobrien
9166179404Sobrien    case bfd_mach_mipsisa32:
9167179404Sobrien      val = E_MIPS_ARCH_32;
9168179404Sobrien      break;
9169179404Sobrien
9170179404Sobrien    case bfd_mach_mipsisa64:
9171179404Sobrien      val = E_MIPS_ARCH_64;
9172179404Sobrien      break;
9173179404Sobrien
9174179404Sobrien    case bfd_mach_mipsisa32r2:
9175179404Sobrien      val = E_MIPS_ARCH_32R2;
9176179404Sobrien      break;
9177179404Sobrien
9178179404Sobrien    case bfd_mach_mipsisa64r2:
9179179404Sobrien      val = E_MIPS_ARCH_64R2;
9180179404Sobrien      break;
9181179404Sobrien    }
9182179404Sobrien  elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
9183179404Sobrien  elf_elfheader (abfd)->e_flags |= val;
9184179404Sobrien
9185179404Sobrien}
9186179404Sobrien
9187179404Sobrien
9188179404Sobrien/* The final processing done just before writing out a MIPS ELF object
9189179404Sobrien   file.  This gets the MIPS architecture right based on the machine
9190179404Sobrien   number.  This is used by both the 32-bit and the 64-bit ABI.  */
9191179404Sobrien
9192179404Sobrienvoid
9193179404Sobrien_bfd_mips_elf_final_write_processing (bfd *abfd,
9194179404Sobrien				      bfd_boolean linker ATTRIBUTE_UNUSED)
9195179404Sobrien{
9196179404Sobrien  unsigned int i;
9197179404Sobrien  Elf_Internal_Shdr **hdrpp;
9198179404Sobrien  const char *name;
9199179404Sobrien  asection *sec;
9200179404Sobrien
9201179404Sobrien  /* Keep the existing EF_MIPS_MACH and EF_MIPS_ARCH flags if the former
9202179404Sobrien     is nonzero.  This is for compatibility with old objects, which used
9203179404Sobrien     a combination of a 32-bit EF_MIPS_ARCH and a 64-bit EF_MIPS_MACH.  */
9204179404Sobrien  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_MACH) == 0)
9205179404Sobrien    mips_set_isa_flags (abfd);
9206179404Sobrien
9207179404Sobrien  /* Set the sh_info field for .gptab sections and other appropriate
9208179404Sobrien     info for each special section.  */
9209179404Sobrien  for (i = 1, hdrpp = elf_elfsections (abfd) + 1;
9210179404Sobrien       i < elf_numsections (abfd);
9211179404Sobrien       i++, hdrpp++)
9212179404Sobrien    {
9213179404Sobrien      switch ((*hdrpp)->sh_type)
9214179404Sobrien	{
9215179404Sobrien	case SHT_MIPS_MSYM:
9216179404Sobrien	case SHT_MIPS_LIBLIST:
9217179404Sobrien	  sec = bfd_get_section_by_name (abfd, ".dynstr");
9218179404Sobrien	  if (sec != NULL)
9219179404Sobrien	    (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
9220179404Sobrien	  break;
9221179404Sobrien
9222179404Sobrien	case SHT_MIPS_GPTAB:
9223179404Sobrien	  BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
9224179404Sobrien	  name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
9225179404Sobrien	  BFD_ASSERT (name != NULL
9226218822Sdim		      && CONST_STRNEQ (name, ".gptab."));
9227179404Sobrien	  sec = bfd_get_section_by_name (abfd, name + sizeof ".gptab" - 1);
9228179404Sobrien	  BFD_ASSERT (sec != NULL);
9229179404Sobrien	  (*hdrpp)->sh_info = elf_section_data (sec)->this_idx;
9230179404Sobrien	  break;
9231179404Sobrien
9232179404Sobrien	case SHT_MIPS_CONTENT:
9233179404Sobrien	  BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
9234179404Sobrien	  name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
9235179404Sobrien	  BFD_ASSERT (name != NULL
9236218822Sdim		      && CONST_STRNEQ (name, ".MIPS.content"));
9237179404Sobrien	  sec = bfd_get_section_by_name (abfd,
9238179404Sobrien					 name + sizeof ".MIPS.content" - 1);
9239179404Sobrien	  BFD_ASSERT (sec != NULL);
9240179404Sobrien	  (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
9241179404Sobrien	  break;
9242179404Sobrien
9243179404Sobrien	case SHT_MIPS_SYMBOL_LIB:
9244179404Sobrien	  sec = bfd_get_section_by_name (abfd, ".dynsym");
9245179404Sobrien	  if (sec != NULL)
9246179404Sobrien	    (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
9247179404Sobrien	  sec = bfd_get_section_by_name (abfd, ".liblist");
9248179404Sobrien	  if (sec != NULL)
9249179404Sobrien	    (*hdrpp)->sh_info = elf_section_data (sec)->this_idx;
9250179404Sobrien	  break;
9251179404Sobrien
9252179404Sobrien	case SHT_MIPS_EVENTS:
9253179404Sobrien	  BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
9254179404Sobrien	  name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
9255179404Sobrien	  BFD_ASSERT (name != NULL);
9256218822Sdim	  if (CONST_STRNEQ (name, ".MIPS.events"))
9257179404Sobrien	    sec = bfd_get_section_by_name (abfd,
9258179404Sobrien					   name + sizeof ".MIPS.events" - 1);
9259179404Sobrien	  else
9260179404Sobrien	    {
9261218822Sdim	      BFD_ASSERT (CONST_STRNEQ (name, ".MIPS.post_rel"));
9262179404Sobrien	      sec = bfd_get_section_by_name (abfd,
9263179404Sobrien					     (name
9264179404Sobrien					      + sizeof ".MIPS.post_rel" - 1));
9265179404Sobrien	    }
9266179404Sobrien	  BFD_ASSERT (sec != NULL);
9267179404Sobrien	  (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
9268179404Sobrien	  break;
9269179404Sobrien
9270179404Sobrien	}
9271179404Sobrien    }
9272179404Sobrien}
9273179404Sobrien
9274179404Sobrien/* When creating an IRIX5 executable, we need REGINFO and RTPROC
9275179404Sobrien   segments.  */
9276179404Sobrien
9277179404Sobrienint
9278218822Sdim_bfd_mips_elf_additional_program_headers (bfd *abfd,
9279218822Sdim					  struct bfd_link_info *info ATTRIBUTE_UNUSED)
9280179404Sobrien{
9281179404Sobrien  asection *s;
9282179404Sobrien  int ret = 0;
9283179404Sobrien
9284179404Sobrien  /* See if we need a PT_MIPS_REGINFO segment.  */
9285179404Sobrien  s = bfd_get_section_by_name (abfd, ".reginfo");
9286179404Sobrien  if (s && (s->flags & SEC_LOAD))
9287179404Sobrien    ++ret;
9288179404Sobrien
9289179404Sobrien  /* See if we need a PT_MIPS_OPTIONS segment.  */
9290179404Sobrien  if (IRIX_COMPAT (abfd) == ict_irix6
9291179404Sobrien      && bfd_get_section_by_name (abfd,
9292179404Sobrien				  MIPS_ELF_OPTIONS_SECTION_NAME (abfd)))
9293179404Sobrien    ++ret;
9294179404Sobrien
9295179404Sobrien  /* See if we need a PT_MIPS_RTPROC segment.  */
9296179404Sobrien  if (IRIX_COMPAT (abfd) == ict_irix5
9297179404Sobrien      && bfd_get_section_by_name (abfd, ".dynamic")
9298179404Sobrien      && bfd_get_section_by_name (abfd, ".mdebug"))
9299179404Sobrien    ++ret;
9300179404Sobrien
9301218822Sdim  /* Allocate a PT_NULL header in dynamic objects.  See
9302218822Sdim     _bfd_mips_elf_modify_segment_map for details.  */
9303218822Sdim  if (!SGI_COMPAT (abfd)
9304218822Sdim      && bfd_get_section_by_name (abfd, ".dynamic"))
9305218822Sdim    ++ret;
9306218822Sdim
9307179404Sobrien  return ret;
9308179404Sobrien}
9309179404Sobrien
9310179404Sobrien/* Modify the segment map for an IRIX5 executable.  */
9311179404Sobrien
9312179404Sobrienbfd_boolean
9313179404Sobrien_bfd_mips_elf_modify_segment_map (bfd *abfd,
9314179404Sobrien				  struct bfd_link_info *info ATTRIBUTE_UNUSED)
9315179404Sobrien{
9316179404Sobrien  asection *s;
9317179404Sobrien  struct elf_segment_map *m, **pm;
9318179404Sobrien  bfd_size_type amt;
9319179404Sobrien
9320179404Sobrien  /* If there is a .reginfo section, we need a PT_MIPS_REGINFO
9321179404Sobrien     segment.  */
9322179404Sobrien  s = bfd_get_section_by_name (abfd, ".reginfo");
9323179404Sobrien  if (s != NULL && (s->flags & SEC_LOAD) != 0)
9324179404Sobrien    {
9325179404Sobrien      for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
9326179404Sobrien	if (m->p_type == PT_MIPS_REGINFO)
9327179404Sobrien	  break;
9328179404Sobrien      if (m == NULL)
9329179404Sobrien	{
9330179404Sobrien	  amt = sizeof *m;
9331179404Sobrien	  m = bfd_zalloc (abfd, amt);
9332179404Sobrien	  if (m == NULL)
9333179404Sobrien	    return FALSE;
9334179404Sobrien
9335179404Sobrien	  m->p_type = PT_MIPS_REGINFO;
9336179404Sobrien	  m->count = 1;
9337179404Sobrien	  m->sections[0] = s;
9338179404Sobrien
9339179404Sobrien	  /* We want to put it after the PHDR and INTERP segments.  */
9340179404Sobrien	  pm = &elf_tdata (abfd)->segment_map;
9341179404Sobrien	  while (*pm != NULL
9342179404Sobrien		 && ((*pm)->p_type == PT_PHDR
9343179404Sobrien		     || (*pm)->p_type == PT_INTERP))
9344179404Sobrien	    pm = &(*pm)->next;
9345179404Sobrien
9346179404Sobrien	  m->next = *pm;
9347179404Sobrien	  *pm = m;
9348179404Sobrien	}
9349179404Sobrien    }
9350179404Sobrien
9351179404Sobrien  /* For IRIX 6, we don't have .mdebug sections, nor does anything but
9352179404Sobrien     .dynamic end up in PT_DYNAMIC.  However, we do have to insert a
9353179404Sobrien     PT_MIPS_OPTIONS segment immediately following the program header
9354179404Sobrien     table.  */
9355179404Sobrien  if (NEWABI_P (abfd)
9356179404Sobrien      /* On non-IRIX6 new abi, we'll have already created a segment
9357179404Sobrien	 for this section, so don't create another.  I'm not sure this
9358179404Sobrien	 is not also the case for IRIX 6, but I can't test it right
9359179404Sobrien	 now.  */
9360179404Sobrien      && IRIX_COMPAT (abfd) == ict_irix6)
9361179404Sobrien    {
9362179404Sobrien      for (s = abfd->sections; s; s = s->next)
9363179404Sobrien	if (elf_section_data (s)->this_hdr.sh_type == SHT_MIPS_OPTIONS)
9364179404Sobrien	  break;
9365179404Sobrien
9366179404Sobrien      if (s)
9367179404Sobrien	{
9368179404Sobrien	  struct elf_segment_map *options_segment;
9369179404Sobrien
9370179404Sobrien	  pm = &elf_tdata (abfd)->segment_map;
9371179404Sobrien	  while (*pm != NULL
9372179404Sobrien		 && ((*pm)->p_type == PT_PHDR
9373179404Sobrien		     || (*pm)->p_type == PT_INTERP))
9374179404Sobrien	    pm = &(*pm)->next;
9375179404Sobrien
9376218822Sdim	  if (*pm == NULL || (*pm)->p_type != PT_MIPS_OPTIONS)
9377218822Sdim	    {
9378218822Sdim	      amt = sizeof (struct elf_segment_map);
9379218822Sdim	      options_segment = bfd_zalloc (abfd, amt);
9380218822Sdim	      options_segment->next = *pm;
9381218822Sdim	      options_segment->p_type = PT_MIPS_OPTIONS;
9382218822Sdim	      options_segment->p_flags = PF_R;
9383218822Sdim	      options_segment->p_flags_valid = TRUE;
9384218822Sdim	      options_segment->count = 1;
9385218822Sdim	      options_segment->sections[0] = s;
9386218822Sdim	      *pm = options_segment;
9387218822Sdim	    }
9388179404Sobrien	}
9389179404Sobrien    }
9390179404Sobrien  else
9391179404Sobrien    {
9392179404Sobrien      if (IRIX_COMPAT (abfd) == ict_irix5)
9393179404Sobrien	{
9394179404Sobrien	  /* If there are .dynamic and .mdebug sections, we make a room
9395179404Sobrien	     for the RTPROC header.  FIXME: Rewrite without section names.  */
9396179404Sobrien	  if (bfd_get_section_by_name (abfd, ".interp") == NULL
9397179404Sobrien	      && bfd_get_section_by_name (abfd, ".dynamic") != NULL
9398179404Sobrien	      && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
9399179404Sobrien	    {
9400179404Sobrien	      for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
9401179404Sobrien		if (m->p_type == PT_MIPS_RTPROC)
9402179404Sobrien		  break;
9403179404Sobrien	      if (m == NULL)
9404179404Sobrien		{
9405179404Sobrien		  amt = sizeof *m;
9406179404Sobrien		  m = bfd_zalloc (abfd, amt);
9407179404Sobrien		  if (m == NULL)
9408179404Sobrien		    return FALSE;
9409179404Sobrien
9410179404Sobrien		  m->p_type = PT_MIPS_RTPROC;
9411179404Sobrien
9412179404Sobrien		  s = bfd_get_section_by_name (abfd, ".rtproc");
9413179404Sobrien		  if (s == NULL)
9414179404Sobrien		    {
9415179404Sobrien		      m->count = 0;
9416179404Sobrien		      m->p_flags = 0;
9417179404Sobrien		      m->p_flags_valid = 1;
9418179404Sobrien		    }
9419179404Sobrien		  else
9420179404Sobrien		    {
9421179404Sobrien		      m->count = 1;
9422179404Sobrien		      m->sections[0] = s;
9423179404Sobrien		    }
9424179404Sobrien
9425179404Sobrien		  /* We want to put it after the DYNAMIC segment.  */
9426179404Sobrien		  pm = &elf_tdata (abfd)->segment_map;
9427179404Sobrien		  while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
9428179404Sobrien		    pm = &(*pm)->next;
9429179404Sobrien		  if (*pm != NULL)
9430179404Sobrien		    pm = &(*pm)->next;
9431179404Sobrien
9432179404Sobrien		  m->next = *pm;
9433179404Sobrien		  *pm = m;
9434179404Sobrien		}
9435179404Sobrien	    }
9436179404Sobrien	}
9437179404Sobrien      /* On IRIX5, the PT_DYNAMIC segment includes the .dynamic,
9438179404Sobrien	 .dynstr, .dynsym, and .hash sections, and everything in
9439179404Sobrien	 between.  */
9440179404Sobrien      for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL;
9441179404Sobrien	   pm = &(*pm)->next)
9442179404Sobrien	if ((*pm)->p_type == PT_DYNAMIC)
9443179404Sobrien	  break;
9444179404Sobrien      m = *pm;
9445179404Sobrien      if (m != NULL && IRIX_COMPAT (abfd) == ict_none)
9446179404Sobrien	{
9447179404Sobrien	  /* For a normal mips executable the permissions for the PT_DYNAMIC
9448179404Sobrien	     segment are read, write and execute. We do that here since
9449179404Sobrien	     the code in elf.c sets only the read permission. This matters
9450179404Sobrien	     sometimes for the dynamic linker.  */
9451179404Sobrien	  if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
9452179404Sobrien	    {
9453179404Sobrien	      m->p_flags = PF_R | PF_W | PF_X;
9454179404Sobrien	      m->p_flags_valid = 1;
9455179404Sobrien	    }
9456179404Sobrien	}
9457218822Sdim      /* GNU/Linux binaries do not need the extended PT_DYNAMIC section.
9458218822Sdim	 glibc's dynamic linker has traditionally derived the number of
9459218822Sdim	 tags from the p_filesz field, and sometimes allocates stack
9460218822Sdim	 arrays of that size.  An overly-big PT_DYNAMIC segment can
9461218822Sdim	 be actively harmful in such cases.  Making PT_DYNAMIC contain
9462218822Sdim	 other sections can also make life hard for the prelinker,
9463218822Sdim	 which might move one of the other sections to a different
9464218822Sdim	 PT_LOAD segment.  */
9465218822Sdim      if (SGI_COMPAT (abfd)
9466218822Sdim	  && m != NULL
9467218822Sdim	  && m->count == 1
9468218822Sdim	  && strcmp (m->sections[0]->name, ".dynamic") == 0)
9469179404Sobrien	{
9470179404Sobrien	  static const char *sec_names[] =
9471179404Sobrien	  {
9472179404Sobrien	    ".dynamic", ".dynstr", ".dynsym", ".hash"
9473179404Sobrien	  };
9474179404Sobrien	  bfd_vma low, high;
9475179404Sobrien	  unsigned int i, c;
9476179404Sobrien	  struct elf_segment_map *n;
9477179404Sobrien
9478179404Sobrien	  low = ~(bfd_vma) 0;
9479179404Sobrien	  high = 0;
9480179404Sobrien	  for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
9481179404Sobrien	    {
9482179404Sobrien	      s = bfd_get_section_by_name (abfd, sec_names[i]);
9483179404Sobrien	      if (s != NULL && (s->flags & SEC_LOAD) != 0)
9484179404Sobrien		{
9485179404Sobrien		  bfd_size_type sz;
9486179404Sobrien
9487179404Sobrien		  if (low > s->vma)
9488179404Sobrien		    low = s->vma;
9489218822Sdim		  sz = s->size;
9490179404Sobrien		  if (high < s->vma + sz)
9491179404Sobrien		    high = s->vma + sz;
9492179404Sobrien		}
9493179404Sobrien	    }
9494179404Sobrien
9495179404Sobrien	  c = 0;
9496179404Sobrien	  for (s = abfd->sections; s != NULL; s = s->next)
9497179404Sobrien	    if ((s->flags & SEC_LOAD) != 0
9498179404Sobrien		&& s->vma >= low
9499218822Sdim		&& s->vma + s->size <= high)
9500179404Sobrien	      ++c;
9501179404Sobrien
9502179404Sobrien	  amt = sizeof *n + (bfd_size_type) (c - 1) * sizeof (asection *);
9503179404Sobrien	  n = bfd_zalloc (abfd, amt);
9504179404Sobrien	  if (n == NULL)
9505179404Sobrien	    return FALSE;
9506179404Sobrien	  *n = *m;
9507179404Sobrien	  n->count = c;
9508179404Sobrien
9509179404Sobrien	  i = 0;
9510179404Sobrien	  for (s = abfd->sections; s != NULL; s = s->next)
9511179404Sobrien	    {
9512179404Sobrien	      if ((s->flags & SEC_LOAD) != 0
9513179404Sobrien		  && s->vma >= low
9514218822Sdim		  && s->vma + s->size <= high)
9515179404Sobrien		{
9516179404Sobrien		  n->sections[i] = s;
9517179404Sobrien		  ++i;
9518179404Sobrien		}
9519179404Sobrien	    }
9520179404Sobrien
9521179404Sobrien	  *pm = n;
9522179404Sobrien	}
9523179404Sobrien    }
9524179404Sobrien
9525218822Sdim  /* Allocate a spare program header in dynamic objects so that tools
9526218822Sdim     like the prelinker can add an extra PT_LOAD entry.
9527218822Sdim
9528218822Sdim     If the prelinker needs to make room for a new PT_LOAD entry, its
9529218822Sdim     standard procedure is to move the first (read-only) sections into
9530218822Sdim     the new (writable) segment.  However, the MIPS ABI requires
9531218822Sdim     .dynamic to be in a read-only segment, and the section will often
9532218822Sdim     start within sizeof (ElfNN_Phdr) bytes of the last program header.
9533218822Sdim
9534218822Sdim     Although the prelinker could in principle move .dynamic to a
9535218822Sdim     writable segment, it seems better to allocate a spare program
9536218822Sdim     header instead, and avoid the need to move any sections.
9537218822Sdim     There is a long tradition of allocating spare dynamic tags,
9538218822Sdim     so allocating a spare program header seems like a natural
9539218822Sdim     extension.  */
9540218822Sdim  if (!SGI_COMPAT (abfd)
9541218822Sdim      && bfd_get_section_by_name (abfd, ".dynamic"))
9542218822Sdim    {
9543218822Sdim      for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next)
9544218822Sdim	if ((*pm)->p_type == PT_NULL)
9545218822Sdim	  break;
9546218822Sdim      if (*pm == NULL)
9547218822Sdim	{
9548218822Sdim	  m = bfd_zalloc (abfd, sizeof (*m));
9549218822Sdim	  if (m == NULL)
9550218822Sdim	    return FALSE;
9551218822Sdim
9552218822Sdim	  m->p_type = PT_NULL;
9553218822Sdim	  *pm = m;
9554218822Sdim	}
9555218822Sdim    }
9556218822Sdim
9557179404Sobrien  return TRUE;
9558179404Sobrien}
9559179404Sobrien
9560179404Sobrien/* Return the section that should be marked against GC for a given
9561179404Sobrien   relocation.  */
9562179404Sobrien
9563179404Sobrienasection *
9564179404Sobrien_bfd_mips_elf_gc_mark_hook (asection *sec,
9565218822Sdim			    struct bfd_link_info *info,
9566179404Sobrien			    Elf_Internal_Rela *rel,
9567179404Sobrien			    struct elf_link_hash_entry *h,
9568179404Sobrien			    Elf_Internal_Sym *sym)
9569179404Sobrien{
9570179404Sobrien  /* ??? Do mips16 stub sections need to be handled special?  */
9571179404Sobrien
9572179404Sobrien  if (h != NULL)
9573218822Sdim    switch (ELF_R_TYPE (sec->owner, rel->r_info))
9574218822Sdim      {
9575218822Sdim      case R_MIPS_GNU_VTINHERIT:
9576218822Sdim      case R_MIPS_GNU_VTENTRY:
9577218822Sdim	return NULL;
9578218822Sdim      }
9579179404Sobrien
9580218822Sdim  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
9581179404Sobrien}
9582179404Sobrien
9583179404Sobrien/* Update the got entry reference counts for the section being removed.  */
9584179404Sobrien
9585179404Sobrienbfd_boolean
9586179404Sobrien_bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
9587179404Sobrien			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
9588179404Sobrien			     asection *sec ATTRIBUTE_UNUSED,
9589179404Sobrien			     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
9590179404Sobrien{
9591179404Sobrien#if 0
9592179404Sobrien  Elf_Internal_Shdr *symtab_hdr;
9593179404Sobrien  struct elf_link_hash_entry **sym_hashes;
9594179404Sobrien  bfd_signed_vma *local_got_refcounts;
9595179404Sobrien  const Elf_Internal_Rela *rel, *relend;
9596179404Sobrien  unsigned long r_symndx;
9597179404Sobrien  struct elf_link_hash_entry *h;
9598179404Sobrien
9599179404Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
9600179404Sobrien  sym_hashes = elf_sym_hashes (abfd);
9601179404Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
9602179404Sobrien
9603179404Sobrien  relend = relocs + sec->reloc_count;
9604179404Sobrien  for (rel = relocs; rel < relend; rel++)
9605179404Sobrien    switch (ELF_R_TYPE (abfd, rel->r_info))
9606179404Sobrien      {
9607179404Sobrien      case R_MIPS_GOT16:
9608179404Sobrien      case R_MIPS_CALL16:
9609179404Sobrien      case R_MIPS_CALL_HI16:
9610179404Sobrien      case R_MIPS_CALL_LO16:
9611179404Sobrien      case R_MIPS_GOT_HI16:
9612179404Sobrien      case R_MIPS_GOT_LO16:
9613179404Sobrien      case R_MIPS_GOT_DISP:
9614179404Sobrien      case R_MIPS_GOT_PAGE:
9615179404Sobrien      case R_MIPS_GOT_OFST:
9616179404Sobrien	/* ??? It would seem that the existing MIPS code does no sort
9617179404Sobrien	   of reference counting or whatnot on its GOT and PLT entries,
9618179404Sobrien	   so it is not possible to garbage collect them at this time.  */
9619179404Sobrien	break;
9620179404Sobrien
9621179404Sobrien      default:
9622179404Sobrien	break;
9623179404Sobrien      }
9624179404Sobrien#endif
9625179404Sobrien
9626179404Sobrien  return TRUE;
9627179404Sobrien}
9628179404Sobrien
9629179404Sobrien/* Copy data from a MIPS ELF indirect symbol to its direct symbol,
9630179404Sobrien   hiding the old indirect symbol.  Process additional relocation
9631179404Sobrien   information.  Also called for weakdefs, in which case we just let
9632179404Sobrien   _bfd_elf_link_hash_copy_indirect copy the flags for us.  */
9633179404Sobrien
9634179404Sobrienvoid
9635218822Sdim_bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
9636179404Sobrien				    struct elf_link_hash_entry *dir,
9637179404Sobrien				    struct elf_link_hash_entry *ind)
9638179404Sobrien{
9639179404Sobrien  struct mips_elf_link_hash_entry *dirmips, *indmips;
9640179404Sobrien
9641218822Sdim  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
9642179404Sobrien
9643179404Sobrien  if (ind->root.type != bfd_link_hash_indirect)
9644179404Sobrien    return;
9645179404Sobrien
9646179404Sobrien  dirmips = (struct mips_elf_link_hash_entry *) dir;
9647179404Sobrien  indmips = (struct mips_elf_link_hash_entry *) ind;
9648179404Sobrien  dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
9649179404Sobrien  if (indmips->readonly_reloc)
9650179404Sobrien    dirmips->readonly_reloc = TRUE;
9651179404Sobrien  if (indmips->no_fn_stub)
9652179404Sobrien    dirmips->no_fn_stub = TRUE;
9653218822Sdim
9654218822Sdim  if (dirmips->tls_type == 0)
9655218822Sdim    dirmips->tls_type = indmips->tls_type;
9656179404Sobrien}
9657179404Sobrien
9658179404Sobrienvoid
9659179404Sobrien_bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
9660179404Sobrien			   struct elf_link_hash_entry *entry,
9661179404Sobrien			   bfd_boolean force_local)
9662179404Sobrien{
9663179404Sobrien  bfd *dynobj;
9664179404Sobrien  asection *got;
9665179404Sobrien  struct mips_got_info *g;
9666179404Sobrien  struct mips_elf_link_hash_entry *h;
9667179404Sobrien
9668179404Sobrien  h = (struct mips_elf_link_hash_entry *) entry;
9669179404Sobrien  if (h->forced_local)
9670179404Sobrien    return;
9671179404Sobrien  h->forced_local = force_local;
9672179404Sobrien
9673179404Sobrien  dynobj = elf_hash_table (info)->dynobj;
9674218822Sdim  if (dynobj != NULL && force_local && h->root.type != STT_TLS
9675218822Sdim      && (got = mips_elf_got_section (dynobj, TRUE)) != NULL
9676218822Sdim      && (g = mips_elf_section_data (got)->u.got_info) != NULL)
9677179404Sobrien    {
9678179404Sobrien      if (g->next)
9679179404Sobrien	{
9680179404Sobrien	  struct mips_got_entry e;
9681179404Sobrien	  struct mips_got_info *gg = g;
9682179404Sobrien
9683179404Sobrien	  /* Since we're turning what used to be a global symbol into a
9684179404Sobrien	     local one, bump up the number of local entries of each GOT
9685179404Sobrien	     that had an entry for it.  This will automatically decrease
9686179404Sobrien	     the number of global entries, since global_gotno is actually
9687179404Sobrien	     the upper limit of global entries.  */
9688179404Sobrien	  e.abfd = dynobj;
9689179404Sobrien	  e.symndx = -1;
9690179404Sobrien	  e.d.h = h;
9691218822Sdim	  e.tls_type = 0;
9692179404Sobrien
9693179404Sobrien	  for (g = g->next; g != gg; g = g->next)
9694179404Sobrien	    if (htab_find (g->got_entries, &e))
9695179404Sobrien	      {
9696179404Sobrien		BFD_ASSERT (g->global_gotno > 0);
9697179404Sobrien		g->local_gotno++;
9698179404Sobrien		g->global_gotno--;
9699179404Sobrien	      }
9700179404Sobrien
9701179404Sobrien	  /* If this was a global symbol forced into the primary GOT, we
9702179404Sobrien	     no longer need an entry for it.  We can't release the entry
9703179404Sobrien	     at this point, but we must at least stop counting it as one
9704179404Sobrien	     of the symbols that required a forced got entry.  */
9705179404Sobrien	  if (h->root.got.offset == 2)
9706179404Sobrien	    {
9707179404Sobrien	      BFD_ASSERT (gg->assigned_gotno > 0);
9708179404Sobrien	      gg->assigned_gotno--;
9709179404Sobrien	    }
9710179404Sobrien	}
9711179404Sobrien      else if (g->global_gotno == 0 && g->global_gotsym == NULL)
9712179404Sobrien	/* If we haven't got through GOT allocation yet, just bump up the
9713179404Sobrien	   number of local entries, as this symbol won't be counted as
9714179404Sobrien	   global.  */
9715179404Sobrien	g->local_gotno++;
9716179404Sobrien      else if (h->root.got.offset == 1)
9717179404Sobrien	{
9718179404Sobrien	  /* If we're past non-multi-GOT allocation and this symbol had
9719179404Sobrien	     been marked for a global got entry, give it a local entry
9720179404Sobrien	     instead.  */
9721179404Sobrien	  BFD_ASSERT (g->global_gotno > 0);
9722179404Sobrien	  g->local_gotno++;
9723179404Sobrien	  g->global_gotno--;
9724179404Sobrien	}
9725179404Sobrien    }
9726179404Sobrien
9727179404Sobrien  _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
9728179404Sobrien}
9729179404Sobrien
9730179404Sobrien#define PDR_SIZE 32
9731179404Sobrien
9732179404Sobrienbfd_boolean
9733179404Sobrien_bfd_mips_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
9734179404Sobrien			    struct bfd_link_info *info)
9735179404Sobrien{
9736179404Sobrien  asection *o;
9737179404Sobrien  bfd_boolean ret = FALSE;
9738179404Sobrien  unsigned char *tdata;
9739179404Sobrien  size_t i, skip;
9740179404Sobrien
9741179404Sobrien  o = bfd_get_section_by_name (abfd, ".pdr");
9742179404Sobrien  if (! o)
9743179404Sobrien    return FALSE;
9744218822Sdim  if (o->size == 0)
9745179404Sobrien    return FALSE;
9746218822Sdim  if (o->size % PDR_SIZE != 0)
9747179404Sobrien    return FALSE;
9748179404Sobrien  if (o->output_section != NULL
9749179404Sobrien      && bfd_is_abs_section (o->output_section))
9750179404Sobrien    return FALSE;
9751179404Sobrien
9752218822Sdim  tdata = bfd_zmalloc (o->size / PDR_SIZE);
9753179404Sobrien  if (! tdata)
9754179404Sobrien    return FALSE;
9755179404Sobrien
9756179404Sobrien  cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
9757179404Sobrien					    info->keep_memory);
9758179404Sobrien  if (!cookie->rels)
9759179404Sobrien    {
9760179404Sobrien      free (tdata);
9761179404Sobrien      return FALSE;
9762179404Sobrien    }
9763179404Sobrien
9764179404Sobrien  cookie->rel = cookie->rels;
9765179404Sobrien  cookie->relend = cookie->rels + o->reloc_count;
9766179404Sobrien
9767218822Sdim  for (i = 0, skip = 0; i < o->size / PDR_SIZE; i ++)
9768179404Sobrien    {
9769179404Sobrien      if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
9770179404Sobrien	{
9771179404Sobrien	  tdata[i] = 1;
9772179404Sobrien	  skip ++;
9773179404Sobrien	}
9774179404Sobrien    }
9775179404Sobrien
9776179404Sobrien  if (skip != 0)
9777179404Sobrien    {
9778179404Sobrien      mips_elf_section_data (o)->u.tdata = tdata;
9779218822Sdim      o->size -= skip * PDR_SIZE;
9780179404Sobrien      ret = TRUE;
9781179404Sobrien    }
9782179404Sobrien  else
9783179404Sobrien    free (tdata);
9784179404Sobrien
9785179404Sobrien  if (! info->keep_memory)
9786179404Sobrien    free (cookie->rels);
9787179404Sobrien
9788179404Sobrien  return ret;
9789179404Sobrien}
9790179404Sobrien
9791179404Sobrienbfd_boolean
9792179404Sobrien_bfd_mips_elf_ignore_discarded_relocs (asection *sec)
9793179404Sobrien{
9794179404Sobrien  if (strcmp (sec->name, ".pdr") == 0)
9795179404Sobrien    return TRUE;
9796179404Sobrien  return FALSE;
9797179404Sobrien}
9798179404Sobrien
9799179404Sobrienbfd_boolean
9800218822Sdim_bfd_mips_elf_write_section (bfd *output_bfd,
9801218822Sdim			     struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
9802218822Sdim                             asection *sec, bfd_byte *contents)
9803179404Sobrien{
9804179404Sobrien  bfd_byte *to, *from, *end;
9805179404Sobrien  int i;
9806179404Sobrien
9807179404Sobrien  if (strcmp (sec->name, ".pdr") != 0)
9808179404Sobrien    return FALSE;
9809179404Sobrien
9810179404Sobrien  if (mips_elf_section_data (sec)->u.tdata == NULL)
9811179404Sobrien    return FALSE;
9812179404Sobrien
9813179404Sobrien  to = contents;
9814218822Sdim  end = contents + sec->size;
9815179404Sobrien  for (from = contents, i = 0;
9816179404Sobrien       from < end;
9817179404Sobrien       from += PDR_SIZE, i++)
9818179404Sobrien    {
9819179404Sobrien      if ((mips_elf_section_data (sec)->u.tdata)[i] == 1)
9820179404Sobrien	continue;
9821179404Sobrien      if (to != from)
9822179404Sobrien	memcpy (to, from, PDR_SIZE);
9823179404Sobrien      to += PDR_SIZE;
9824179404Sobrien    }
9825179404Sobrien  bfd_set_section_contents (output_bfd, sec->output_section, contents,
9826218822Sdim			    sec->output_offset, sec->size);
9827179404Sobrien  return TRUE;
9828179404Sobrien}
9829179404Sobrien
9830179404Sobrien/* MIPS ELF uses a special find_nearest_line routine in order the
9831179404Sobrien   handle the ECOFF debugging information.  */
9832179404Sobrien
9833179404Sobrienstruct mips_elf_find_line
9834179404Sobrien{
9835179404Sobrien  struct ecoff_debug_info d;
9836179404Sobrien  struct ecoff_find_line i;
9837179404Sobrien};
9838179404Sobrien
9839179404Sobrienbfd_boolean
9840179404Sobrien_bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section,
9841179404Sobrien				 asymbol **symbols, bfd_vma offset,
9842179404Sobrien				 const char **filename_ptr,
9843179404Sobrien				 const char **functionname_ptr,
9844179404Sobrien				 unsigned int *line_ptr)
9845179404Sobrien{
9846179404Sobrien  asection *msec;
9847179404Sobrien
9848179404Sobrien  if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
9849179404Sobrien				     filename_ptr, functionname_ptr,
9850179404Sobrien				     line_ptr))
9851179404Sobrien    return TRUE;
9852179404Sobrien
9853179404Sobrien  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
9854179404Sobrien				     filename_ptr, functionname_ptr,
9855179404Sobrien				     line_ptr, ABI_64_P (abfd) ? 8 : 0,
9856179404Sobrien				     &elf_tdata (abfd)->dwarf2_find_line_info))
9857179404Sobrien    return TRUE;
9858179404Sobrien
9859179404Sobrien  msec = bfd_get_section_by_name (abfd, ".mdebug");
9860179404Sobrien  if (msec != NULL)
9861179404Sobrien    {
9862179404Sobrien      flagword origflags;
9863179404Sobrien      struct mips_elf_find_line *fi;
9864179404Sobrien      const struct ecoff_debug_swap * const swap =
9865179404Sobrien	get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
9866179404Sobrien
9867179404Sobrien      /* If we are called during a link, mips_elf_final_link may have
9868179404Sobrien	 cleared the SEC_HAS_CONTENTS field.  We force it back on here
9869179404Sobrien	 if appropriate (which it normally will be).  */
9870179404Sobrien      origflags = msec->flags;
9871179404Sobrien      if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
9872179404Sobrien	msec->flags |= SEC_HAS_CONTENTS;
9873179404Sobrien
9874179404Sobrien      fi = elf_tdata (abfd)->find_line_info;
9875179404Sobrien      if (fi == NULL)
9876179404Sobrien	{
9877179404Sobrien	  bfd_size_type external_fdr_size;
9878179404Sobrien	  char *fraw_src;
9879179404Sobrien	  char *fraw_end;
9880179404Sobrien	  struct fdr *fdr_ptr;
9881179404Sobrien	  bfd_size_type amt = sizeof (struct mips_elf_find_line);
9882179404Sobrien
9883179404Sobrien	  fi = bfd_zalloc (abfd, amt);
9884179404Sobrien	  if (fi == NULL)
9885179404Sobrien	    {
9886179404Sobrien	      msec->flags = origflags;
9887179404Sobrien	      return FALSE;
9888179404Sobrien	    }
9889179404Sobrien
9890179404Sobrien	  if (! _bfd_mips_elf_read_ecoff_info (abfd, msec, &fi->d))
9891179404Sobrien	    {
9892179404Sobrien	      msec->flags = origflags;
9893179404Sobrien	      return FALSE;
9894179404Sobrien	    }
9895179404Sobrien
9896179404Sobrien	  /* Swap in the FDR information.  */
9897179404Sobrien	  amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
9898179404Sobrien	  fi->d.fdr = bfd_alloc (abfd, amt);
9899179404Sobrien	  if (fi->d.fdr == NULL)
9900179404Sobrien	    {
9901179404Sobrien	      msec->flags = origflags;
9902179404Sobrien	      return FALSE;
9903179404Sobrien	    }
9904179404Sobrien	  external_fdr_size = swap->external_fdr_size;
9905179404Sobrien	  fdr_ptr = fi->d.fdr;
9906179404Sobrien	  fraw_src = (char *) fi->d.external_fdr;
9907179404Sobrien	  fraw_end = (fraw_src
9908179404Sobrien		      + fi->d.symbolic_header.ifdMax * external_fdr_size);
9909179404Sobrien	  for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
9910179404Sobrien	    (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
9911179404Sobrien
9912179404Sobrien	  elf_tdata (abfd)->find_line_info = fi;
9913179404Sobrien
9914179404Sobrien	  /* Note that we don't bother to ever free this information.
9915179404Sobrien             find_nearest_line is either called all the time, as in
9916179404Sobrien             objdump -l, so the information should be saved, or it is
9917179404Sobrien             rarely called, as in ld error messages, so the memory
9918179404Sobrien             wasted is unimportant.  Still, it would probably be a
9919179404Sobrien             good idea for free_cached_info to throw it away.  */
9920179404Sobrien	}
9921179404Sobrien
9922179404Sobrien      if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
9923179404Sobrien				  &fi->i, filename_ptr, functionname_ptr,
9924179404Sobrien				  line_ptr))
9925179404Sobrien	{
9926179404Sobrien	  msec->flags = origflags;
9927179404Sobrien	  return TRUE;
9928179404Sobrien	}
9929179404Sobrien
9930179404Sobrien      msec->flags = origflags;
9931179404Sobrien    }
9932179404Sobrien
9933179404Sobrien  /* Fall back on the generic ELF find_nearest_line routine.  */
9934179404Sobrien
9935179404Sobrien  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
9936179404Sobrien				     filename_ptr, functionname_ptr,
9937179404Sobrien				     line_ptr);
9938179404Sobrien}
9939218822Sdim
9940218822Sdimbfd_boolean
9941218822Sdim_bfd_mips_elf_find_inliner_info (bfd *abfd,
9942218822Sdim				 const char **filename_ptr,
9943218822Sdim				 const char **functionname_ptr,
9944218822Sdim				 unsigned int *line_ptr)
9945218822Sdim{
9946218822Sdim  bfd_boolean found;
9947218822Sdim  found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr,
9948218822Sdim					 functionname_ptr, line_ptr,
9949218822Sdim					 & elf_tdata (abfd)->dwarf2_find_line_info);
9950218822Sdim  return found;
9951218822Sdim}
9952218822Sdim
9953179404Sobrien
9954179404Sobrien/* When are writing out the .options or .MIPS.options section,
9955179404Sobrien   remember the bytes we are writing out, so that we can install the
9956179404Sobrien   GP value in the section_processing routine.  */
9957179404Sobrien
9958179404Sobrienbfd_boolean
9959179404Sobrien_bfd_mips_elf_set_section_contents (bfd *abfd, sec_ptr section,
9960179404Sobrien				    const void *location,
9961179404Sobrien				    file_ptr offset, bfd_size_type count)
9962179404Sobrien{
9963218822Sdim  if (MIPS_ELF_OPTIONS_SECTION_NAME_P (section->name))
9964179404Sobrien    {
9965179404Sobrien      bfd_byte *c;
9966179404Sobrien
9967179404Sobrien      if (elf_section_data (section) == NULL)
9968179404Sobrien	{
9969179404Sobrien	  bfd_size_type amt = sizeof (struct bfd_elf_section_data);
9970179404Sobrien	  section->used_by_bfd = bfd_zalloc (abfd, amt);
9971179404Sobrien	  if (elf_section_data (section) == NULL)
9972179404Sobrien	    return FALSE;
9973179404Sobrien	}
9974179404Sobrien      c = mips_elf_section_data (section)->u.tdata;
9975179404Sobrien      if (c == NULL)
9976179404Sobrien	{
9977218822Sdim	  c = bfd_zalloc (abfd, section->size);
9978179404Sobrien	  if (c == NULL)
9979179404Sobrien	    return FALSE;
9980179404Sobrien	  mips_elf_section_data (section)->u.tdata = c;
9981179404Sobrien	}
9982179404Sobrien
9983179404Sobrien      memcpy (c + offset, location, count);
9984179404Sobrien    }
9985179404Sobrien
9986179404Sobrien  return _bfd_elf_set_section_contents (abfd, section, location, offset,
9987179404Sobrien					count);
9988179404Sobrien}
9989179404Sobrien
9990179404Sobrien/* This is almost identical to bfd_generic_get_... except that some
9991179404Sobrien   MIPS relocations need to be handled specially.  Sigh.  */
9992179404Sobrien
9993179404Sobrienbfd_byte *
9994179404Sobrien_bfd_elf_mips_get_relocated_section_contents
9995179404Sobrien  (bfd *abfd,
9996179404Sobrien   struct bfd_link_info *link_info,
9997179404Sobrien   struct bfd_link_order *link_order,
9998179404Sobrien   bfd_byte *data,
9999179404Sobrien   bfd_boolean relocatable,
10000179404Sobrien   asymbol **symbols)
10001179404Sobrien{
10002179404Sobrien  /* Get enough memory to hold the stuff */
10003179404Sobrien  bfd *input_bfd = link_order->u.indirect.section->owner;
10004179404Sobrien  asection *input_section = link_order->u.indirect.section;
10005218822Sdim  bfd_size_type sz;
10006179404Sobrien
10007179404Sobrien  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
10008179404Sobrien  arelent **reloc_vector = NULL;
10009179404Sobrien  long reloc_count;
10010179404Sobrien
10011179404Sobrien  if (reloc_size < 0)
10012179404Sobrien    goto error_return;
10013179404Sobrien
10014179404Sobrien  reloc_vector = bfd_malloc (reloc_size);
10015179404Sobrien  if (reloc_vector == NULL && reloc_size != 0)
10016179404Sobrien    goto error_return;
10017179404Sobrien
10018179404Sobrien  /* read in the section */
10019218822Sdim  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
10020218822Sdim  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
10021179404Sobrien    goto error_return;
10022179404Sobrien
10023179404Sobrien  reloc_count = bfd_canonicalize_reloc (input_bfd,
10024179404Sobrien					input_section,
10025179404Sobrien					reloc_vector,
10026179404Sobrien					symbols);
10027179404Sobrien  if (reloc_count < 0)
10028179404Sobrien    goto error_return;
10029179404Sobrien
10030179404Sobrien  if (reloc_count > 0)
10031179404Sobrien    {
10032179404Sobrien      arelent **parent;
10033179404Sobrien      /* for mips */
10034179404Sobrien      int gp_found;
10035179404Sobrien      bfd_vma gp = 0x12345678;	/* initialize just to shut gcc up */
10036179404Sobrien
10037179404Sobrien      {
10038179404Sobrien	struct bfd_hash_entry *h;
10039179404Sobrien	struct bfd_link_hash_entry *lh;
10040179404Sobrien	/* Skip all this stuff if we aren't mixing formats.  */
10041179404Sobrien	if (abfd && input_bfd
10042179404Sobrien	    && abfd->xvec == input_bfd->xvec)
10043179404Sobrien	  lh = 0;
10044179404Sobrien	else
10045179404Sobrien	  {
10046179404Sobrien	    h = bfd_hash_lookup (&link_info->hash->table, "_gp", FALSE, FALSE);
10047179404Sobrien	    lh = (struct bfd_link_hash_entry *) h;
10048179404Sobrien	  }
10049179404Sobrien      lookup:
10050179404Sobrien	if (lh)
10051179404Sobrien	  {
10052179404Sobrien	    switch (lh->type)
10053179404Sobrien	      {
10054179404Sobrien	      case bfd_link_hash_undefined:
10055179404Sobrien	      case bfd_link_hash_undefweak:
10056179404Sobrien	      case bfd_link_hash_common:
10057179404Sobrien		gp_found = 0;
10058179404Sobrien		break;
10059179404Sobrien	      case bfd_link_hash_defined:
10060179404Sobrien	      case bfd_link_hash_defweak:
10061179404Sobrien		gp_found = 1;
10062179404Sobrien		gp = lh->u.def.value;
10063179404Sobrien		break;
10064179404Sobrien	      case bfd_link_hash_indirect:
10065179404Sobrien	      case bfd_link_hash_warning:
10066179404Sobrien		lh = lh->u.i.link;
10067179404Sobrien		/* @@FIXME  ignoring warning for now */
10068179404Sobrien		goto lookup;
10069179404Sobrien	      case bfd_link_hash_new:
10070179404Sobrien	      default:
10071179404Sobrien		abort ();
10072179404Sobrien	      }
10073179404Sobrien	  }
10074179404Sobrien	else
10075179404Sobrien	  gp_found = 0;
10076179404Sobrien      }
10077179404Sobrien      /* end mips */
10078179404Sobrien      for (parent = reloc_vector; *parent != NULL; parent++)
10079179404Sobrien	{
10080179404Sobrien	  char *error_message = NULL;
10081179404Sobrien	  bfd_reloc_status_type r;
10082179404Sobrien
10083179404Sobrien	  /* Specific to MIPS: Deal with relocation types that require
10084179404Sobrien	     knowing the gp of the output bfd.  */
10085179404Sobrien	  asymbol *sym = *(*parent)->sym_ptr_ptr;
10086179404Sobrien
10087218822Sdim	  /* If we've managed to find the gp and have a special
10088218822Sdim	     function for the relocation then go ahead, else default
10089218822Sdim	     to the generic handling.  */
10090218822Sdim	  if (gp_found
10091218822Sdim	      && (*parent)->howto->special_function
10092218822Sdim	      == _bfd_mips_elf32_gprel16_reloc)
10093218822Sdim	    r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent,
10094218822Sdim					       input_section, relocatable,
10095218822Sdim					       data, gp);
10096218822Sdim	  else
10097218822Sdim	    r = bfd_perform_relocation (input_bfd, *parent, data,
10098218822Sdim					input_section,
10099218822Sdim					relocatable ? abfd : NULL,
10100218822Sdim					&error_message);
10101179404Sobrien
10102179404Sobrien	  if (relocatable)
10103179404Sobrien	    {
10104179404Sobrien	      asection *os = input_section->output_section;
10105179404Sobrien
10106179404Sobrien	      /* A partial link, so keep the relocs */
10107179404Sobrien	      os->orelocation[os->reloc_count] = *parent;
10108179404Sobrien	      os->reloc_count++;
10109179404Sobrien	    }
10110179404Sobrien
10111179404Sobrien	  if (r != bfd_reloc_ok)
10112179404Sobrien	    {
10113179404Sobrien	      switch (r)
10114179404Sobrien		{
10115179404Sobrien		case bfd_reloc_undefined:
10116179404Sobrien		  if (!((*link_info->callbacks->undefined_symbol)
10117179404Sobrien			(link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
10118218822Sdim			 input_bfd, input_section, (*parent)->address, TRUE)))
10119179404Sobrien		    goto error_return;
10120179404Sobrien		  break;
10121179404Sobrien		case bfd_reloc_dangerous:
10122179404Sobrien		  BFD_ASSERT (error_message != NULL);
10123179404Sobrien		  if (!((*link_info->callbacks->reloc_dangerous)
10124179404Sobrien			(link_info, error_message, input_bfd, input_section,
10125179404Sobrien			 (*parent)->address)))
10126179404Sobrien		    goto error_return;
10127179404Sobrien		  break;
10128179404Sobrien		case bfd_reloc_overflow:
10129179404Sobrien		  if (!((*link_info->callbacks->reloc_overflow)
10130218822Sdim			(link_info, NULL,
10131218822Sdim			 bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
10132179404Sobrien			 (*parent)->howto->name, (*parent)->addend,
10133179404Sobrien			 input_bfd, input_section, (*parent)->address)))
10134179404Sobrien		    goto error_return;
10135179404Sobrien		  break;
10136179404Sobrien		case bfd_reloc_outofrange:
10137179404Sobrien		default:
10138179404Sobrien		  abort ();
10139179404Sobrien		  break;
10140179404Sobrien		}
10141179404Sobrien
10142179404Sobrien	    }
10143179404Sobrien	}
10144179404Sobrien    }
10145179404Sobrien  if (reloc_vector != NULL)
10146179404Sobrien    free (reloc_vector);
10147179404Sobrien  return data;
10148179404Sobrien
10149179404Sobrienerror_return:
10150179404Sobrien  if (reloc_vector != NULL)
10151179404Sobrien    free (reloc_vector);
10152179404Sobrien  return NULL;
10153179404Sobrien}
10154179404Sobrien
10155179404Sobrien/* Create a MIPS ELF linker hash table.  */
10156179404Sobrien
10157179404Sobrienstruct bfd_link_hash_table *
10158179404Sobrien_bfd_mips_elf_link_hash_table_create (bfd *abfd)
10159179404Sobrien{
10160179404Sobrien  struct mips_elf_link_hash_table *ret;
10161179404Sobrien  bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
10162179404Sobrien
10163179404Sobrien  ret = bfd_malloc (amt);
10164179404Sobrien  if (ret == NULL)
10165179404Sobrien    return NULL;
10166179404Sobrien
10167218822Sdim  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
10168218822Sdim				      mips_elf_link_hash_newfunc,
10169218822Sdim				      sizeof (struct mips_elf_link_hash_entry)))
10170179404Sobrien    {
10171179404Sobrien      free (ret);
10172179404Sobrien      return NULL;
10173179404Sobrien    }
10174179404Sobrien
10175179404Sobrien#if 0
10176179404Sobrien  /* We no longer use this.  */
10177179404Sobrien  for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
10178179404Sobrien    ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
10179179404Sobrien#endif
10180179404Sobrien  ret->procedure_count = 0;
10181179404Sobrien  ret->compact_rel_size = 0;
10182179404Sobrien  ret->use_rld_obj_head = FALSE;
10183179404Sobrien  ret->rld_value = 0;
10184179404Sobrien  ret->mips16_stubs_seen = FALSE;
10185218822Sdim  ret->is_vxworks = FALSE;
10186218822Sdim  ret->srelbss = NULL;
10187218822Sdim  ret->sdynbss = NULL;
10188218822Sdim  ret->srelplt = NULL;
10189218822Sdim  ret->srelplt2 = NULL;
10190218822Sdim  ret->sgotplt = NULL;
10191218822Sdim  ret->splt = NULL;
10192218822Sdim  ret->plt_header_size = 0;
10193218822Sdim  ret->plt_entry_size = 0;
10194218822Sdim  ret->function_stub_size = 0;
10195179404Sobrien
10196179404Sobrien  return &ret->root.root;
10197179404Sobrien}
10198218822Sdim
10199218822Sdim/* Likewise, but indicate that the target is VxWorks.  */
10200218822Sdim
10201218822Sdimstruct bfd_link_hash_table *
10202218822Sdim_bfd_mips_vxworks_link_hash_table_create (bfd *abfd)
10203218822Sdim{
10204218822Sdim  struct bfd_link_hash_table *ret;
10205218822Sdim
10206218822Sdim  ret = _bfd_mips_elf_link_hash_table_create (abfd);
10207218822Sdim  if (ret)
10208218822Sdim    {
10209218822Sdim      struct mips_elf_link_hash_table *htab;
10210218822Sdim
10211218822Sdim      htab = (struct mips_elf_link_hash_table *) ret;
10212218822Sdim      htab->is_vxworks = 1;
10213218822Sdim    }
10214218822Sdim  return ret;
10215218822Sdim}
10216179404Sobrien
10217179404Sobrien/* We need to use a special link routine to handle the .reginfo and
10218179404Sobrien   the .mdebug sections.  We need to merge all instances of these
10219179404Sobrien   sections together, not write them all out sequentially.  */
10220179404Sobrien
10221179404Sobrienbfd_boolean
10222179404Sobrien_bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
10223179404Sobrien{
10224179404Sobrien  asection *o;
10225179404Sobrien  struct bfd_link_order *p;
10226179404Sobrien  asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
10227179404Sobrien  asection *rtproc_sec;
10228179404Sobrien  Elf32_RegInfo reginfo;
10229179404Sobrien  struct ecoff_debug_info debug;
10230218822Sdim  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
10231218822Sdim  const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
10232179404Sobrien  HDRR *symhdr = &debug.symbolic_header;
10233179404Sobrien  void *mdebug_handle = NULL;
10234179404Sobrien  asection *s;
10235179404Sobrien  EXTR esym;
10236179404Sobrien  unsigned int i;
10237179404Sobrien  bfd_size_type amt;
10238218822Sdim  struct mips_elf_link_hash_table *htab;
10239179404Sobrien
10240179404Sobrien  static const char * const secname[] =
10241179404Sobrien  {
10242179404Sobrien    ".text", ".init", ".fini", ".data",
10243179404Sobrien    ".rodata", ".sdata", ".sbss", ".bss"
10244179404Sobrien  };
10245179404Sobrien  static const int sc[] =
10246179404Sobrien  {
10247179404Sobrien    scText, scInit, scFini, scData,
10248179404Sobrien    scRData, scSData, scSBss, scBss
10249179404Sobrien  };
10250179404Sobrien
10251179404Sobrien  /* We'd carefully arranged the dynamic symbol indices, and then the
10252179404Sobrien     generic size_dynamic_sections renumbered them out from under us.
10253179404Sobrien     Rather than trying somehow to prevent the renumbering, just do
10254179404Sobrien     the sort again.  */
10255218822Sdim  htab = mips_elf_hash_table (info);
10256179404Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
10257179404Sobrien    {
10258179404Sobrien      bfd *dynobj;
10259179404Sobrien      asection *got;
10260179404Sobrien      struct mips_got_info *g;
10261218822Sdim      bfd_size_type dynsecsymcount;
10262179404Sobrien
10263179404Sobrien      /* When we resort, we must tell mips_elf_sort_hash_table what
10264179404Sobrien	 the lowest index it may use is.  That's the number of section
10265179404Sobrien	 symbols we're going to add.  The generic ELF linker only
10266179404Sobrien	 adds these symbols when building a shared object.  Note that
10267179404Sobrien	 we count the sections after (possibly) removing the .options
10268179404Sobrien	 section above.  */
10269218822Sdim
10270218822Sdim      dynsecsymcount = count_section_dynsyms (abfd, info);
10271218822Sdim      if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
10272179404Sobrien	return FALSE;
10273179404Sobrien
10274179404Sobrien      /* Make sure we didn't grow the global .got region.  */
10275179404Sobrien      dynobj = elf_hash_table (info)->dynobj;
10276179404Sobrien      got = mips_elf_got_section (dynobj, FALSE);
10277179404Sobrien      g = mips_elf_section_data (got)->u.got_info;
10278179404Sobrien
10279179404Sobrien      if (g->global_gotsym != NULL)
10280179404Sobrien	BFD_ASSERT ((elf_hash_table (info)->dynsymcount
10281179404Sobrien		     - g->global_gotsym->dynindx)
10282179404Sobrien		    <= g->global_gotno);
10283179404Sobrien    }
10284179404Sobrien
10285179404Sobrien  /* Get a value for the GP register.  */
10286179404Sobrien  if (elf_gp (abfd) == 0)
10287179404Sobrien    {
10288179404Sobrien      struct bfd_link_hash_entry *h;
10289179404Sobrien
10290179404Sobrien      h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
10291179404Sobrien      if (h != NULL && h->type == bfd_link_hash_defined)
10292179404Sobrien	elf_gp (abfd) = (h->u.def.value
10293179404Sobrien			 + h->u.def.section->output_section->vma
10294179404Sobrien			 + h->u.def.section->output_offset);
10295218822Sdim      else if (htab->is_vxworks
10296218822Sdim	       && (h = bfd_link_hash_lookup (info->hash,
10297218822Sdim					     "_GLOBAL_OFFSET_TABLE_",
10298218822Sdim					     FALSE, FALSE, TRUE))
10299218822Sdim	       && h->type == bfd_link_hash_defined)
10300218822Sdim	elf_gp (abfd) = (h->u.def.section->output_section->vma
10301218822Sdim			 + h->u.def.section->output_offset
10302218822Sdim			 + h->u.def.value);
10303179404Sobrien      else if (info->relocatable)
10304179404Sobrien	{
10305179404Sobrien	  bfd_vma lo = MINUS_ONE;
10306179404Sobrien
10307179404Sobrien	  /* Find the GP-relative section with the lowest offset.  */
10308179404Sobrien	  for (o = abfd->sections; o != NULL; o = o->next)
10309179404Sobrien	    if (o->vma < lo
10310179404Sobrien		&& (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
10311179404Sobrien	      lo = o->vma;
10312179404Sobrien
10313179404Sobrien	  /* And calculate GP relative to that.  */
10314218822Sdim	  elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info);
10315179404Sobrien	}
10316179404Sobrien      else
10317179404Sobrien	{
10318179404Sobrien	  /* If the relocate_section function needs to do a reloc
10319179404Sobrien	     involving the GP value, it should make a reloc_dangerous
10320179404Sobrien	     callback to warn that GP is not defined.  */
10321179404Sobrien	}
10322179404Sobrien    }
10323179404Sobrien
10324179404Sobrien  /* Go through the sections and collect the .reginfo and .mdebug
10325179404Sobrien     information.  */
10326179404Sobrien  reginfo_sec = NULL;
10327179404Sobrien  mdebug_sec = NULL;
10328179404Sobrien  gptab_data_sec = NULL;
10329179404Sobrien  gptab_bss_sec = NULL;
10330179404Sobrien  for (o = abfd->sections; o != NULL; o = o->next)
10331179404Sobrien    {
10332179404Sobrien      if (strcmp (o->name, ".reginfo") == 0)
10333179404Sobrien	{
10334179404Sobrien	  memset (&reginfo, 0, sizeof reginfo);
10335179404Sobrien
10336179404Sobrien	  /* We have found the .reginfo section in the output file.
10337179404Sobrien	     Look through all the link_orders comprising it and merge
10338179404Sobrien	     the information together.  */
10339218822Sdim	  for (p = o->map_head.link_order; p != NULL; p = p->next)
10340179404Sobrien	    {
10341179404Sobrien	      asection *input_section;
10342179404Sobrien	      bfd *input_bfd;
10343179404Sobrien	      Elf32_External_RegInfo ext;
10344179404Sobrien	      Elf32_RegInfo sub;
10345179404Sobrien
10346179404Sobrien	      if (p->type != bfd_indirect_link_order)
10347179404Sobrien		{
10348179404Sobrien		  if (p->type == bfd_data_link_order)
10349179404Sobrien		    continue;
10350179404Sobrien		  abort ();
10351179404Sobrien		}
10352179404Sobrien
10353179404Sobrien	      input_section = p->u.indirect.section;
10354179404Sobrien	      input_bfd = input_section->owner;
10355179404Sobrien
10356179404Sobrien	      if (! bfd_get_section_contents (input_bfd, input_section,
10357179404Sobrien					      &ext, 0, sizeof ext))
10358179404Sobrien		return FALSE;
10359179404Sobrien
10360179404Sobrien	      bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub);
10361179404Sobrien
10362179404Sobrien	      reginfo.ri_gprmask |= sub.ri_gprmask;
10363179404Sobrien	      reginfo.ri_cprmask[0] |= sub.ri_cprmask[0];
10364179404Sobrien	      reginfo.ri_cprmask[1] |= sub.ri_cprmask[1];
10365179404Sobrien	      reginfo.ri_cprmask[2] |= sub.ri_cprmask[2];
10366179404Sobrien	      reginfo.ri_cprmask[3] |= sub.ri_cprmask[3];
10367179404Sobrien
10368179404Sobrien	      /* ri_gp_value is set by the function
10369179404Sobrien		 mips_elf32_section_processing when the section is
10370179404Sobrien		 finally written out.  */
10371179404Sobrien
10372179404Sobrien	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
10373179404Sobrien		 elf_link_input_bfd ignores this section.  */
10374179404Sobrien	      input_section->flags &= ~SEC_HAS_CONTENTS;
10375179404Sobrien	    }
10376179404Sobrien
10377179404Sobrien	  /* Size has been set in _bfd_mips_elf_always_size_sections.  */
10378218822Sdim	  BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
10379179404Sobrien
10380179404Sobrien	  /* Skip this section later on (I don't think this currently
10381179404Sobrien	     matters, but someday it might).  */
10382218822Sdim	  o->map_head.link_order = NULL;
10383179404Sobrien
10384179404Sobrien	  reginfo_sec = o;
10385179404Sobrien	}
10386179404Sobrien
10387179404Sobrien      if (strcmp (o->name, ".mdebug") == 0)
10388179404Sobrien	{
10389179404Sobrien	  struct extsym_info einfo;
10390179404Sobrien	  bfd_vma last;
10391179404Sobrien
10392179404Sobrien	  /* We have found the .mdebug section in the output file.
10393179404Sobrien	     Look through all the link_orders comprising it and merge
10394179404Sobrien	     the information together.  */
10395179404Sobrien	  symhdr->magic = swap->sym_magic;
10396179404Sobrien	  /* FIXME: What should the version stamp be?  */
10397179404Sobrien	  symhdr->vstamp = 0;
10398179404Sobrien	  symhdr->ilineMax = 0;
10399179404Sobrien	  symhdr->cbLine = 0;
10400179404Sobrien	  symhdr->idnMax = 0;
10401179404Sobrien	  symhdr->ipdMax = 0;
10402179404Sobrien	  symhdr->isymMax = 0;
10403179404Sobrien	  symhdr->ioptMax = 0;
10404179404Sobrien	  symhdr->iauxMax = 0;
10405179404Sobrien	  symhdr->issMax = 0;
10406179404Sobrien	  symhdr->issExtMax = 0;
10407179404Sobrien	  symhdr->ifdMax = 0;
10408179404Sobrien	  symhdr->crfd = 0;
10409179404Sobrien	  symhdr->iextMax = 0;
10410179404Sobrien
10411179404Sobrien	  /* We accumulate the debugging information itself in the
10412179404Sobrien	     debug_info structure.  */
10413179404Sobrien	  debug.line = NULL;
10414179404Sobrien	  debug.external_dnr = NULL;
10415179404Sobrien	  debug.external_pdr = NULL;
10416179404Sobrien	  debug.external_sym = NULL;
10417179404Sobrien	  debug.external_opt = NULL;
10418179404Sobrien	  debug.external_aux = NULL;
10419179404Sobrien	  debug.ss = NULL;
10420179404Sobrien	  debug.ssext = debug.ssext_end = NULL;
10421179404Sobrien	  debug.external_fdr = NULL;
10422179404Sobrien	  debug.external_rfd = NULL;
10423179404Sobrien	  debug.external_ext = debug.external_ext_end = NULL;
10424179404Sobrien
10425179404Sobrien	  mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
10426179404Sobrien	  if (mdebug_handle == NULL)
10427179404Sobrien	    return FALSE;
10428179404Sobrien
10429179404Sobrien	  esym.jmptbl = 0;
10430179404Sobrien	  esym.cobol_main = 0;
10431179404Sobrien	  esym.weakext = 0;
10432179404Sobrien	  esym.reserved = 0;
10433179404Sobrien	  esym.ifd = ifdNil;
10434179404Sobrien	  esym.asym.iss = issNil;
10435179404Sobrien	  esym.asym.st = stLocal;
10436179404Sobrien	  esym.asym.reserved = 0;
10437179404Sobrien	  esym.asym.index = indexNil;
10438179404Sobrien	  last = 0;
10439179404Sobrien	  for (i = 0; i < sizeof (secname) / sizeof (secname[0]); i++)
10440179404Sobrien	    {
10441179404Sobrien	      esym.asym.sc = sc[i];
10442179404Sobrien	      s = bfd_get_section_by_name (abfd, secname[i]);
10443179404Sobrien	      if (s != NULL)
10444179404Sobrien		{
10445179404Sobrien		  esym.asym.value = s->vma;
10446218822Sdim		  last = s->vma + s->size;
10447179404Sobrien		}
10448179404Sobrien	      else
10449179404Sobrien		esym.asym.value = last;
10450179404Sobrien	      if (!bfd_ecoff_debug_one_external (abfd, &debug, swap,
10451179404Sobrien						 secname[i], &esym))
10452179404Sobrien		return FALSE;
10453179404Sobrien	    }
10454179404Sobrien
10455218822Sdim	  for (p = o->map_head.link_order; p != NULL; p = p->next)
10456179404Sobrien	    {
10457179404Sobrien	      asection *input_section;
10458179404Sobrien	      bfd *input_bfd;
10459179404Sobrien	      const struct ecoff_debug_swap *input_swap;
10460179404Sobrien	      struct ecoff_debug_info input_debug;
10461179404Sobrien	      char *eraw_src;
10462179404Sobrien	      char *eraw_end;
10463179404Sobrien
10464179404Sobrien	      if (p->type != bfd_indirect_link_order)
10465179404Sobrien		{
10466179404Sobrien		  if (p->type == bfd_data_link_order)
10467179404Sobrien		    continue;
10468179404Sobrien		  abort ();
10469179404Sobrien		}
10470179404Sobrien
10471179404Sobrien	      input_section = p->u.indirect.section;
10472179404Sobrien	      input_bfd = input_section->owner;
10473179404Sobrien
10474179404Sobrien	      if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
10475179404Sobrien		  || (get_elf_backend_data (input_bfd)
10476179404Sobrien		      ->elf_backend_ecoff_debug_swap) == NULL)
10477179404Sobrien		{
10478179404Sobrien		  /* I don't know what a non MIPS ELF bfd would be
10479179404Sobrien		     doing with a .mdebug section, but I don't really
10480179404Sobrien		     want to deal with it.  */
10481179404Sobrien		  continue;
10482179404Sobrien		}
10483179404Sobrien
10484179404Sobrien	      input_swap = (get_elf_backend_data (input_bfd)
10485179404Sobrien			    ->elf_backend_ecoff_debug_swap);
10486179404Sobrien
10487218822Sdim	      BFD_ASSERT (p->size == input_section->size);
10488179404Sobrien
10489179404Sobrien	      /* The ECOFF linking code expects that we have already
10490179404Sobrien		 read in the debugging information and set up an
10491179404Sobrien		 ecoff_debug_info structure, so we do that now.  */
10492179404Sobrien	      if (! _bfd_mips_elf_read_ecoff_info (input_bfd, input_section,
10493179404Sobrien						   &input_debug))
10494179404Sobrien		return FALSE;
10495179404Sobrien
10496179404Sobrien	      if (! (bfd_ecoff_debug_accumulate
10497179404Sobrien		     (mdebug_handle, abfd, &debug, swap, input_bfd,
10498179404Sobrien		      &input_debug, input_swap, info)))
10499179404Sobrien		return FALSE;
10500179404Sobrien
10501179404Sobrien	      /* Loop through the external symbols.  For each one with
10502179404Sobrien		 interesting information, try to find the symbol in
10503179404Sobrien		 the linker global hash table and save the information
10504179404Sobrien		 for the output external symbols.  */
10505179404Sobrien	      eraw_src = input_debug.external_ext;
10506179404Sobrien	      eraw_end = (eraw_src
10507179404Sobrien			  + (input_debug.symbolic_header.iextMax
10508179404Sobrien			     * input_swap->external_ext_size));
10509179404Sobrien	      for (;
10510179404Sobrien		   eraw_src < eraw_end;
10511179404Sobrien		   eraw_src += input_swap->external_ext_size)
10512179404Sobrien		{
10513179404Sobrien		  EXTR ext;
10514179404Sobrien		  const char *name;
10515179404Sobrien		  struct mips_elf_link_hash_entry *h;
10516179404Sobrien
10517179404Sobrien		  (*input_swap->swap_ext_in) (input_bfd, eraw_src, &ext);
10518179404Sobrien		  if (ext.asym.sc == scNil
10519179404Sobrien		      || ext.asym.sc == scUndefined
10520179404Sobrien		      || ext.asym.sc == scSUndefined)
10521179404Sobrien		    continue;
10522179404Sobrien
10523179404Sobrien		  name = input_debug.ssext + ext.asym.iss;
10524179404Sobrien		  h = mips_elf_link_hash_lookup (mips_elf_hash_table (info),
10525179404Sobrien						 name, FALSE, FALSE, TRUE);
10526179404Sobrien		  if (h == NULL || h->esym.ifd != -2)
10527179404Sobrien		    continue;
10528179404Sobrien
10529179404Sobrien		  if (ext.ifd != -1)
10530179404Sobrien		    {
10531179404Sobrien		      BFD_ASSERT (ext.ifd
10532179404Sobrien				  < input_debug.symbolic_header.ifdMax);
10533179404Sobrien		      ext.ifd = input_debug.ifdmap[ext.ifd];
10534179404Sobrien		    }
10535179404Sobrien
10536179404Sobrien		  h->esym = ext;
10537179404Sobrien		}
10538179404Sobrien
10539179404Sobrien	      /* Free up the information we just read.  */
10540179404Sobrien	      free (input_debug.line);
10541179404Sobrien	      free (input_debug.external_dnr);
10542179404Sobrien	      free (input_debug.external_pdr);
10543179404Sobrien	      free (input_debug.external_sym);
10544179404Sobrien	      free (input_debug.external_opt);
10545179404Sobrien	      free (input_debug.external_aux);
10546179404Sobrien	      free (input_debug.ss);
10547179404Sobrien	      free (input_debug.ssext);
10548179404Sobrien	      free (input_debug.external_fdr);
10549179404Sobrien	      free (input_debug.external_rfd);
10550179404Sobrien	      free (input_debug.external_ext);
10551179404Sobrien
10552179404Sobrien	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
10553179404Sobrien		 elf_link_input_bfd ignores this section.  */
10554179404Sobrien	      input_section->flags &= ~SEC_HAS_CONTENTS;
10555179404Sobrien	    }
10556179404Sobrien
10557179404Sobrien	  if (SGI_COMPAT (abfd) && info->shared)
10558179404Sobrien	    {
10559179404Sobrien	      /* Create .rtproc section.  */
10560179404Sobrien	      rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
10561179404Sobrien	      if (rtproc_sec == NULL)
10562179404Sobrien		{
10563179404Sobrien		  flagword flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
10564179404Sobrien				    | SEC_LINKER_CREATED | SEC_READONLY);
10565179404Sobrien
10566218822Sdim		  rtproc_sec = bfd_make_section_with_flags (abfd,
10567218822Sdim							    ".rtproc",
10568218822Sdim							    flags);
10569179404Sobrien		  if (rtproc_sec == NULL
10570179404Sobrien		      || ! bfd_set_section_alignment (abfd, rtproc_sec, 4))
10571179404Sobrien		    return FALSE;
10572179404Sobrien		}
10573179404Sobrien
10574179404Sobrien	      if (! mips_elf_create_procedure_table (mdebug_handle, abfd,
10575179404Sobrien						     info, rtproc_sec,
10576179404Sobrien						     &debug))
10577179404Sobrien		return FALSE;
10578179404Sobrien	    }
10579179404Sobrien
10580179404Sobrien	  /* Build the external symbol information.  */
10581179404Sobrien	  einfo.abfd = abfd;
10582179404Sobrien	  einfo.info = info;
10583179404Sobrien	  einfo.debug = &debug;
10584179404Sobrien	  einfo.swap = swap;
10585179404Sobrien	  einfo.failed = FALSE;
10586179404Sobrien	  mips_elf_link_hash_traverse (mips_elf_hash_table (info),
10587179404Sobrien				       mips_elf_output_extsym, &einfo);
10588179404Sobrien	  if (einfo.failed)
10589179404Sobrien	    return FALSE;
10590179404Sobrien
10591179404Sobrien	  /* Set the size of the .mdebug section.  */
10592218822Sdim	  o->size = bfd_ecoff_debug_size (abfd, &debug, swap);
10593179404Sobrien
10594179404Sobrien	  /* Skip this section later on (I don't think this currently
10595179404Sobrien	     matters, but someday it might).  */
10596218822Sdim	  o->map_head.link_order = NULL;
10597179404Sobrien
10598179404Sobrien	  mdebug_sec = o;
10599179404Sobrien	}
10600179404Sobrien
10601218822Sdim      if (CONST_STRNEQ (o->name, ".gptab."))
10602179404Sobrien	{
10603179404Sobrien	  const char *subname;
10604179404Sobrien	  unsigned int c;
10605179404Sobrien	  Elf32_gptab *tab;
10606179404Sobrien	  Elf32_External_gptab *ext_tab;
10607179404Sobrien	  unsigned int j;
10608179404Sobrien
10609179404Sobrien	  /* The .gptab.sdata and .gptab.sbss sections hold
10610179404Sobrien	     information describing how the small data area would
10611179404Sobrien	     change depending upon the -G switch.  These sections
10612179404Sobrien	     not used in executables files.  */
10613179404Sobrien	  if (! info->relocatable)
10614179404Sobrien	    {
10615218822Sdim	      for (p = o->map_head.link_order; p != NULL; p = p->next)
10616179404Sobrien		{
10617179404Sobrien		  asection *input_section;
10618179404Sobrien
10619179404Sobrien		  if (p->type != bfd_indirect_link_order)
10620179404Sobrien		    {
10621179404Sobrien		      if (p->type == bfd_data_link_order)
10622179404Sobrien			continue;
10623179404Sobrien		      abort ();
10624179404Sobrien		    }
10625179404Sobrien
10626179404Sobrien		  input_section = p->u.indirect.section;
10627179404Sobrien
10628179404Sobrien		  /* Hack: reset the SEC_HAS_CONTENTS flag so that
10629179404Sobrien		     elf_link_input_bfd ignores this section.  */
10630179404Sobrien		  input_section->flags &= ~SEC_HAS_CONTENTS;
10631179404Sobrien		}
10632179404Sobrien
10633179404Sobrien	      /* Skip this section later on (I don't think this
10634179404Sobrien		 currently matters, but someday it might).  */
10635218822Sdim	      o->map_head.link_order = NULL;
10636179404Sobrien
10637179404Sobrien	      /* Really remove the section.  */
10638218822Sdim	      bfd_section_list_remove (abfd, o);
10639179404Sobrien	      --abfd->section_count;
10640179404Sobrien
10641179404Sobrien	      continue;
10642179404Sobrien	    }
10643179404Sobrien
10644179404Sobrien	  /* There is one gptab for initialized data, and one for
10645179404Sobrien	     uninitialized data.  */
10646179404Sobrien	  if (strcmp (o->name, ".gptab.sdata") == 0)
10647179404Sobrien	    gptab_data_sec = o;
10648179404Sobrien	  else if (strcmp (o->name, ".gptab.sbss") == 0)
10649179404Sobrien	    gptab_bss_sec = o;
10650179404Sobrien	  else
10651179404Sobrien	    {
10652179404Sobrien	      (*_bfd_error_handler)
10653179404Sobrien		(_("%s: illegal section name `%s'"),
10654179404Sobrien		 bfd_get_filename (abfd), o->name);
10655179404Sobrien	      bfd_set_error (bfd_error_nonrepresentable_section);
10656179404Sobrien	      return FALSE;
10657179404Sobrien	    }
10658179404Sobrien
10659179404Sobrien	  /* The linker script always combines .gptab.data and
10660179404Sobrien	     .gptab.sdata into .gptab.sdata, and likewise for
10661179404Sobrien	     .gptab.bss and .gptab.sbss.  It is possible that there is
10662179404Sobrien	     no .sdata or .sbss section in the output file, in which
10663179404Sobrien	     case we must change the name of the output section.  */
10664179404Sobrien	  subname = o->name + sizeof ".gptab" - 1;
10665179404Sobrien	  if (bfd_get_section_by_name (abfd, subname) == NULL)
10666179404Sobrien	    {
10667179404Sobrien	      if (o == gptab_data_sec)
10668179404Sobrien		o->name = ".gptab.data";
10669179404Sobrien	      else
10670179404Sobrien		o->name = ".gptab.bss";
10671179404Sobrien	      subname = o->name + sizeof ".gptab" - 1;
10672179404Sobrien	      BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL);
10673179404Sobrien	    }
10674179404Sobrien
10675179404Sobrien	  /* Set up the first entry.  */
10676179404Sobrien	  c = 1;
10677179404Sobrien	  amt = c * sizeof (Elf32_gptab);
10678179404Sobrien	  tab = bfd_malloc (amt);
10679179404Sobrien	  if (tab == NULL)
10680179404Sobrien	    return FALSE;
10681179404Sobrien	  tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
10682179404Sobrien	  tab[0].gt_header.gt_unused = 0;
10683179404Sobrien
10684179404Sobrien	  /* Combine the input sections.  */
10685218822Sdim	  for (p = o->map_head.link_order; p != NULL; p = p->next)
10686179404Sobrien	    {
10687179404Sobrien	      asection *input_section;
10688179404Sobrien	      bfd *input_bfd;
10689179404Sobrien	      bfd_size_type size;
10690179404Sobrien	      unsigned long last;
10691179404Sobrien	      bfd_size_type gpentry;
10692179404Sobrien
10693179404Sobrien	      if (p->type != bfd_indirect_link_order)
10694179404Sobrien		{
10695179404Sobrien		  if (p->type == bfd_data_link_order)
10696179404Sobrien		    continue;
10697179404Sobrien		  abort ();
10698179404Sobrien		}
10699179404Sobrien
10700179404Sobrien	      input_section = p->u.indirect.section;
10701179404Sobrien	      input_bfd = input_section->owner;
10702179404Sobrien
10703179404Sobrien	      /* Combine the gptab entries for this input section one
10704179404Sobrien		 by one.  We know that the input gptab entries are
10705179404Sobrien		 sorted by ascending -G value.  */
10706218822Sdim	      size = input_section->size;
10707179404Sobrien	      last = 0;
10708179404Sobrien	      for (gpentry = sizeof (Elf32_External_gptab);
10709179404Sobrien		   gpentry < size;
10710179404Sobrien		   gpentry += sizeof (Elf32_External_gptab))
10711179404Sobrien		{
10712179404Sobrien		  Elf32_External_gptab ext_gptab;
10713179404Sobrien		  Elf32_gptab int_gptab;
10714179404Sobrien		  unsigned long val;
10715179404Sobrien		  unsigned long add;
10716179404Sobrien		  bfd_boolean exact;
10717179404Sobrien		  unsigned int look;
10718179404Sobrien
10719179404Sobrien		  if (! (bfd_get_section_contents
10720179404Sobrien			 (input_bfd, input_section, &ext_gptab, gpentry,
10721179404Sobrien			  sizeof (Elf32_External_gptab))))
10722179404Sobrien		    {
10723179404Sobrien		      free (tab);
10724179404Sobrien		      return FALSE;
10725179404Sobrien		    }
10726179404Sobrien
10727179404Sobrien		  bfd_mips_elf32_swap_gptab_in (input_bfd, &ext_gptab,
10728179404Sobrien						&int_gptab);
10729179404Sobrien		  val = int_gptab.gt_entry.gt_g_value;
10730179404Sobrien		  add = int_gptab.gt_entry.gt_bytes - last;
10731179404Sobrien
10732179404Sobrien		  exact = FALSE;
10733179404Sobrien		  for (look = 1; look < c; look++)
10734179404Sobrien		    {
10735179404Sobrien		      if (tab[look].gt_entry.gt_g_value >= val)
10736179404Sobrien			tab[look].gt_entry.gt_bytes += add;
10737179404Sobrien
10738179404Sobrien		      if (tab[look].gt_entry.gt_g_value == val)
10739179404Sobrien			exact = TRUE;
10740179404Sobrien		    }
10741179404Sobrien
10742179404Sobrien		  if (! exact)
10743179404Sobrien		    {
10744179404Sobrien		      Elf32_gptab *new_tab;
10745179404Sobrien		      unsigned int max;
10746179404Sobrien
10747179404Sobrien		      /* We need a new table entry.  */
10748179404Sobrien		      amt = (bfd_size_type) (c + 1) * sizeof (Elf32_gptab);
10749179404Sobrien		      new_tab = bfd_realloc (tab, amt);
10750179404Sobrien		      if (new_tab == NULL)
10751179404Sobrien			{
10752179404Sobrien			  free (tab);
10753179404Sobrien			  return FALSE;
10754179404Sobrien			}
10755179404Sobrien		      tab = new_tab;
10756179404Sobrien		      tab[c].gt_entry.gt_g_value = val;
10757179404Sobrien		      tab[c].gt_entry.gt_bytes = add;
10758179404Sobrien
10759179404Sobrien		      /* Merge in the size for the next smallest -G
10760179404Sobrien			 value, since that will be implied by this new
10761179404Sobrien			 value.  */
10762179404Sobrien		      max = 0;
10763179404Sobrien		      for (look = 1; look < c; look++)
10764179404Sobrien			{
10765179404Sobrien			  if (tab[look].gt_entry.gt_g_value < val
10766179404Sobrien			      && (max == 0
10767179404Sobrien				  || (tab[look].gt_entry.gt_g_value
10768179404Sobrien				      > tab[max].gt_entry.gt_g_value)))
10769179404Sobrien			    max = look;
10770179404Sobrien			}
10771179404Sobrien		      if (max != 0)
10772179404Sobrien			tab[c].gt_entry.gt_bytes +=
10773179404Sobrien			  tab[max].gt_entry.gt_bytes;
10774179404Sobrien
10775179404Sobrien		      ++c;
10776179404Sobrien		    }
10777179404Sobrien
10778179404Sobrien		  last = int_gptab.gt_entry.gt_bytes;
10779179404Sobrien		}
10780179404Sobrien
10781179404Sobrien	      /* Hack: reset the SEC_HAS_CONTENTS flag so that
10782179404Sobrien		 elf_link_input_bfd ignores this section.  */
10783179404Sobrien	      input_section->flags &= ~SEC_HAS_CONTENTS;
10784179404Sobrien	    }
10785179404Sobrien
10786179404Sobrien	  /* The table must be sorted by -G value.  */
10787179404Sobrien	  if (c > 2)
10788179404Sobrien	    qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare);
10789179404Sobrien
10790179404Sobrien	  /* Swap out the table.  */
10791179404Sobrien	  amt = (bfd_size_type) c * sizeof (Elf32_External_gptab);
10792179404Sobrien	  ext_tab = bfd_alloc (abfd, amt);
10793179404Sobrien	  if (ext_tab == NULL)
10794179404Sobrien	    {
10795179404Sobrien	      free (tab);
10796179404Sobrien	      return FALSE;
10797179404Sobrien	    }
10798179404Sobrien
10799179404Sobrien	  for (j = 0; j < c; j++)
10800179404Sobrien	    bfd_mips_elf32_swap_gptab_out (abfd, tab + j, ext_tab + j);
10801179404Sobrien	  free (tab);
10802179404Sobrien
10803218822Sdim	  o->size = c * sizeof (Elf32_External_gptab);
10804179404Sobrien	  o->contents = (bfd_byte *) ext_tab;
10805179404Sobrien
10806179404Sobrien	  /* Skip this section later on (I don't think this currently
10807179404Sobrien	     matters, but someday it might).  */
10808218822Sdim	  o->map_head.link_order = NULL;
10809179404Sobrien	}
10810179404Sobrien    }
10811179404Sobrien
10812179404Sobrien  /* Invoke the regular ELF backend linker to do all the work.  */
10813179404Sobrien  if (!bfd_elf_final_link (abfd, info))
10814179404Sobrien    return FALSE;
10815179404Sobrien
10816179404Sobrien  /* Now write out the computed sections.  */
10817179404Sobrien
10818179404Sobrien  if (reginfo_sec != NULL)
10819179404Sobrien    {
10820179404Sobrien      Elf32_External_RegInfo ext;
10821179404Sobrien
10822179404Sobrien      bfd_mips_elf32_swap_reginfo_out (abfd, &reginfo, &ext);
10823179404Sobrien      if (! bfd_set_section_contents (abfd, reginfo_sec, &ext, 0, sizeof ext))
10824179404Sobrien	return FALSE;
10825179404Sobrien    }
10826179404Sobrien
10827179404Sobrien  if (mdebug_sec != NULL)
10828179404Sobrien    {
10829179404Sobrien      BFD_ASSERT (abfd->output_has_begun);
10830179404Sobrien      if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
10831179404Sobrien					       swap, info,
10832179404Sobrien					       mdebug_sec->filepos))
10833179404Sobrien	return FALSE;
10834179404Sobrien
10835179404Sobrien      bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
10836179404Sobrien    }
10837179404Sobrien
10838179404Sobrien  if (gptab_data_sec != NULL)
10839179404Sobrien    {
10840179404Sobrien      if (! bfd_set_section_contents (abfd, gptab_data_sec,
10841179404Sobrien				      gptab_data_sec->contents,
10842218822Sdim				      0, gptab_data_sec->size))
10843179404Sobrien	return FALSE;
10844179404Sobrien    }
10845179404Sobrien
10846179404Sobrien  if (gptab_bss_sec != NULL)
10847179404Sobrien    {
10848179404Sobrien      if (! bfd_set_section_contents (abfd, gptab_bss_sec,
10849179404Sobrien				      gptab_bss_sec->contents,
10850218822Sdim				      0, gptab_bss_sec->size))
10851179404Sobrien	return FALSE;
10852179404Sobrien    }
10853179404Sobrien
10854179404Sobrien  if (SGI_COMPAT (abfd))
10855179404Sobrien    {
10856179404Sobrien      rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
10857179404Sobrien      if (rtproc_sec != NULL)
10858179404Sobrien	{
10859179404Sobrien	  if (! bfd_set_section_contents (abfd, rtproc_sec,
10860179404Sobrien					  rtproc_sec->contents,
10861218822Sdim					  0, rtproc_sec->size))
10862179404Sobrien	    return FALSE;
10863179404Sobrien	}
10864179404Sobrien    }
10865179404Sobrien
10866179404Sobrien  return TRUE;
10867179404Sobrien}
10868179404Sobrien
10869179404Sobrien/* Structure for saying that BFD machine EXTENSION extends BASE.  */
10870179404Sobrien
10871179404Sobrienstruct mips_mach_extension {
10872179404Sobrien  unsigned long extension, base;
10873179404Sobrien};
10874179404Sobrien
10875179404Sobrien
10876179404Sobrien/* An array describing how BFD machines relate to one another.  The entries
10877179404Sobrien   are ordered topologically with MIPS I extensions listed last.  */
10878179404Sobrien
10879179404Sobrienstatic const struct mips_mach_extension mips_mach_extensions[] = {
10880208737Sjmallett  /* MIPS64r2 extensions.  */
10881208737Sjmallett  { bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 },
10882208737Sjmallett
10883179404Sobrien  /* MIPS64 extensions.  */
10884179404Sobrien  { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
10885179404Sobrien  { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
10886179404Sobrien
10887179404Sobrien  /* MIPS V extensions.  */
10888179404Sobrien  { bfd_mach_mipsisa64, bfd_mach_mips5 },
10889179404Sobrien
10890179404Sobrien  /* R10000 extensions.  */
10891179404Sobrien  { bfd_mach_mips12000, bfd_mach_mips10000 },
10892179404Sobrien
10893179404Sobrien  /* R5000 extensions.  Note: the vr5500 ISA is an extension of the core
10894179404Sobrien     vr5400 ISA, but doesn't include the multimedia stuff.  It seems
10895179404Sobrien     better to allow vr5400 and vr5500 code to be merged anyway, since
10896179404Sobrien     many libraries will just use the core ISA.  Perhaps we could add
10897179404Sobrien     some sort of ASE flag if this ever proves a problem.  */
10898179404Sobrien  { bfd_mach_mips5500, bfd_mach_mips5400 },
10899179404Sobrien  { bfd_mach_mips5400, bfd_mach_mips5000 },
10900179404Sobrien
10901179404Sobrien  /* MIPS IV extensions.  */
10902179404Sobrien  { bfd_mach_mips5, bfd_mach_mips8000 },
10903179404Sobrien  { bfd_mach_mips10000, bfd_mach_mips8000 },
10904179404Sobrien  { bfd_mach_mips5000, bfd_mach_mips8000 },
10905179404Sobrien  { bfd_mach_mips7000, bfd_mach_mips8000 },
10906208737Sjmallett  { bfd_mach_mips9000, bfd_mach_mips8000 },
10907179404Sobrien
10908179404Sobrien  /* VR4100 extensions.  */
10909179404Sobrien  { bfd_mach_mips4120, bfd_mach_mips4100 },
10910179404Sobrien  { bfd_mach_mips4111, bfd_mach_mips4100 },
10911179404Sobrien
10912179404Sobrien  /* MIPS III extensions.  */
10913179404Sobrien  { bfd_mach_mips8000, bfd_mach_mips4000 },
10914179404Sobrien  { bfd_mach_mips4650, bfd_mach_mips4000 },
10915179404Sobrien  { bfd_mach_mips4600, bfd_mach_mips4000 },
10916179404Sobrien  { bfd_mach_mips4400, bfd_mach_mips4000 },
10917179404Sobrien  { bfd_mach_mips4300, bfd_mach_mips4000 },
10918179404Sobrien  { bfd_mach_mips4100, bfd_mach_mips4000 },
10919179404Sobrien  { bfd_mach_mips4010, bfd_mach_mips4000 },
10920179404Sobrien
10921179404Sobrien  /* MIPS32 extensions.  */
10922179404Sobrien  { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 },
10923179404Sobrien
10924179404Sobrien  /* MIPS II extensions.  */
10925179404Sobrien  { bfd_mach_mips4000, bfd_mach_mips6000 },
10926179404Sobrien  { bfd_mach_mipsisa32, bfd_mach_mips6000 },
10927179404Sobrien
10928179404Sobrien  /* MIPS I extensions.  */
10929179404Sobrien  { bfd_mach_mips6000, bfd_mach_mips3000 },
10930179404Sobrien  { bfd_mach_mips3900, bfd_mach_mips3000 }
10931179404Sobrien};
10932179404Sobrien
10933179404Sobrien
10934179404Sobrien/* Return true if bfd machine EXTENSION is an extension of machine BASE.  */
10935179404Sobrien
10936179404Sobrienstatic bfd_boolean
10937179404Sobrienmips_mach_extends_p (unsigned long base, unsigned long extension)
10938179404Sobrien{
10939179404Sobrien  size_t i;
10940179404Sobrien
10941208737Sjmallett  if (extension == base)
10942208737Sjmallett    return TRUE;
10943208737Sjmallett
10944208737Sjmallett  if (base == bfd_mach_mipsisa32
10945208737Sjmallett      && mips_mach_extends_p (bfd_mach_mipsisa64, extension))
10946208737Sjmallett    return TRUE;
10947208737Sjmallett
10948208737Sjmallett  if (base == bfd_mach_mipsisa32r2
10949208737Sjmallett      && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension))
10950208737Sjmallett    return TRUE;
10951208737Sjmallett
10952208737Sjmallett  for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++)
10953179404Sobrien    if (extension == mips_mach_extensions[i].extension)
10954208737Sjmallett      {
10955208737Sjmallett	extension = mips_mach_extensions[i].base;
10956208737Sjmallett	if (extension == base)
10957208737Sjmallett	  return TRUE;
10958208737Sjmallett      }
10959179404Sobrien
10960208737Sjmallett  return FALSE;
10961179404Sobrien}
10962179404Sobrien
10963179404Sobrien
10964179404Sobrien/* Return true if the given ELF header flags describe a 32-bit binary.  */
10965179404Sobrien
10966179404Sobrienstatic bfd_boolean
10967179404Sobrienmips_32bit_flags_p (flagword flags)
10968179404Sobrien{
10969179404Sobrien  return ((flags & EF_MIPS_32BITMODE) != 0
10970179404Sobrien	  || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
10971179404Sobrien	  || (flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
10972179404Sobrien	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
10973179404Sobrien	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
10974179404Sobrien	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
10975179404Sobrien	  || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2);
10976179404Sobrien}
10977179404Sobrien
10978179404Sobrien
10979218822Sdim/* Merge object attributes from IBFD into OBFD.  Raise an error if
10980218822Sdim   there are conflicting attributes.  */
10981218822Sdimstatic bfd_boolean
10982218822Sdimmips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
10983218822Sdim{
10984218822Sdim  obj_attribute *in_attr;
10985218822Sdim  obj_attribute *out_attr;
10986218822Sdim
10987218822Sdim  if (!elf_known_obj_attributes_proc (obfd)[0].i)
10988218822Sdim    {
10989218822Sdim      /* This is the first object.  Copy the attributes.  */
10990218822Sdim      _bfd_elf_copy_obj_attributes (ibfd, obfd);
10991218822Sdim
10992218822Sdim      /* Use the Tag_null value to indicate the attributes have been
10993218822Sdim	 initialized.  */
10994218822Sdim      elf_known_obj_attributes_proc (obfd)[0].i = 1;
10995218822Sdim
10996218822Sdim      return TRUE;
10997218822Sdim    }
10998218822Sdim
10999218822Sdim  /* Check for conflicting Tag_GNU_MIPS_ABI_FP attributes and merge
11000218822Sdim     non-conflicting ones.  */
11001218822Sdim  in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
11002218822Sdim  out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
11003218822Sdim  if (in_attr[Tag_GNU_MIPS_ABI_FP].i != out_attr[Tag_GNU_MIPS_ABI_FP].i)
11004218822Sdim    {
11005218822Sdim      out_attr[Tag_GNU_MIPS_ABI_FP].type = 1;
11006218822Sdim      if (out_attr[Tag_GNU_MIPS_ABI_FP].i == 0)
11007218822Sdim	out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
11008218822Sdim      else if (in_attr[Tag_GNU_MIPS_ABI_FP].i == 0)
11009218822Sdim	;
11010218822Sdim      else if (in_attr[Tag_GNU_MIPS_ABI_FP].i > 3)
11011218822Sdim	_bfd_error_handler
11012218822Sdim	  (_("Warning: %B uses unknown floating point ABI %d"), ibfd,
11013218822Sdim	   in_attr[Tag_GNU_MIPS_ABI_FP].i);
11014218822Sdim      else if (out_attr[Tag_GNU_MIPS_ABI_FP].i > 3)
11015218822Sdim	_bfd_error_handler
11016218822Sdim	  (_("Warning: %B uses unknown floating point ABI %d"), obfd,
11017218822Sdim	   out_attr[Tag_GNU_MIPS_ABI_FP].i);
11018218822Sdim      else
11019218822Sdim	switch (out_attr[Tag_GNU_MIPS_ABI_FP].i)
11020218822Sdim	  {
11021218822Sdim	  case 1:
11022218822Sdim	    switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
11023218822Sdim	      {
11024218822Sdim	      case 2:
11025218822Sdim		_bfd_error_handler
11026218822Sdim		  (_("Warning: %B uses -msingle-float, %B uses -mdouble-float"),
11027218822Sdim		   obfd, ibfd);
11028218822Sdim
11029218822Sdim	      case 3:
11030218822Sdim		_bfd_error_handler
11031218822Sdim		  (_("Warning: %B uses hard float, %B uses soft float"),
11032218822Sdim		   obfd, ibfd);
11033218822Sdim		break;
11034218822Sdim
11035218822Sdim	      default:
11036218822Sdim		abort ();
11037218822Sdim	      }
11038218822Sdim	    break;
11039218822Sdim
11040218822Sdim	  case 2:
11041218822Sdim	    switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
11042218822Sdim	      {
11043218822Sdim	      case 1:
11044218822Sdim		_bfd_error_handler
11045218822Sdim		  (_("Warning: %B uses -msingle-float, %B uses -mdouble-float"),
11046218822Sdim		   ibfd, obfd);
11047218822Sdim
11048218822Sdim	      case 3:
11049218822Sdim		_bfd_error_handler
11050218822Sdim		  (_("Warning: %B uses hard float, %B uses soft float"),
11051218822Sdim		   obfd, ibfd);
11052218822Sdim		break;
11053218822Sdim
11054218822Sdim	      default:
11055218822Sdim		abort ();
11056218822Sdim	      }
11057218822Sdim	    break;
11058218822Sdim
11059218822Sdim	  case 3:
11060218822Sdim	    switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
11061218822Sdim	      {
11062218822Sdim	      case 1:
11063218822Sdim	      case 2:
11064218822Sdim		_bfd_error_handler
11065218822Sdim		  (_("Warning: %B uses hard float, %B uses soft float"),
11066218822Sdim		   ibfd, obfd);
11067218822Sdim		break;
11068218822Sdim
11069218822Sdim	      default:
11070218822Sdim		abort ();
11071218822Sdim	      }
11072218822Sdim	    break;
11073218822Sdim
11074218822Sdim	  default:
11075218822Sdim	    abort ();
11076218822Sdim	  }
11077218822Sdim    }
11078218822Sdim
11079218822Sdim  /* Merge Tag_compatibility attributes and any common GNU ones.  */
11080218822Sdim  _bfd_elf_merge_object_attributes (ibfd, obfd);
11081218822Sdim
11082218822Sdim  return TRUE;
11083218822Sdim}
11084218822Sdim
11085179404Sobrien/* Merge backend specific data from an object file to the output
11086179404Sobrien   object file when linking.  */
11087179404Sobrien
11088179404Sobrienbfd_boolean
11089179404Sobrien_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
11090179404Sobrien{
11091179404Sobrien  flagword old_flags;
11092179404Sobrien  flagword new_flags;
11093179404Sobrien  bfd_boolean ok;
11094179404Sobrien  bfd_boolean null_input_bfd = TRUE;
11095179404Sobrien  asection *sec;
11096179404Sobrien
11097179404Sobrien  /* Check if we have the same endianess */
11098179404Sobrien  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
11099179404Sobrien    {
11100179404Sobrien      (*_bfd_error_handler)
11101218822Sdim	(_("%B: endianness incompatible with that of the selected emulation"),
11102218822Sdim	 ibfd);
11103179404Sobrien      return FALSE;
11104179404Sobrien    }
11105179404Sobrien
11106179404Sobrien  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
11107179404Sobrien      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
11108179404Sobrien    return TRUE;
11109179404Sobrien
11110179404Sobrien  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
11111179404Sobrien    {
11112179404Sobrien      (*_bfd_error_handler)
11113218822Sdim	(_("%B: ABI is incompatible with that of the selected emulation"),
11114218822Sdim	 ibfd);
11115179404Sobrien      return FALSE;
11116179404Sobrien    }
11117179404Sobrien
11118218822Sdim  if (!mips_elf_merge_obj_attributes (ibfd, obfd))
11119218822Sdim    return FALSE;
11120218822Sdim
11121179404Sobrien  new_flags = elf_elfheader (ibfd)->e_flags;
11122179404Sobrien  elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
11123179404Sobrien  old_flags = elf_elfheader (obfd)->e_flags;
11124179404Sobrien
11125179404Sobrien  if (! elf_flags_init (obfd))
11126179404Sobrien    {
11127179404Sobrien      elf_flags_init (obfd) = TRUE;
11128179404Sobrien      elf_elfheader (obfd)->e_flags = new_flags;
11129179404Sobrien      elf_elfheader (obfd)->e_ident[EI_CLASS]
11130179404Sobrien	= elf_elfheader (ibfd)->e_ident[EI_CLASS];
11131179404Sobrien
11132179404Sobrien      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
11133218822Sdim	  && (bfd_get_arch_info (obfd)->the_default
11134218822Sdim	      || mips_mach_extends_p (bfd_get_mach (obfd),
11135218822Sdim				      bfd_get_mach (ibfd))))
11136179404Sobrien	{
11137179404Sobrien	  if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
11138179404Sobrien				   bfd_get_mach (ibfd)))
11139179404Sobrien	    return FALSE;
11140179404Sobrien	}
11141179404Sobrien
11142179404Sobrien      return TRUE;
11143179404Sobrien    }
11144179404Sobrien
11145179404Sobrien  /* Check flag compatibility.  */
11146179404Sobrien
11147179404Sobrien  new_flags &= ~EF_MIPS_NOREORDER;
11148179404Sobrien  old_flags &= ~EF_MIPS_NOREORDER;
11149179404Sobrien
11150179404Sobrien  /* Some IRIX 6 BSD-compatibility objects have this bit set.  It
11151179404Sobrien     doesn't seem to matter.  */
11152179404Sobrien  new_flags &= ~EF_MIPS_XGOT;
11153179404Sobrien  old_flags &= ~EF_MIPS_XGOT;
11154179404Sobrien
11155179404Sobrien  /* MIPSpro generates ucode info in n64 objects.  Again, we should
11156179404Sobrien     just be able to ignore this.  */
11157179404Sobrien  new_flags &= ~EF_MIPS_UCODE;
11158179404Sobrien  old_flags &= ~EF_MIPS_UCODE;
11159179404Sobrien
11160218822Sdim  /* Don't care about the PIC flags from dynamic objects; they are
11161218822Sdim     PIC by design.  */
11162218822Sdim  if ((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0
11163218822Sdim      && (ibfd->flags & DYNAMIC) != 0)
11164218822Sdim    new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
11165218822Sdim
11166179404Sobrien  if (new_flags == old_flags)
11167179404Sobrien    return TRUE;
11168179404Sobrien
11169179404Sobrien  /* Check to see if the input BFD actually contains any sections.
11170179404Sobrien     If not, its flags may not have been initialised either, but it cannot
11171179404Sobrien     actually cause any incompatibility.  */
11172179404Sobrien  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
11173179404Sobrien    {
11174179404Sobrien      /* Ignore synthetic sections and empty .text, .data and .bss sections
11175179404Sobrien	  which are automatically generated by gas.  */
11176179404Sobrien      if (strcmp (sec->name, ".reginfo")
11177179404Sobrien	  && strcmp (sec->name, ".mdebug")
11178218822Sdim	  && (sec->size != 0
11179179404Sobrien	      || (strcmp (sec->name, ".text")
11180179404Sobrien		  && strcmp (sec->name, ".data")
11181179404Sobrien		  && strcmp (sec->name, ".bss"))))
11182179404Sobrien	{
11183179404Sobrien	  null_input_bfd = FALSE;
11184179404Sobrien	  break;
11185179404Sobrien	}
11186179404Sobrien    }
11187179404Sobrien  if (null_input_bfd)
11188179404Sobrien    return TRUE;
11189179404Sobrien
11190179404Sobrien  ok = TRUE;
11191179404Sobrien
11192179404Sobrien  if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
11193179404Sobrien      != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
11194179404Sobrien    {
11195179404Sobrien      (*_bfd_error_handler)
11196218822Sdim	(_("%B: warning: linking PIC files with non-PIC files"),
11197218822Sdim	 ibfd);
11198179404Sobrien      ok = TRUE;
11199179404Sobrien    }
11200179404Sobrien
11201179404Sobrien  if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
11202179404Sobrien    elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
11203179404Sobrien  if (! (new_flags & EF_MIPS_PIC))
11204179404Sobrien    elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;
11205179404Sobrien
11206179404Sobrien  new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
11207179404Sobrien  old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
11208179404Sobrien
11209179404Sobrien  /* Compare the ISAs.  */
11210179404Sobrien  if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
11211179404Sobrien    {
11212179404Sobrien      (*_bfd_error_handler)
11213218822Sdim	(_("%B: linking 32-bit code with 64-bit code"),
11214218822Sdim	 ibfd);
11215179404Sobrien      ok = FALSE;
11216179404Sobrien    }
11217179404Sobrien  else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd)))
11218179404Sobrien    {
11219179404Sobrien      /* OBFD's ISA isn't the same as, or an extension of, IBFD's.  */
11220179404Sobrien      if (mips_mach_extends_p (bfd_get_mach (obfd), bfd_get_mach (ibfd)))
11221179404Sobrien	{
11222179404Sobrien	  /* Copy the architecture info from IBFD to OBFD.  Also copy
11223179404Sobrien	     the 32-bit flag (if set) so that we continue to recognise
11224179404Sobrien	     OBFD as a 32-bit binary.  */
11225179404Sobrien	  bfd_set_arch_info (obfd, bfd_get_arch_info (ibfd));
11226179404Sobrien	  elf_elfheader (obfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
11227179404Sobrien	  elf_elfheader (obfd)->e_flags
11228179404Sobrien	    |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
11229179404Sobrien
11230179404Sobrien	  /* Copy across the ABI flags if OBFD doesn't use them
11231179404Sobrien	     and if that was what caused us to treat IBFD as 32-bit.  */
11232179404Sobrien	  if ((old_flags & EF_MIPS_ABI) == 0
11233179404Sobrien	      && mips_32bit_flags_p (new_flags)
11234179404Sobrien	      && !mips_32bit_flags_p (new_flags & ~EF_MIPS_ABI))
11235179404Sobrien	    elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ABI;
11236179404Sobrien	}
11237179404Sobrien      else
11238179404Sobrien	{
11239179404Sobrien	  /* The ISAs aren't compatible.  */
11240179404Sobrien	  (*_bfd_error_handler)
11241218822Sdim	    (_("%B: linking %s module with previous %s modules"),
11242218822Sdim	     ibfd,
11243179404Sobrien	     bfd_printable_name (ibfd),
11244179404Sobrien	     bfd_printable_name (obfd));
11245179404Sobrien	  ok = FALSE;
11246179404Sobrien	}
11247179404Sobrien    }
11248179404Sobrien
11249179404Sobrien  new_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
11250179404Sobrien  old_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
11251179404Sobrien
11252179404Sobrien  /* Compare ABIs.  The 64-bit ABI does not use EF_MIPS_ABI.  But, it
11253179404Sobrien     does set EI_CLASS differently from any 32-bit ABI.  */
11254179404Sobrien  if ((new_flags & EF_MIPS_ABI) != (old_flags & EF_MIPS_ABI)
11255179404Sobrien      || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
11256179404Sobrien	  != elf_elfheader (obfd)->e_ident[EI_CLASS]))
11257179404Sobrien    {
11258179404Sobrien      /* Only error if both are set (to different values).  */
11259179404Sobrien      if (((new_flags & EF_MIPS_ABI) && (old_flags & EF_MIPS_ABI))
11260179404Sobrien	  || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
11261179404Sobrien	      != elf_elfheader (obfd)->e_ident[EI_CLASS]))
11262179404Sobrien	{
11263179404Sobrien	  (*_bfd_error_handler)
11264218822Sdim	    (_("%B: ABI mismatch: linking %s module with previous %s modules"),
11265218822Sdim	     ibfd,
11266179404Sobrien	     elf_mips_abi_name (ibfd),
11267179404Sobrien	     elf_mips_abi_name (obfd));
11268179404Sobrien	  ok = FALSE;
11269179404Sobrien	}
11270179404Sobrien      new_flags &= ~EF_MIPS_ABI;
11271179404Sobrien      old_flags &= ~EF_MIPS_ABI;
11272179404Sobrien    }
11273179404Sobrien
11274179404Sobrien  /* For now, allow arbitrary mixing of ASEs (retain the union).  */
11275179404Sobrien  if ((new_flags & EF_MIPS_ARCH_ASE) != (old_flags & EF_MIPS_ARCH_ASE))
11276179404Sobrien    {
11277179404Sobrien      elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_ARCH_ASE;
11278179404Sobrien
11279179404Sobrien      new_flags &= ~ EF_MIPS_ARCH_ASE;
11280179404Sobrien      old_flags &= ~ EF_MIPS_ARCH_ASE;
11281179404Sobrien    }
11282179404Sobrien
11283179404Sobrien  /* Warn about any other mismatches */
11284179404Sobrien  if (new_flags != old_flags)
11285179404Sobrien    {
11286179404Sobrien      (*_bfd_error_handler)
11287218822Sdim	(_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
11288218822Sdim	 ibfd, (unsigned long) new_flags,
11289179404Sobrien	 (unsigned long) old_flags);
11290179404Sobrien      ok = FALSE;
11291179404Sobrien    }
11292179404Sobrien
11293179404Sobrien  if (! ok)
11294179404Sobrien    {
11295179404Sobrien      bfd_set_error (bfd_error_bad_value);
11296179404Sobrien      return FALSE;
11297179404Sobrien    }
11298179404Sobrien
11299179404Sobrien  return TRUE;
11300179404Sobrien}
11301179404Sobrien
11302179404Sobrien/* Function to keep MIPS specific file flags like as EF_MIPS_PIC.  */
11303179404Sobrien
11304179404Sobrienbfd_boolean
11305179404Sobrien_bfd_mips_elf_set_private_flags (bfd *abfd, flagword flags)
11306179404Sobrien{
11307179404Sobrien  BFD_ASSERT (!elf_flags_init (abfd)
11308179404Sobrien	      || elf_elfheader (abfd)->e_flags == flags);
11309179404Sobrien
11310179404Sobrien  elf_elfheader (abfd)->e_flags = flags;
11311179404Sobrien  elf_flags_init (abfd) = TRUE;
11312179404Sobrien  return TRUE;
11313179404Sobrien}
11314179404Sobrien
11315179404Sobrienbfd_boolean
11316179404Sobrien_bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
11317179404Sobrien{
11318179404Sobrien  FILE *file = ptr;
11319179404Sobrien
11320179404Sobrien  BFD_ASSERT (abfd != NULL && ptr != NULL);
11321179404Sobrien
11322179404Sobrien  /* Print normal ELF private data.  */
11323179404Sobrien  _bfd_elf_print_private_bfd_data (abfd, ptr);
11324179404Sobrien
11325179404Sobrien  /* xgettext:c-format */
11326179404Sobrien  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
11327179404Sobrien
11328179404Sobrien  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O32)
11329179404Sobrien    fprintf (file, _(" [abi=O32]"));
11330179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O64)
11331179404Sobrien    fprintf (file, _(" [abi=O64]"));
11332179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32)
11333179404Sobrien    fprintf (file, _(" [abi=EABI32]"));
11334179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
11335179404Sobrien    fprintf (file, _(" [abi=EABI64]"));
11336179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI))
11337179404Sobrien    fprintf (file, _(" [abi unknown]"));
11338179404Sobrien  else if (ABI_N32_P (abfd))
11339179404Sobrien    fprintf (file, _(" [abi=N32]"));
11340179404Sobrien  else if (ABI_64_P (abfd))
11341179404Sobrien    fprintf (file, _(" [abi=64]"));
11342179404Sobrien  else
11343179404Sobrien    fprintf (file, _(" [no abi set]"));
11344179404Sobrien
11345179404Sobrien  if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
11346218822Sdim    fprintf (file, " [mips1]");
11347179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
11348218822Sdim    fprintf (file, " [mips2]");
11349179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
11350218822Sdim    fprintf (file, " [mips3]");
11351179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
11352218822Sdim    fprintf (file, " [mips4]");
11353179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5)
11354218822Sdim    fprintf (file, " [mips5]");
11355179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32)
11356218822Sdim    fprintf (file, " [mips32]");
11357179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64)
11358218822Sdim    fprintf (file, " [mips64]");
11359179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2)
11360218822Sdim    fprintf (file, " [mips32r2]");
11361179404Sobrien  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
11362218822Sdim    fprintf (file, " [mips64r2]");
11363179404Sobrien  else
11364179404Sobrien    fprintf (file, _(" [unknown ISA]"));
11365179404Sobrien
11366179404Sobrien  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MDMX)
11367218822Sdim    fprintf (file, " [mdmx]");
11368179404Sobrien
11369179404Sobrien  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_M16)
11370218822Sdim    fprintf (file, " [mips16]");
11371179404Sobrien
11372179404Sobrien  if (elf_elfheader (abfd)->e_flags & EF_MIPS_32BITMODE)
11373218822Sdim    fprintf (file, " [32bitmode]");
11374179404Sobrien  else
11375179404Sobrien    fprintf (file, _(" [not 32bitmode]"));
11376179404Sobrien
11377218822Sdim  if (elf_elfheader (abfd)->e_flags & EF_MIPS_NOREORDER)
11378218822Sdim    fprintf (file, " [noreorder]");
11379218822Sdim
11380218822Sdim  if (elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
11381218822Sdim    fprintf (file, " [PIC]");
11382218822Sdim
11383218822Sdim  if (elf_elfheader (abfd)->e_flags & EF_MIPS_CPIC)
11384218822Sdim    fprintf (file, " [CPIC]");
11385218822Sdim
11386218822Sdim  if (elf_elfheader (abfd)->e_flags & EF_MIPS_XGOT)
11387218822Sdim    fprintf (file, " [XGOT]");
11388218822Sdim
11389218822Sdim  if (elf_elfheader (abfd)->e_flags & EF_MIPS_UCODE)
11390218822Sdim    fprintf (file, " [UCODE]");
11391218822Sdim
11392179404Sobrien  fputc ('\n', file);
11393179404Sobrien
11394179404Sobrien  return TRUE;
11395179404Sobrien}
11396179404Sobrien
11397218822Sdimconst struct bfd_elf_special_section _bfd_mips_elf_special_sections[] =
11398179404Sobrien{
11399218822Sdim  { STRING_COMMA_LEN (".lit4"),   0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
11400218822Sdim  { STRING_COMMA_LEN (".lit8"),   0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
11401218822Sdim  { STRING_COMMA_LEN (".mdebug"), 0, SHT_MIPS_DEBUG, 0 },
11402218822Sdim  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,     SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
11403218822Sdim  { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
11404218822Sdim  { STRING_COMMA_LEN (".ucode"),  0, SHT_MIPS_UCODE, 0 },
11405218822Sdim  { NULL,                     0,  0, 0,              0 }
11406179404Sobrien};
11407218822Sdim
11408218822Sdim/* Merge non visibility st_other attributes.  Ensure that the
11409218822Sdim   STO_OPTIONAL flag is copied into h->other, even if this is not a
11410218822Sdim   definiton of the symbol.  */
11411218822Sdimvoid
11412218822Sdim_bfd_mips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
11413218822Sdim				      const Elf_Internal_Sym *isym,
11414218822Sdim				      bfd_boolean definition,
11415218822Sdim				      bfd_boolean dynamic ATTRIBUTE_UNUSED)
11416218822Sdim{
11417218822Sdim  if ((isym->st_other & ~ELF_ST_VISIBILITY (-1)) != 0)
11418218822Sdim    {
11419218822Sdim      unsigned char other;
11420218822Sdim
11421218822Sdim      other = (definition ? isym->st_other : h->other);
11422218822Sdim      other &= ~ELF_ST_VISIBILITY (-1);
11423218822Sdim      h->other = other | ELF_ST_VISIBILITY (h->other);
11424218822Sdim    }
11425218822Sdim
11426218822Sdim  if (!definition
11427218822Sdim      && ELF_MIPS_IS_OPTIONAL (isym->st_other))
11428218822Sdim    h->other |= STO_OPTIONAL;
11429218822Sdim}
11430218822Sdim
11431218822Sdim/* Decide whether an undefined symbol is special and can be ignored.
11432218822Sdim   This is the case for OPTIONAL symbols on IRIX.  */
11433218822Sdimbfd_boolean
11434218822Sdim_bfd_mips_elf_ignore_undef_symbol (struct elf_link_hash_entry *h)
11435218822Sdim{
11436218822Sdim  return ELF_MIPS_IS_OPTIONAL (h->other) ? TRUE : FALSE;
11437218822Sdim}
11438218822Sdim
11439218822Sdimbfd_boolean
11440218822Sdim_bfd_mips_elf_common_definition (Elf_Internal_Sym *sym)
11441218822Sdim{
11442218822Sdim  return (sym->st_shndx == SHN_COMMON
11443218822Sdim	  || sym->st_shndx == SHN_MIPS_ACOMMON
11444218822Sdim	  || sym->st_shndx == SHN_MIPS_SCOMMON);
11445218822Sdim}
11446