Line 434... |
Line 434... |
|
|
/* This flag indicates that the value of DT_MIPS_RLD_MAP dynamic
|
/* This flag indicates that the value of DT_MIPS_RLD_MAP dynamic
|
entry is set to the address of __rld_obj_head as in IRIX5. */
|
entry is set to the address of __rld_obj_head as in IRIX5. */
|
bfd_boolean use_rld_obj_head;
|
bfd_boolean use_rld_obj_head;
|
|
|
/* This is the value of the __rld_map or __rld_obj_head symbol. */
|
/* The __rld_map or __rld_obj_head symbol. */
|
bfd_vma rld_value;
|
struct elf_link_hash_entry *rld_symbol;
|
|
|
/* This is set if we see any mips16 stub sections. */
|
/* This is set if we see any mips16 stub sections. */
|
bfd_boolean mips16_stubs_seen;
|
bfd_boolean mips16_stubs_seen;
|
|
|
/* True if we can generate copy relocs and PLTs. */
|
/* True if we can generate copy relocs and PLTs. */
|
Line 527... |
Line 527... |
|| r_type == R_MIPS_TLS_GOTTPREL \
|
|| r_type == R_MIPS_TLS_GOTTPREL \
|
|| r_type == R_MIPS_TLS_TPREL32 \
|
|| r_type == R_MIPS_TLS_TPREL32 \
|
|| r_type == R_MIPS_TLS_TPREL64 \
|
|| r_type == R_MIPS_TLS_TPREL64 \
|
|| r_type == R_MIPS_TLS_TPREL_HI16 \
|
|| r_type == R_MIPS_TLS_TPREL_HI16 \
|
|| r_type == R_MIPS_TLS_TPREL_LO16 \
|
|| r_type == R_MIPS_TLS_TPREL_LO16 \
|
|
|| r_type == R_MIPS16_TLS_GD \
|
|
|| r_type == R_MIPS16_TLS_LDM \
|
|
|| r_type == R_MIPS16_TLS_DTPREL_HI16 \
|
|
|| r_type == R_MIPS16_TLS_DTPREL_LO16 \
|
|
|| r_type == R_MIPS16_TLS_GOTTPREL \
|
|
|| r_type == R_MIPS16_TLS_TPREL_HI16 \
|
|
|| r_type == R_MIPS16_TLS_TPREL_LO16 \
|
|| r_type == R_MICROMIPS_TLS_GD \
|
|| r_type == R_MICROMIPS_TLS_GD \
|
|| r_type == R_MICROMIPS_TLS_LDM \
|
|| r_type == R_MICROMIPS_TLS_LDM \
|
|| r_type == R_MICROMIPS_TLS_DTPREL_HI16 \
|
|| r_type == R_MICROMIPS_TLS_DTPREL_HI16 \
|
|| r_type == R_MICROMIPS_TLS_DTPREL_LO16 \
|
|| r_type == R_MICROMIPS_TLS_DTPREL_LO16 \
|
|| r_type == R_MICROMIPS_TLS_GOTTPREL \
|
|| r_type == R_MICROMIPS_TLS_GOTTPREL \
|
Line 766... |
Line 773... |
|
|
/* The size of a GOT entry. */
|
/* The size of a GOT entry. */
|
#define MIPS_ELF_GOT_SIZE(abfd) \
|
#define MIPS_ELF_GOT_SIZE(abfd) \
|
(get_elf_backend_data (abfd)->s->arch_size / 8)
|
(get_elf_backend_data (abfd)->s->arch_size / 8)
|
|
|
|
/* The size of the .rld_map section. */
|
|
#define MIPS_ELF_RLD_MAP_SIZE(abfd) \
|
|
(get_elf_backend_data (abfd)->s->arch_size / 8)
|
|
|
/* The size of a symbol-table entry. */
|
/* The size of a symbol-table entry. */
|
#define MIPS_ELF_SYM_SIZE(abfd) \
|
#define MIPS_ELF_SYM_SIZE(abfd) \
|
(get_elf_backend_data (abfd)->s->sizeof_sym)
|
(get_elf_backend_data (abfd)->s->sizeof_sym)
|
|
|
/* The default alignment for sections, as a power of two. */
|
/* The default alignment for sections, as a power of two. */
|
Line 915... |
Line 926... |
{
|
{
|
0x3c1c0000, /* lui $28, %hi(&GOTPLT[0]) */
|
0x3c1c0000, /* lui $28, %hi(&GOTPLT[0]) */
|
0x8f990000, /* lw $25, %lo(&GOTPLT[0])($28) */
|
0x8f990000, /* lw $25, %lo(&GOTPLT[0])($28) */
|
0x279c0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */
|
0x279c0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */
|
0x031cc023, /* subu $24, $24, $28 */
|
0x031cc023, /* subu $24, $24, $28 */
|
0x03e07821, /* move $15, $31 */
|
0x03e07821, /* move $15, $31 # 32-bit move (addu) */
|
0x0018c082, /* srl $24, $24, 2 */
|
0x0018c082, /* srl $24, $24, 2 */
|
0x0320f809, /* jalr $25 */
|
0x0320f809, /* jalr $25 */
|
0x2718fffe /* subu $24, $24, 2 */
|
0x2718fffe /* subu $24, $24, 2 */
|
};
|
};
|
|
|
Line 929... |
Line 940... |
{
|
{
|
0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */
|
0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */
|
0x8dd90000, /* lw $25, %lo(&GOTPLT[0])($14) */
|
0x8dd90000, /* lw $25, %lo(&GOTPLT[0])($14) */
|
0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */
|
0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */
|
0x030ec023, /* subu $24, $24, $14 */
|
0x030ec023, /* subu $24, $24, $14 */
|
0x03e07821, /* move $15, $31 */
|
0x03e07821, /* move $15, $31 # 32-bit move (addu) */
|
0x0018c082, /* srl $24, $24, 2 */
|
0x0018c082, /* srl $24, $24, 2 */
|
0x0320f809, /* jalr $25 */
|
0x0320f809, /* jalr $25 */
|
0x2718fffe /* subu $24, $24, 2 */
|
0x2718fffe /* subu $24, $24, 2 */
|
};
|
};
|
|
|
Line 943... |
Line 954... |
{
|
{
|
0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */
|
0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */
|
0xddd90000, /* ld $25, %lo(&GOTPLT[0])($14) */
|
0xddd90000, /* ld $25, %lo(&GOTPLT[0])($14) */
|
0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */
|
0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */
|
0x030ec023, /* subu $24, $24, $14 */
|
0x030ec023, /* subu $24, $24, $14 */
|
0x03e07821, /* move $15, $31 */
|
0x03e0782d, /* move $15, $31 # 64-bit move (daddu) */
|
0x0018c0c2, /* srl $24, $24, 3 */
|
0x0018c0c2, /* srl $24, $24, 3 */
|
0x0320f809, /* jalr $25 */
|
0x0320f809, /* jalr $25 */
|
0x2718fffe /* subu $24, $24, 2 */
|
0x2718fffe /* subu $24, $24, 2 */
|
};
|
};
|
|
|
Line 1569... |
Line 1580... |
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* Return true if H is a locally-defined PIC function, in the sense
|
/* Return true if H is a locally-defined PIC function, in the sense
|
that it might need $25 to be valid on entry. Note that MIPS16
|
that it or its fn_stub might need $25 to be valid on entry.
|
functions never need $25 to be valid on entry; they set up $gp
|
Note that MIPS16 functions set up $gp using PC-relative instructions,
|
using PC-relative instructions instead. */
|
so they themselves never need $25 to be valid. Only non-MIPS16
|
|
entry points are of interest here. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h)
|
mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h)
|
{
|
{
|
return ((h->root.root.type == bfd_link_hash_defined
|
return ((h->root.root.type == bfd_link_hash_defined
|
|| h->root.root.type == bfd_link_hash_defweak)
|
|| h->root.root.type == bfd_link_hash_defweak)
|
&& h->root.def_regular
|
&& h->root.def_regular
|
&& !bfd_is_abs_section (h->root.root.u.def.section)
|
&& !bfd_is_abs_section (h->root.root.u.def.section)
|
&& !ELF_ST_IS_MIPS16 (h->root.other)
|
&& (!ELF_ST_IS_MIPS16 (h->root.other)
|
|
|| (h->fn_stub && h->need_fn_stub))
|
&& (PIC_OBJECT_P (h->root.root.u.def.section->owner)
|
&& (PIC_OBJECT_P (h->root.root.u.def.section->owner)
|
|| ELF_ST_IS_MIPS_PIC (h->root.other)));
|
|| ELF_ST_IS_MIPS_PIC (h->root.other)));
|
}
|
}
|
|
|
|
/* Set *SEC to the input section that contains the target of STUB.
|
|
Return the offset of the target from the start of that section. */
|
|
|
|
static bfd_vma
|
|
mips_elf_get_la25_target (struct mips_elf_la25_stub *stub,
|
|
asection **sec)
|
|
{
|
|
if (ELF_ST_IS_MIPS16 (stub->h->root.other))
|
|
{
|
|
BFD_ASSERT (stub->h->need_fn_stub);
|
|
*sec = stub->h->fn_stub;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
*sec = stub->h->root.root.u.def.section;
|
|
return stub->h->root.root.u.def.value;
|
|
}
|
|
}
|
|
|
/* STUB describes an la25 stub that we have decided to implement
|
/* STUB describes an la25 stub that we have decided to implement
|
by inserting an LUI/ADDIU pair before the target function.
|
by inserting an LUI/ADDIU pair before the target function.
|
Create the section and redirect the function symbol to it. */
|
Create the section and redirect the function symbol to it. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
Line 1609... |
Line 1642... |
if (name == NULL)
|
if (name == NULL)
|
return FALSE;
|
return FALSE;
|
sprintf (name, ".text.stub.%d", (int) htab_elements (htab->la25_stubs));
|
sprintf (name, ".text.stub.%d", (int) htab_elements (htab->la25_stubs));
|
|
|
/* Create the section. */
|
/* Create the section. */
|
input_section = stub->h->root.root.u.def.section;
|
mips_elf_get_la25_target (stub, &input_section);
|
s = htab->add_stub_section (name, input_section,
|
s = htab->add_stub_section (name, input_section,
|
input_section->output_section);
|
input_section->output_section);
|
if (s == NULL)
|
if (s == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
Line 1683... |
Line 1716... |
bfd_boolean use_trampoline_p;
|
bfd_boolean use_trampoline_p;
|
asection *s;
|
asection *s;
|
bfd_vma value;
|
bfd_vma value;
|
void **slot;
|
void **slot;
|
|
|
/* Prefer to use LUI/ADDIU stubs if the function is at the beginning
|
|
of the section and if we would need no more than 2 nops. */
|
|
s = h->root.root.u.def.section;
|
|
value = h->root.root.u.def.value;
|
|
use_trampoline_p = (value != 0 || s->alignment_power > 4);
|
|
|
|
/* Describe the stub we want. */
|
/* Describe the stub we want. */
|
search.stub_section = NULL;
|
search.stub_section = NULL;
|
search.offset = 0;
|
search.offset = 0;
|
search.h = h;
|
search.h = h;
|
|
|
Line 1718... |
Line 1745... |
if (stub == NULL)
|
if (stub == NULL)
|
return FALSE;
|
return FALSE;
|
*stub = search;
|
*stub = search;
|
*slot = stub;
|
*slot = stub;
|
|
|
|
/* Prefer to use LUI/ADDIU stubs if the function is at the beginning
|
|
of the section and if we would need no more than 2 nops. */
|
|
value = mips_elf_get_la25_target (stub, &s);
|
|
use_trampoline_p = (value != 0 || s->alignment_power > 4);
|
|
|
h->la25_stub = stub;
|
h->la25_stub = stub;
|
return (use_trampoline_p
|
return (use_trampoline_p
|
? mips_elf_add_la25_trampoline (stub, info)
|
? mips_elf_add_la25_trampoline (stub, info)
|
: mips_elf_add_la25_intro (stub, info));
|
: mips_elf_add_la25_intro (stub, info));
|
}
|
}
|
Line 1858... |
Line 1890... |
case R_MIPS16_GPREL:
|
case R_MIPS16_GPREL:
|
case R_MIPS16_GOT16:
|
case R_MIPS16_GOT16:
|
case R_MIPS16_CALL16:
|
case R_MIPS16_CALL16:
|
case R_MIPS16_HI16:
|
case R_MIPS16_HI16:
|
case R_MIPS16_LO16:
|
case R_MIPS16_LO16:
|
|
case R_MIPS16_TLS_GD:
|
|
case R_MIPS16_TLS_LDM:
|
|
case R_MIPS16_TLS_DTPREL_HI16:
|
|
case R_MIPS16_TLS_DTPREL_LO16:
|
|
case R_MIPS16_TLS_GOTTPREL:
|
|
case R_MIPS16_TLS_TPREL_HI16:
|
|
case R_MIPS16_TLS_TPREL_LO16:
|
return TRUE;
|
return TRUE;
|
|
|
default:
|
default:
|
return FALSE;
|
return FALSE;
|
}
|
}
|
Line 1985... |
Line 2024... |
}
|
}
|
|
|
static inline bfd_boolean
|
static inline bfd_boolean
|
tls_gd_reloc_p (unsigned int r_type)
|
tls_gd_reloc_p (unsigned int r_type)
|
{
|
{
|
return r_type == R_MIPS_TLS_GD || r_type == R_MICROMIPS_TLS_GD;
|
return (r_type == R_MIPS_TLS_GD
|
|
|| r_type == R_MIPS16_TLS_GD
|
|
|| r_type == R_MICROMIPS_TLS_GD);
|
}
|
}
|
|
|
static inline bfd_boolean
|
static inline bfd_boolean
|
tls_ldm_reloc_p (unsigned int r_type)
|
tls_ldm_reloc_p (unsigned int r_type)
|
{
|
{
|
return r_type == R_MIPS_TLS_LDM || r_type == R_MICROMIPS_TLS_LDM;
|
return (r_type == R_MIPS_TLS_LDM
|
|
|| r_type == R_MIPS16_TLS_LDM
|
|
|| r_type == R_MICROMIPS_TLS_LDM);
|
}
|
}
|
|
|
static inline bfd_boolean
|
static inline bfd_boolean
|
tls_gottprel_reloc_p (unsigned int r_type)
|
tls_gottprel_reloc_p (unsigned int r_type)
|
{
|
{
|
return r_type == R_MIPS_TLS_GOTTPREL || r_type == R_MICROMIPS_TLS_GOTTPREL;
|
return (r_type == R_MIPS_TLS_GOTTPREL
|
|
|| r_type == R_MIPS16_TLS_GOTTPREL
|
|
|| r_type == R_MICROMIPS_TLS_GOTTPREL);
|
}
|
}
|
|
|
void
|
void
|
_bfd_mips_elf_reloc_unshuffle (bfd *abfd, int r_type,
|
_bfd_mips_elf_reloc_unshuffle (bfd *abfd, int r_type,
|
bfd_boolean jal_shuffle, bfd_byte *data)
|
bfd_boolean jal_shuffle, bfd_byte *data)
|
Line 4905... |
Line 4950... |
require an la25 stub. See also mips_elf_local_pic_function_p,
|
require an la25 stub. See also mips_elf_local_pic_function_p,
|
which determines whether the destination function ever requires a
|
which determines whether the destination function ever requires a
|
stub. */
|
stub. */
|
|
|
static bfd_boolean
|
static bfd_boolean
|
mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type)
|
mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type,
|
|
bfd_boolean target_is_16_bit_code_p)
|
{
|
{
|
/* We specifically ignore branches and jumps from EF_PIC objects,
|
/* We specifically ignore branches and jumps from EF_PIC objects,
|
where the onus is on the compiler or programmer to perform any
|
where the onus is on the compiler or programmer to perform any
|
necessary initialization of $25. Sometimes such initialization
|
necessary initialization of $25. Sometimes such initialization
|
is unnecessary; for example, -mno-shared functions do not use
|
is unnecessary; for example, -mno-shared functions do not use
|
Line 4919... |
Line 4965... |
|
|
switch (r_type)
|
switch (r_type)
|
{
|
{
|
case R_MIPS_26:
|
case R_MIPS_26:
|
case R_MIPS_PC16:
|
case R_MIPS_PC16:
|
case R_MIPS16_26:
|
|
case R_MICROMIPS_26_S1:
|
case R_MICROMIPS_26_S1:
|
case R_MICROMIPS_PC7_S1:
|
case R_MICROMIPS_PC7_S1:
|
case R_MICROMIPS_PC10_S1:
|
case R_MICROMIPS_PC10_S1:
|
case R_MICROMIPS_PC16_S1:
|
case R_MICROMIPS_PC16_S1:
|
case R_MICROMIPS_PC23_S2:
|
case R_MICROMIPS_PC23_S2:
|
return TRUE;
|
return TRUE;
|
|
|
|
case R_MIPS16_26:
|
|
return !target_is_16_bit_code_p;
|
|
|
default:
|
default:
|
return FALSE;
|
return FALSE;
|
}
|
}
|
}
|
}
|
|
|
Line 5187... |
Line 5235... |
{
|
{
|
/* This is a 32- or 64-bit call to a 16-bit function. We should
|
/* This is a 32- or 64-bit call to a 16-bit function. We should
|
have already noticed that we were going to need the
|
have already noticed that we were going to need the
|
stub. */
|
stub. */
|
if (local_p)
|
if (local_p)
|
|
{
|
sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
|
sec = elf_tdata (input_bfd)->local_stubs[r_symndx];
|
|
value = 0;
|
|
}
|
else
|
else
|
{
|
{
|
BFD_ASSERT (h->need_fn_stub);
|
BFD_ASSERT (h->need_fn_stub);
|
|
if (h->la25_stub)
|
|
{
|
|
/* If a LA25 header for the stub itself exists, point to the
|
|
prepended LUI/ADDIU sequence. */
|
|
sec = h->la25_stub->stub_section;
|
|
value = h->la25_stub->offset;
|
|
}
|
|
else
|
|
{
|
sec = h->fn_stub;
|
sec = h->fn_stub;
|
|
value = 0;
|
|
}
|
}
|
}
|
|
|
symbol = sec->output_section->vma + sec->output_offset;
|
symbol = sec->output_section->vma + sec->output_offset + value;
|
/* The target is 16-bit, but the stub isn't. */
|
/* The target is 16-bit, but the stub isn't. */
|
target_is_16_bit_code_p = FALSE;
|
target_is_16_bit_code_p = FALSE;
|
}
|
}
|
/* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
|
/* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
|
need to redirect the call to the stub. Note that we specifically
|
need to redirect the call to the stub. Note that we specifically
|
Line 5244... |
Line 5306... |
symbol = sec->output_section->vma + sec->output_offset;
|
symbol = sec->output_section->vma + sec->output_offset;
|
}
|
}
|
/* If this is a direct call to a PIC function, redirect to the
|
/* If this is a direct call to a PIC function, redirect to the
|
non-PIC stub. */
|
non-PIC stub. */
|
else if (h != NULL && h->la25_stub
|
else if (h != NULL && h->la25_stub
|
&& mips_elf_relocation_needs_la25_stub (input_bfd, r_type))
|
&& mips_elf_relocation_needs_la25_stub (input_bfd, r_type,
|
|
target_is_16_bit_code_p))
|
symbol = (h->la25_stub->stub_section->output_section->vma
|
symbol = (h->la25_stub->stub_section->output_section->vma
|
+ h->la25_stub->stub_section->output_offset
|
+ h->la25_stub->stub_section->output_offset
|
+ h->la25_stub->offset);
|
+ h->la25_stub->offset);
|
|
|
/* Make sure MIPS16 and microMIPS are not used together. */
|
/* Make sure MIPS16 and microMIPS are not used together. */
|
Line 5316... |
Line 5379... |
case R_MICROMIPS_GOT_LO16:
|
case R_MICROMIPS_GOT_LO16:
|
case R_MICROMIPS_CALL_LO16:
|
case R_MICROMIPS_CALL_LO16:
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_LDM:
|
case R_MIPS_TLS_LDM:
|
|
case R_MIPS16_TLS_GD:
|
|
case R_MIPS16_TLS_GOTTPREL:
|
|
case R_MIPS16_TLS_LDM:
|
case R_MICROMIPS_TLS_GD:
|
case R_MICROMIPS_TLS_GD:
|
case R_MICROMIPS_TLS_GOTTPREL:
|
case R_MICROMIPS_TLS_GOTTPREL:
|
case R_MICROMIPS_TLS_LDM:
|
case R_MICROMIPS_TLS_LDM:
|
/* Find the index into the GOT where this value is located. */
|
/* Find the index into the GOT where this value is located. */
|
if (tls_ldm_reloc_p (r_type))
|
if (tls_ldm_reloc_p (r_type))
|
Line 5485... |
Line 5551... |
value &= howto->dst_mask;
|
value &= howto->dst_mask;
|
}
|
}
|
break;
|
break;
|
|
|
case R_MIPS_TLS_DTPREL_HI16:
|
case R_MIPS_TLS_DTPREL_HI16:
|
|
case R_MIPS16_TLS_DTPREL_HI16:
|
case R_MICROMIPS_TLS_DTPREL_HI16:
|
case R_MICROMIPS_TLS_DTPREL_HI16:
|
value = (mips_elf_high (addend + symbol - dtprel_base (info))
|
value = (mips_elf_high (addend + symbol - dtprel_base (info))
|
& howto->dst_mask);
|
& howto->dst_mask);
|
break;
|
break;
|
|
|
case R_MIPS_TLS_DTPREL_LO16:
|
case R_MIPS_TLS_DTPREL_LO16:
|
case R_MIPS_TLS_DTPREL32:
|
case R_MIPS_TLS_DTPREL32:
|
case R_MIPS_TLS_DTPREL64:
|
case R_MIPS_TLS_DTPREL64:
|
|
case R_MIPS16_TLS_DTPREL_LO16:
|
case R_MICROMIPS_TLS_DTPREL_LO16:
|
case R_MICROMIPS_TLS_DTPREL_LO16:
|
value = (symbol + addend - dtprel_base (info)) & howto->dst_mask;
|
value = (symbol + addend - dtprel_base (info)) & howto->dst_mask;
|
break;
|
break;
|
|
|
case R_MIPS_TLS_TPREL_HI16:
|
case R_MIPS_TLS_TPREL_HI16:
|
|
case R_MIPS16_TLS_TPREL_HI16:
|
case R_MICROMIPS_TLS_TPREL_HI16:
|
case R_MICROMIPS_TLS_TPREL_HI16:
|
value = (mips_elf_high (addend + symbol - tprel_base (info))
|
value = (mips_elf_high (addend + symbol - tprel_base (info))
|
& howto->dst_mask);
|
& howto->dst_mask);
|
break;
|
break;
|
|
|
case R_MIPS_TLS_TPREL_LO16:
|
case R_MIPS_TLS_TPREL_LO16:
|
|
case R_MIPS_TLS_TPREL32:
|
|
case R_MIPS_TLS_TPREL64:
|
|
case R_MIPS16_TLS_TPREL_LO16:
|
case R_MICROMIPS_TLS_TPREL_LO16:
|
case R_MICROMIPS_TLS_TPREL_LO16:
|
value = (symbol + addend - tprel_base (info)) & howto->dst_mask;
|
value = (symbol + addend - tprel_base (info)) & howto->dst_mask;
|
break;
|
break;
|
|
|
case R_MIPS_HI16:
|
case R_MIPS_HI16:
|
Line 5525... |
Line 5597... |
4: addiupc $v1,%lo(_gp_disp)
|
4: addiupc $v1,%lo(_gp_disp)
|
8: sll $v0,16
|
8: sll $v0,16
|
12: addu $v0,$v1
|
12: addu $v0,$v1
|
14: move $gp,$v0
|
14: move $gp,$v0
|
So the offsets of hi and lo relocs are the same, but the
|
So the offsets of hi and lo relocs are the same, but the
|
$pc is four higher than $t9 would be, so reduce
|
base $pc is that used by the ADDIUPC instruction at $t9 + 4.
|
both reloc addends by 4. */
|
ADDIUPC clears the low two bits of the instruction address,
|
|
so the base is ($t9 + 4) & ~3. */
|
if (r_type == R_MIPS16_HI16)
|
if (r_type == R_MIPS16_HI16)
|
value = mips_elf_high (addend + gp - p - 4);
|
value = mips_elf_high (addend + gp - ((p + 4) & ~(bfd_vma) 0x3));
|
/* The microMIPS .cpload sequence uses the same assembly
|
/* The microMIPS .cpload sequence uses the same assembly
|
instructions as the traditional psABI version, but the
|
instructions as the traditional psABI version, but the
|
incoming $t9 has the low bit set. */
|
incoming $t9 has the low bit set. */
|
else if (r_type == R_MICROMIPS_HI16)
|
else if (r_type == R_MICROMIPS_HI16)
|
value = mips_elf_high (addend + gp - p - 1);
|
value = mips_elf_high (addend + gp - p - 1);
|
Line 5551... |
Line 5624... |
else
|
else
|
{
|
{
|
/* See the comment for R_MIPS16_HI16 above for the reason
|
/* See the comment for R_MIPS16_HI16 above for the reason
|
for this conditional. */
|
for this conditional. */
|
if (r_type == R_MIPS16_LO16)
|
if (r_type == R_MIPS16_LO16)
|
value = addend + gp - p;
|
value = addend + gp - (p & ~(bfd_vma) 0x3);
|
else if (r_type == R_MICROMIPS_LO16
|
else if (r_type == R_MICROMIPS_LO16
|
|| r_type == R_MICROMIPS_HI0_LO16)
|
|| r_type == R_MICROMIPS_HI0_LO16)
|
value = addend + gp - p + 3;
|
value = addend + gp - p + 3;
|
else
|
else
|
value = addend + gp - p + 4;
|
value = addend + gp - p + 4;
|
Line 5635... |
Line 5708... |
|
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_LDM:
|
case R_MIPS_TLS_LDM:
|
case R_MIPS_GOT_DISP:
|
case R_MIPS_GOT_DISP:
|
|
case R_MIPS16_TLS_GD:
|
|
case R_MIPS16_TLS_GOTTPREL:
|
|
case R_MIPS16_TLS_LDM:
|
case R_MICROMIPS_TLS_GD:
|
case R_MICROMIPS_TLS_GD:
|
case R_MICROMIPS_TLS_GOTTPREL:
|
case R_MICROMIPS_TLS_GOTTPREL:
|
case R_MICROMIPS_TLS_LDM:
|
case R_MICROMIPS_TLS_LDM:
|
case R_MICROMIPS_GOT_DISP:
|
case R_MICROMIPS_GOT_DISP:
|
value = g;
|
value = g;
|
Line 6180... |
Line 6256... |
return bfd_mach_mips_loongson_2f;
|
return bfd_mach_mips_loongson_2f;
|
|
|
case E_MIPS_MACH_LS3A:
|
case E_MIPS_MACH_LS3A:
|
return bfd_mach_mips_loongson_3a;
|
return bfd_mach_mips_loongson_3a;
|
|
|
|
case E_MIPS_MACH_OCTEON2:
|
|
return bfd_mach_mips_octeon2;
|
|
|
case E_MIPS_MACH_OCTEON:
|
case E_MIPS_MACH_OCTEON:
|
return bfd_mach_mips_octeon;
|
return bfd_mach_mips_octeon;
|
|
|
case E_MIPS_MACH_XLR:
|
case E_MIPS_MACH_XLR:
|
return bfd_mach_mips_xlr;
|
return bfd_mach_mips_xlr;
|
Line 7077... |
Line 7156... |
|
|
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
return FALSE;
|
return FALSE;
|
|
|
mips_elf_hash_table (info)->use_rld_obj_head = TRUE;
|
mips_elf_hash_table (info)->use_rld_obj_head = TRUE;
|
|
mips_elf_hash_table (info)->rld_symbol = h;
|
}
|
}
|
|
|
/* If this is a mips16 text symbol, add 1 to the value to make it
|
/* If this is a mips16 text symbol, add 1 to the value to make it
|
odd. This will cause something like .word SYM to come up with
|
odd. This will cause something like .word SYM to come up with
|
the right value when it is loaded into the PC. */
|
the right value when it is loaded into the PC. */
|
Line 7262... |
Line 7342... |
h->def_regular = 1;
|
h->def_regular = 1;
|
h->type = STT_OBJECT;
|
h->type = STT_OBJECT;
|
|
|
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
return FALSE;
|
return FALSE;
|
|
mips_elf_hash_table (info)->rld_symbol = h;
|
}
|
}
|
}
|
}
|
|
|
/* Create the .plt, .rel(a).plt, .dynbss and .rel(a).bss sections.
|
/* Create the .plt, .rel(a).plt, .dynbss and .rel(a).bss sections.
|
Also create the _PROCEDURE_LINKAGE_TABLE symbol. */
|
Also create the _PROCEDURE_LINKAGE_TABLE symbol. */
|
Line 7763... |
Line 7844... |
/* Set CAN_MAKE_DYNAMIC_P to true if we can convert this
|
/* Set CAN_MAKE_DYNAMIC_P to true if we can convert this
|
relocation into a dynamic one. */
|
relocation into a dynamic one. */
|
can_make_dynamic_p = FALSE;
|
can_make_dynamic_p = FALSE;
|
switch (r_type)
|
switch (r_type)
|
{
|
{
|
case R_MIPS16_GOT16:
|
|
case R_MIPS16_CALL16:
|
|
case R_MIPS_GOT16:
|
case R_MIPS_GOT16:
|
case R_MIPS_CALL16:
|
case R_MIPS_CALL16:
|
case R_MIPS_CALL_HI16:
|
case R_MIPS_CALL_HI16:
|
case R_MIPS_CALL_LO16:
|
case R_MIPS_CALL_LO16:
|
case R_MIPS_GOT_HI16:
|
case R_MIPS_GOT_HI16:
|
Line 7777... |
Line 7856... |
case R_MIPS_GOT_OFST:
|
case R_MIPS_GOT_OFST:
|
case R_MIPS_GOT_DISP:
|
case R_MIPS_GOT_DISP:
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_LDM:
|
case R_MIPS_TLS_LDM:
|
|
case R_MIPS16_GOT16:
|
|
case R_MIPS16_CALL16:
|
|
case R_MIPS16_TLS_GOTTPREL:
|
|
case R_MIPS16_TLS_GD:
|
|
case R_MIPS16_TLS_LDM:
|
case R_MICROMIPS_GOT16:
|
case R_MICROMIPS_GOT16:
|
case R_MICROMIPS_CALL16:
|
case R_MICROMIPS_CALL16:
|
case R_MICROMIPS_CALL_HI16:
|
case R_MICROMIPS_CALL_HI16:
|
case R_MICROMIPS_CALL_LO16:
|
case R_MICROMIPS_CALL_LO16:
|
case R_MICROMIPS_GOT_HI16:
|
case R_MICROMIPS_GOT_HI16:
|
Line 7914... |
Line 7998... |
if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
|
if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
|
rel->r_addend, info, 0))
|
rel->r_addend, info, 0))
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
if (h != NULL && mips_elf_relocation_needs_la25_stub (abfd, r_type))
|
if (h != NULL
|
|
&& mips_elf_relocation_needs_la25_stub (abfd, r_type,
|
|
ELF_ST_IS_MIPS16 (h->other)))
|
((struct mips_elf_link_hash_entry *) h)->has_nonpic_branches = TRUE;
|
((struct mips_elf_link_hash_entry *) h)->has_nonpic_branches = TRUE;
|
|
|
switch (r_type)
|
switch (r_type)
|
{
|
{
|
case R_MIPS_CALL16:
|
case R_MIPS_CALL16:
|
Line 8011... |
Line 8097... |
FALSE, 0))
|
FALSE, 0))
|
return FALSE;
|
return FALSE;
|
break;
|
break;
|
|
|
case R_MIPS_TLS_GOTTPREL:
|
case R_MIPS_TLS_GOTTPREL:
|
|
case R_MIPS16_TLS_GOTTPREL:
|
case R_MICROMIPS_TLS_GOTTPREL:
|
case R_MICROMIPS_TLS_GOTTPREL:
|
if (info->shared)
|
if (info->shared)
|
info->flags |= DF_STATIC_TLS;
|
info->flags |= DF_STATIC_TLS;
|
/* Fall through */
|
/* Fall through */
|
|
|
case R_MIPS_TLS_LDM:
|
case R_MIPS_TLS_LDM:
|
|
case R_MIPS16_TLS_LDM:
|
case R_MICROMIPS_TLS_LDM:
|
case R_MICROMIPS_TLS_LDM:
|
if (tls_ldm_reloc_p (r_type))
|
if (tls_ldm_reloc_p (r_type))
|
{
|
{
|
r_symndx = STN_UNDEF;
|
r_symndx = STN_UNDEF;
|
h = NULL;
|
h = NULL;
|
}
|
}
|
/* Fall through */
|
/* Fall through */
|
|
|
case R_MIPS_TLS_GD:
|
case R_MIPS_TLS_GD:
|
|
case R_MIPS16_TLS_GD:
|
case R_MICROMIPS_TLS_GD:
|
case R_MICROMIPS_TLS_GD:
|
/* This symbol requires a global offset table entry, or two
|
/* This symbol requires a global offset table entry, or two
|
for TLS GD relocations. */
|
for TLS GD relocations. */
|
{
|
{
|
unsigned char flag;
|
unsigned char flag;
|
Line 9023... |
Line 9112... |
&& ! mips_elf_hash_table (info)->use_rld_obj_head
|
&& ! mips_elf_hash_table (info)->use_rld_obj_head
|
&& CONST_STRNEQ (name, ".rld_map"))
|
&& CONST_STRNEQ (name, ".rld_map"))
|
{
|
{
|
/* We add a room for __rld_map. It will be filled in by the
|
/* We add a room for __rld_map. It will be filled in by the
|
rtld to contain a pointer to the _r_debug structure. */
|
rtld to contain a pointer to the _r_debug structure. */
|
s->size += 4;
|
s->size += MIPS_ELF_RLD_MAP_SIZE (output_bfd);
|
}
|
}
|
else if (SGI_COMPAT (output_bfd)
|
else if (SGI_COMPAT (output_bfd)
|
&& CONST_STRNEQ (name, ".compact_rel"))
|
&& CONST_STRNEQ (name, ".compact_rel"))
|
s->size += mips_elf_hash_table (info)->compact_rel_size;
|
s->size += mips_elf_hash_table (info)->compact_rel_size;
|
else if (s == htab->splt)
|
else if (s == htab->splt)
|
Line 9611... |
Line 9700... |
|
|
/* Work out where in the section this stub should go. */
|
/* Work out where in the section this stub should go. */
|
offset = stub->offset;
|
offset = stub->offset;
|
|
|
/* Work out the target address. */
|
/* Work out the target address. */
|
target = (stub->h->root.root.u.def.section->output_section->vma
|
target = mips_elf_get_la25_target (stub, &s);
|
+ stub->h->root.root.u.def.section->output_offset
|
target += s->output_section->vma + s->output_offset;
|
+ stub->h->root.root.u.def.value);
|
|
target_high = ((target + 0x8000) >> 16) & 0xffff;
|
target_high = ((target + 0x8000) >> 16) & 0xffff;
|
target_low = (target & 0xffff);
|
target_low = (target & 0xffff);
|
|
|
if (stub->stub_section != htab->strampoline)
|
if (stub->stub_section != htab->strampoline)
|
{
|
{
|
Line 10026... |
Line 10115... |
|
|
/* Handle the IRIX6-specific symbols. */
|
/* Handle the IRIX6-specific symbols. */
|
if (IRIX_COMPAT (output_bfd) == ict_irix6)
|
if (IRIX_COMPAT (output_bfd) == ict_irix6)
|
mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);
|
mips_elf_irix6_finish_dynamic_symbol (output_bfd, name, sym);
|
|
|
if (! info->shared)
|
|
{
|
|
if (! mips_elf_hash_table (info)->use_rld_obj_head
|
|
&& (strcmp (name, "__rld_map") == 0
|
|
|| strcmp (name, "__RLD_MAP") == 0))
|
|
{
|
|
asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
|
|
BFD_ASSERT (s != NULL);
|
|
sym->st_value = s->output_section->vma + s->output_offset;
|
|
bfd_put_32 (output_bfd, 0, s->contents);
|
|
if (mips_elf_hash_table (info)->rld_value == 0)
|
|
mips_elf_hash_table (info)->rld_value = sym->st_value;
|
|
}
|
|
else if (mips_elf_hash_table (info)->use_rld_obj_head
|
|
&& strcmp (name, "__rld_obj_head") == 0)
|
|
{
|
|
/* IRIX6 does not use a .rld_map section. */
|
|
if (IRIX_COMPAT (output_bfd) == ict_irix5
|
|
|| IRIX_COMPAT (output_bfd) == ict_none)
|
|
BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map")
|
|
!= NULL);
|
|
mips_elf_hash_table (info)->rld_value = sym->st_value;
|
|
}
|
|
}
|
|
|
|
/* Keep dynamic MIPS16 symbols odd. This allows the dynamic linker to
|
/* Keep dynamic MIPS16 symbols odd. This allows the dynamic linker to
|
treat MIPS16 symbols like any other. */
|
treat MIPS16 symbols like any other. */
|
if (ELF_ST_IS_MIPS16 (sym->st_other))
|
if (ELF_ST_IS_MIPS16 (sym->st_other))
|
{
|
{
|
BFD_ASSERT (sym->st_value & 1);
|
BFD_ASSERT (sym->st_value & 1);
|
Line 10513... |
Line 10577... |
case DT_MIPS_HIPAGENO:
|
case DT_MIPS_HIPAGENO:
|
dyn.d_un.d_val = g->local_gotno - htab->reserved_gotno;
|
dyn.d_un.d_val = g->local_gotno - htab->reserved_gotno;
|
break;
|
break;
|
|
|
case DT_MIPS_RLD_MAP:
|
case DT_MIPS_RLD_MAP:
|
dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value;
|
{
|
|
struct elf_link_hash_entry *h;
|
|
h = mips_elf_hash_table (info)->rld_symbol;
|
|
if (!h)
|
|
{
|
|
dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj);
|
|
swap_out_p = FALSE;
|
|
break;
|
|
}
|
|
s = h->root.u.def.section;
|
|
dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
|
|
+ h->root.u.def.value);
|
|
}
|
break;
|
break;
|
|
|
case DT_MIPS_OPTIONS:
|
case DT_MIPS_OPTIONS:
|
s = (bfd_get_section_by_name
|
s = (bfd_get_section_by_name
|
(output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
|
(output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
|
Line 10883... |
Line 10959... |
case bfd_mach_mips_loongson_3a:
|
case bfd_mach_mips_loongson_3a:
|
val = E_MIPS_ARCH_64 | E_MIPS_MACH_LS3A;
|
val = E_MIPS_ARCH_64 | E_MIPS_MACH_LS3A;
|
break;
|
break;
|
|
|
case bfd_mach_mips_octeon:
|
case bfd_mach_mips_octeon:
|
|
case bfd_mach_mips_octeonp:
|
val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON;
|
val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON;
|
break;
|
break;
|
|
|
case bfd_mach_mips_xlr:
|
case bfd_mach_mips_xlr:
|
val = E_MIPS_ARCH_64 | E_MIPS_MACH_XLR;
|
val = E_MIPS_ARCH_64 | E_MIPS_MACH_XLR;
|
break;
|
break;
|
|
|
|
case bfd_mach_mips_octeon2:
|
|
val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON2;
|
|
break;
|
|
|
case bfd_mach_mipsisa32:
|
case bfd_mach_mipsisa32:
|
val = E_MIPS_ARCH_32;
|
val = E_MIPS_ARCH_32;
|
break;
|
break;
|
|
|
case bfd_mach_mipsisa64:
|
case bfd_mach_mipsisa64:
|
Line 12791... |
Line 12872... |
ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
|
ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
|
#endif
|
#endif
|
ret->procedure_count = 0;
|
ret->procedure_count = 0;
|
ret->compact_rel_size = 0;
|
ret->compact_rel_size = 0;
|
ret->use_rld_obj_head = FALSE;
|
ret->use_rld_obj_head = FALSE;
|
ret->rld_value = 0;
|
ret->rld_symbol = NULL;
|
ret->mips16_stubs_seen = FALSE;
|
ret->mips16_stubs_seen = FALSE;
|
ret->use_plts_and_copy_relocs = FALSE;
|
ret->use_plts_and_copy_relocs = FALSE;
|
ret->is_vxworks = FALSE;
|
ret->is_vxworks = FALSE;
|
ret->small_data_overflow_reported = FALSE;
|
ret->small_data_overflow_reported = FALSE;
|
ret->srelbss = NULL;
|
ret->srelbss = NULL;
|
Line 13489... |
Line 13570... |
/* An array describing how BFD machines relate to one another. The entries
|
/* An array describing how BFD machines relate to one another. The entries
|
are ordered topologically with MIPS I extensions listed last. */
|
are ordered topologically with MIPS I extensions listed last. */
|
|
|
static const struct mips_mach_extension mips_mach_extensions[] = {
|
static const struct mips_mach_extension mips_mach_extensions[] = {
|
/* MIPS64r2 extensions. */
|
/* MIPS64r2 extensions. */
|
|
{ bfd_mach_mips_octeon2, bfd_mach_mips_octeonp },
|
|
{ bfd_mach_mips_octeonp, bfd_mach_mips_octeon },
|
{ bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 },
|
{ bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 },
|
|
|
/* MIPS64 extensions. */
|
/* MIPS64 extensions. */
|
{ bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
|
{ bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
|
{ bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
|
{ bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
|