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 (®info, 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, ®info, &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