Add ELFv2 .localentry support.
This defines the ELF symbol st_other field used to encode the number of instructions between a function "global entry" and its "local entry", and adds support related to the local entry offset. include/elf/ * ppc64.h (STO_PPC64_LOCAL_BIT, STO_PPC64_LOCAL_MASK): Define. (ppc64_decode_local_entry, ppc64_encode_local_entry): New functions. (PPC64_LOCAL_ENTRY_OFFSET, PPC64_SET_LOCAL_ENTRY_OFFSET): Define. bfd/ * elf64-ppc.c (struct ppc_stub_hash_entry): Add "other". (stub_hash_newfunc): Init new ppc_stub_hash_entry field, and one we forgot, "plt_ent". (ppc64_elf_add_symbol_hook): Check ELFv1 objects don't have st_other bits only valid in ELFv2. (ppc64_elf_merge_symbol_attribute): New function. (ppc_type_of_stub): Add local_off param to test branch range. (ppc_build_one_stub): Adjust destinations for ELFv2 locals. (ppc_size_one_stub, toc_adjusting_stub_needed): Similarly. (ppc64_elf_size_stubs): Pass local_off to ppc_type_of_stub. Set "other" field. (ppc64_elf_relocate_section): Adjust destination for ELFv2 local calls. gas/ * config/tc-ppc.c (md_pseudo_table): Add .localentry. (ppc_elf_localentry): New function. (ppc_force_relocation): Force relocs on all branches to localenty symbols. (ppc_fix_adjustable): Don't reduce such symbols to section+offset. binutils/ * readelf.c (get_ppc64_symbol_other): New function. (get_symbol_other): Use it for EM_PPC64.
This commit is contained in:
parent
ee67d69a3f
commit
6911b7dcb8
|
@ -1,3 +1,20 @@
|
|||
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||
Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* elf64-ppc.c (struct ppc_stub_hash_entry): Add "other".
|
||||
(stub_hash_newfunc): Init new ppc_stub_hash_entry field, and one
|
||||
we forgot, "plt_ent".
|
||||
(ppc64_elf_add_symbol_hook): Check ELFv1 objects don't have
|
||||
st_other bits only valid in ELFv2.
|
||||
(ppc64_elf_merge_symbol_attribute): New function.
|
||||
(ppc_type_of_stub): Add local_off param to test branch range.
|
||||
(ppc_build_one_stub): Adjust destinations for ELFv2 locals.
|
||||
(ppc_size_one_stub, toc_adjusting_stub_needed): Similarly.
|
||||
(ppc64_elf_size_stubs): Pass local_off to ppc_type_of_stub.
|
||||
Set "other" field.
|
||||
(ppc64_elf_relocate_section): Adjust destination for ELFv2 local
|
||||
calls.
|
||||
|
||||
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.c (abiversion, set_abiversion): New functions.
|
||||
|
|
|
@ -118,6 +118,7 @@ static bfd_vma opd_entry_value
|
|||
#define elf_backend_link_output_symbol_hook ppc64_elf_output_symbol_hook
|
||||
#define elf_backend_special_sections ppc64_elf_special_sections
|
||||
#define elf_backend_post_process_headers _bfd_elf_set_osabi
|
||||
#define elf_backend_merge_symbol_attribute ppc64_elf_merge_symbol_attribute
|
||||
|
||||
/* The name of the dynamic interpreter. This is put in the .interp
|
||||
section. */
|
||||
|
@ -3746,6 +3747,9 @@ struct ppc_stub_hash_entry {
|
|||
/* Where this stub is being called from, or, in the case of combined
|
||||
stub sections, the first input section in the group. */
|
||||
asection *id_sec;
|
||||
|
||||
/* Symbol st_other. */
|
||||
unsigned char other;
|
||||
};
|
||||
|
||||
struct ppc_branch_hash_entry {
|
||||
|
@ -4004,7 +4008,9 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
eh->target_value = 0;
|
||||
eh->target_section = NULL;
|
||||
eh->h = NULL;
|
||||
eh->plt_ent = NULL;
|
||||
eh->id_sec = NULL;
|
||||
eh->other = 0;
|
||||
}
|
||||
|
||||
return entry;
|
||||
|
@ -4750,7 +4756,7 @@ static bfd_boolean
|
|||
ppc64_elf_add_symbol_hook (bfd *ibfd,
|
||||
struct bfd_link_info *info,
|
||||
Elf_Internal_Sym *isym,
|
||||
const char **name ATTRIBUTE_UNUSED,
|
||||
const char **name,
|
||||
flagword *flags ATTRIBUTE_UNUSED,
|
||||
asection **sec,
|
||||
bfd_vma *value ATTRIBUTE_UNUSED)
|
||||
|
@ -4770,9 +4776,35 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
|
|||
&& strcmp ((*sec)->name, ".opd") == 0)
|
||||
isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
|
||||
|
||||
if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
|
||||
{
|
||||
if (abiversion (ibfd) == 0)
|
||||
set_abiversion (ibfd, 2);
|
||||
else if (abiversion (ibfd) == 1)
|
||||
{
|
||||
info->callbacks->einfo (_("%P: symbol '%s' has invalid st_other"
|
||||
" for ABI version 1\n"), name);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Merge non-visibility st_other attributes: local entry point. */
|
||||
|
||||
static void
|
||||
ppc64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
|
||||
const Elf_Internal_Sym *isym,
|
||||
bfd_boolean definition,
|
||||
bfd_boolean dynamic)
|
||||
{
|
||||
if (definition && !dynamic)
|
||||
h->other = ((isym->st_other & ~ELF_ST_VISIBILITY (-1))
|
||||
| ELF_ST_VISIBILITY (h->other));
|
||||
}
|
||||
|
||||
/* This function makes an old ABI object reference to ".bar" cause the
|
||||
inclusion of a new ABI object archive that defines "bar".
|
||||
NAME is a symbol defined in an archive. Return a symbol in the hash
|
||||
|
@ -9796,7 +9828,8 @@ ppc_type_of_stub (asection *input_sec,
|
|||
const Elf_Internal_Rela *rel,
|
||||
struct ppc_link_hash_entry **hash,
|
||||
struct plt_entry **plt_ent,
|
||||
bfd_vma destination)
|
||||
bfd_vma destination,
|
||||
unsigned long local_off)
|
||||
{
|
||||
struct ppc_link_hash_entry *h = *hash;
|
||||
bfd_vma location;
|
||||
|
@ -9865,7 +9898,7 @@ ppc_type_of_stub (asection *input_sec,
|
|||
if (r_type != R_PPC64_REL24)
|
||||
max_branch_offset = 1 << 15;
|
||||
|
||||
if (branch_offset + max_branch_offset >= 2 * max_branch_offset)
|
||||
if (branch_offset + max_branch_offset >= 2 * max_branch_offset - local_off)
|
||||
/* We need a stub. Figure out whether a long_branch or plt_branch
|
||||
is needed later. */
|
||||
return ppc_stub_long_branch;
|
||||
|
@ -10233,9 +10266,11 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
case ppc_stub_long_branch:
|
||||
case ppc_stub_long_branch_r2off:
|
||||
/* Branches are relative. This is where we are going to. */
|
||||
off = dest = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
dest = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
dest += PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
||||
off = dest;
|
||||
|
||||
/* And this is where we are coming from. */
|
||||
off -= (stub_entry->stub_offset
|
||||
|
@ -10338,6 +10373,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
dest = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
||||
dest += PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
||||
|
||||
bfd_put_64 (htab->brlt->owner, dest,
|
||||
htab->brlt->contents + br_entry->offset);
|
||||
|
@ -10682,6 +10719,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
/* ppc_stub_long_branch or ppc_stub_plt_branch, or their r2off
|
||||
variants. */
|
||||
bfd_vma r2off = 0;
|
||||
bfd_vma local_off = 0;
|
||||
|
||||
off = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
|
@ -10710,8 +10748,10 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
off -= size - 4;
|
||||
}
|
||||
|
||||
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
||||
|
||||
/* If the branch offset if too big, use a ppc_stub_plt_branch. */
|
||||
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
|
||||
if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off)
|
||||
{
|
||||
struct ppc_branch_hash_entry *br_entry;
|
||||
|
||||
|
@ -11308,7 +11348,10 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
|||
need a plt_branch stub. A plt_branch stub uses r2. */
|
||||
else if (dest - (isec->output_offset
|
||||
+ isec->output_section->vma
|
||||
+ rel->r_offset) + (1 << 25) >= (2 << 25))
|
||||
+ rel->r_offset) + (1 << 25)
|
||||
>= (2u << 25) - PPC64_LOCAL_ENTRY_OFFSET (h
|
||||
? h->other
|
||||
: sym->st_other))
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
|
@ -11761,6 +11804,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
|
|||
asection *sym_sec, *code_sec;
|
||||
bfd_vma sym_value, code_value;
|
||||
bfd_vma destination;
|
||||
unsigned long local_off;
|
||||
bfd_boolean ok_dest;
|
||||
struct ppc_link_hash_entry *hash;
|
||||
struct ppc_link_hash_entry *fdh;
|
||||
|
@ -11837,12 +11881,16 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
|
|||
}
|
||||
|
||||
destination = 0;
|
||||
local_off = 0;
|
||||
if (ok_dest)
|
||||
{
|
||||
sym_value += irela->r_addend;
|
||||
destination = (sym_value
|
||||
+ sym_sec->output_offset
|
||||
+ sym_sec->output_section->vma);
|
||||
local_off = PPC64_LOCAL_ENTRY_OFFSET (hash
|
||||
? hash->elf.other
|
||||
: sym->st_other);
|
||||
}
|
||||
|
||||
code_sec = sym_sec;
|
||||
|
@ -11879,7 +11927,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
|
|||
/* Determine what (if any) linker stub is needed. */
|
||||
plt_ent = NULL;
|
||||
stub_type = ppc_type_of_stub (section, irela, &hash,
|
||||
&plt_ent, destination);
|
||||
&plt_ent, destination,
|
||||
local_off);
|
||||
|
||||
if (stub_type != ppc_stub_plt_call)
|
||||
{
|
||||
|
@ -11979,6 +12028,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
|
|||
}
|
||||
stub_entry->h = hash;
|
||||
stub_entry->plt_ent = plt_ent;
|
||||
stub_entry->other = hash ? hash->elf.other : sym->st_other;
|
||||
|
||||
if (stub_entry->h != NULL)
|
||||
htab->stub_globals += 1;
|
||||
|
@ -13357,6 +13407,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
+ input_section->output_offset
|
||||
+ input_section->output_section->vma);
|
||||
|
||||
relocation += PPC64_LOCAL_ENTRY_OFFSET (fdh
|
||||
? fdh->elf.other
|
||||
: sym->st_other);
|
||||
|
||||
if (stub_entry != NULL
|
||||
&& (stub_entry->stub_type == ppc_stub_long_branch
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch)
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2013-10-30 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* readelf.c (get_ppc64_symbol_other): New function.
|
||||
(get_symbol_other): Use it for EM_PPC64.
|
||||
|
||||
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* readelf.c (get_machine_flags): Display ABI version for EM_PPC64.
|
||||
|
|
|
@ -9210,6 +9210,19 @@ get_ia64_symbol_other (unsigned int other)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_ppc64_symbol_other (unsigned int other)
|
||||
{
|
||||
if (PPC64_LOCAL_ENTRY_OFFSET (other) != 0)
|
||||
{
|
||||
static char buf[32];
|
||||
snprintf (buf, sizeof buf, _("<localentry>: %d"),
|
||||
PPC64_LOCAL_ENTRY_OFFSET (other));
|
||||
return buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_symbol_other (unsigned int other)
|
||||
{
|
||||
|
@ -9227,6 +9240,9 @@ get_symbol_other (unsigned int other)
|
|||
case EM_IA_64:
|
||||
result = get_ia64_symbol_other (other);
|
||||
break;
|
||||
case EM_PPC64:
|
||||
result = get_ppc64_symbol_other (other);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2013-10-30 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* config/tc-ppc.c (md_pseudo_table): Add .localentry.
|
||||
(ppc_elf_localentry): New function.
|
||||
(ppc_force_relocation): Force relocs on all branches to localenty
|
||||
symbols.
|
||||
(ppc_fix_adjustable): Don't reduce such symbols to section+offset.
|
||||
|
||||
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/tc-ppc.c: Include elf/ppc64.h.
|
||||
|
|
|
@ -134,6 +134,7 @@ static void ppc_vbyte (int);
|
|||
static void ppc_elf_cons (int);
|
||||
static void ppc_elf_rdata (int);
|
||||
static void ppc_elf_lcomm (int);
|
||||
static void ppc_elf_localentry (int);
|
||||
static void ppc_elf_abiversion (int);
|
||||
#endif
|
||||
|
||||
|
@ -266,6 +267,7 @@ const pseudo_typeS md_pseudo_table[] =
|
|||
{ "rdata", ppc_elf_rdata, 0 },
|
||||
{ "rodata", ppc_elf_rdata, 0 },
|
||||
{ "lcomm", ppc_elf_lcomm, 0 },
|
||||
{ "localentry", ppc_elf_localentry, 0 },
|
||||
{ "abiversion", ppc_elf_abiversion, 0 },
|
||||
#endif
|
||||
|
||||
|
@ -2226,6 +2228,68 @@ ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED)
|
|||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Pseudo op to set symbol local entry point. */
|
||||
static void
|
||||
ppc_elf_localentry (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
char *name = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
char *p;
|
||||
expressionS exp;
|
||||
symbolS *sym;
|
||||
asymbol *bfdsym;
|
||||
elf_symbol_type *elfsym;
|
||||
|
||||
p = input_line_pointer;
|
||||
*p = c;
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
*p = 0;
|
||||
as_bad (_("expected comma after name `%s' in .localentry directive"),
|
||||
name);
|
||||
*p = c;
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
input_line_pointer++;
|
||||
expression (&exp);
|
||||
if (exp.X_op == O_absent)
|
||||
{
|
||||
as_bad (_("missing expression in .localentry directive"));
|
||||
exp.X_op = O_constant;
|
||||
exp.X_add_number = 0;
|
||||
}
|
||||
*p = 0;
|
||||
sym = symbol_find_or_make (name);
|
||||
*p = c;
|
||||
|
||||
if (resolve_expression (&exp)
|
||||
&& exp.X_op == O_constant)
|
||||
{
|
||||
unsigned char encoded = PPC64_SET_LOCAL_ENTRY_OFFSET (exp.X_add_number);
|
||||
|
||||
if (exp.X_add_number != PPC64_LOCAL_ENTRY_OFFSET (encoded))
|
||||
as_bad (_(".localentry expression for `%s' "
|
||||
"is not a valid power of 2"), S_GET_NAME (sym));
|
||||
else
|
||||
{
|
||||
bfdsym = symbol_get_bfdsym (sym);
|
||||
elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
|
||||
gas_assert (elfsym);
|
||||
elfsym->internal_elf_sym.st_other &= ~STO_PPC64_LOCAL_MASK;
|
||||
elfsym->internal_elf_sym.st_other |= encoded;
|
||||
if (ppc_abiversion == 0)
|
||||
ppc_abiversion = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
as_bad (_(".localentry expression for `%s' "
|
||||
"does not evaluate to a constant"), S_GET_NAME (sym));
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Pseudo op to set ABI version. */
|
||||
static void
|
||||
ppc_elf_abiversion (int ignore ATTRIBUTE_UNUSED)
|
||||
|
@ -6229,6 +6293,22 @@ ppc_force_relocation (fixS *fix)
|
|||
case BFD_RELOC_24_PLT_PCREL:
|
||||
case BFD_RELOC_PPC64_TOC:
|
||||
return 1;
|
||||
case BFD_RELOC_PPC_B26:
|
||||
case BFD_RELOC_PPC_BA26:
|
||||
case BFD_RELOC_PPC_B16:
|
||||
case BFD_RELOC_PPC_BA16:
|
||||
/* All branch fixups targeting a localentry symbol must
|
||||
force a relocation. */
|
||||
if (fix->fx_addsy)
|
||||
{
|
||||
asymbol *bfdsym = symbol_get_bfdsym (fix->fx_addsy);
|
||||
elf_symbol_type *elfsym
|
||||
= elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
|
||||
gas_assert (elfsym);
|
||||
if ((STO_PPC64_LOCAL_MASK & elfsym->internal_elf_sym.st_other) != 0)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -6243,6 +6323,32 @@ ppc_force_relocation (fixS *fix)
|
|||
int
|
||||
ppc_fix_adjustable (fixS *fix)
|
||||
{
|
||||
switch (fix->fx_r_type)
|
||||
{
|
||||
/* All branch fixups targeting a localentry symbol must
|
||||
continue using the symbol. */
|
||||
case BFD_RELOC_PPC_B26:
|
||||
case BFD_RELOC_PPC_BA26:
|
||||
case BFD_RELOC_PPC_B16:
|
||||
case BFD_RELOC_PPC_BA16:
|
||||
case BFD_RELOC_PPC_B16_BRTAKEN:
|
||||
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
||||
case BFD_RELOC_PPC_BA16_BRTAKEN:
|
||||
case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
||||
if (fix->fx_addsy)
|
||||
{
|
||||
asymbol *bfdsym = symbol_get_bfdsym (fix->fx_addsy);
|
||||
elf_symbol_type *elfsym
|
||||
= elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
|
||||
gas_assert (elfsym);
|
||||
if ((STO_PPC64_LOCAL_MASK & elfsym->internal_elf_sym.st_other) != 0)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
|
||||
&& fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
|
||||
&& fix->fx_r_type != BFD_RELOC_HI16_GOTOFF
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ppc64.h (STO_PPC64_LOCAL_BIT, STO_PPC64_LOCAL_MASK): Define.
|
||||
(ppc64_decode_local_entry, ppc64_encode_local_entry): New functions.
|
||||
(PPC64_LOCAL_ENTRY_OFFSET, PPC64_SET_LOCAL_ENTRY_OFFSET): Define.
|
||||
|
||||
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ppc64.h (EF_PPC64_ABI): Define.
|
||||
|
|
|
@ -180,6 +180,53 @@ END_RELOC_NUMBERS (R_PPC64_max)
|
|||
0 for unspecified or not using any features affected by the differences. */
|
||||
#define EF_PPC64_ABI 3
|
||||
|
||||
/* The ELFv2 ABI uses three bits in the symbol st_other field of a
|
||||
function definition to specify the number of instructions between a
|
||||
function's global entry point and local entry point.
|
||||
The global entry point is used when it is necessary to set up the
|
||||
toc pointer (r2) for the function. Callers must enter the global
|
||||
entry point with r12 set to the global entry point address. On
|
||||
return from the function, r2 may have a different value to that
|
||||
which it had on entry.
|
||||
The local entry point is used when r2 is known to already be valid
|
||||
for the function. There is no requirement on r12 when using the
|
||||
local entry point, and on return r2 will contain the same value as
|
||||
at entry.
|
||||
A value of zero in these bits means that the function has a single
|
||||
entry point with no requirement on r12 or r2, and that on return r2
|
||||
will contain the same value as at entry.
|
||||
Values of one and seven are reserved. */
|
||||
#define STO_PPC64_LOCAL_BIT 5
|
||||
#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
|
||||
|
||||
// 3 bit other field to bytes.
|
||||
static inline unsigned int
|
||||
ppc64_decode_local_entry(unsigned int other)
|
||||
{
|
||||
return ((1 << other) >> 2) << 2;
|
||||
}
|
||||
|
||||
// bytes to field value.
|
||||
static inline unsigned int
|
||||
ppc64_encode_local_entry(unsigned int val)
|
||||
{
|
||||
return (val >= 4 * 4
|
||||
? (val >= 8 * 4
|
||||
? (val >= 16 * 4 ? 6 : 5)
|
||||
: 4)
|
||||
: (val >= 2 * 4
|
||||
? 3
|
||||
: (val >= 1 * 4 ? 2 : 0)));
|
||||
}
|
||||
|
||||
/* st_other to number of bytes. */
|
||||
#define PPC64_LOCAL_ENTRY_OFFSET(other) \
|
||||
ppc64_decode_local_entry (((other) & STO_PPC64_LOCAL_MASK) \
|
||||
>> STO_PPC64_LOCAL_BIT)
|
||||
/* number of bytes to st_other. */
|
||||
#define PPC64_SET_LOCAL_ENTRY_OFFSET(val) \
|
||||
ppc64_encode_local_entry (val) << STO_PPC64_LOCAL_BIT
|
||||
|
||||
/* Specify the start of the .glink section. */
|
||||
#define DT_PPC64_GLINK DT_LOPROC
|
||||
|
||||
|
|
Loading…
Reference in New Issue