This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Problems with building ia64 big endian code on FreeBSD
- From: Jim Wilson <wilson at specifixinc dot com>
- To: dietmar dot hahn at fujitsu-siemens dot com
- Cc: binutils at sources dot redhat dot com
- Date: 10 Jul 2004 20:25:03 -0700
- Subject: Re: Problems with building ia64 big endian code on FreeBSD
- References: <200407091149.24439.dietmar.hahn@fujitsu-siemens.com>
On Fri, 2004-07-09 at 02:49, Dietmar Hahn wrote:
> With try and error I looked through the sources in the bfd directory and
> found the function elf64_ia64_install_value() in the file elf64-ia64.c
> I saw that for bfd_get_64() and bfd_put_64() the functions bfd_getb64() and
> bfd_putb64() were used. I changed this to bfd_getl64() and bfd_putl64() only
> for the instruction relocations and after new compiling ld I got the right
> code.
Here is the patch I came up with. It is pretty big, but it is mostly
mechanical. I changed bfd_get_64 to bfd_getl64 and bfd_put_64 to bfd_putl64
when they were used for the text section, as the text section is always
little endian. That made the abfd arguments unnecessary for 3 functions, and
fixing this led to cascading changes that made it a big patch.
The only bfd_{get,put}_64 calls left are in set_got_entry, set_fptr_entry,
and set_pltoff_entry. I believe these are all correct, as there are all
writing data into the GOT, and hence need to depend on the current object
file's endianness.
Since I don't have access to any big-endian IA-64 system with a working GNU ld
port, I don't have any good way to test this. The ia64-hpux target is the
only big-endian IA-64 target we support, and it has no ld port as yet.
This works correctly for your testcase.
For good measure, I tested this with a gcc bootstrap and make check.
libstdc++ fails to build unfortunately, a result of HJ's recent patch to
make ld complain about references to symbol is deleted linkonce sections.
Otherwise everything was fine.
2004-07-10 James E Wilson <wilson@specifixinc.com>
* elfxx-ia64.c (elfNN_ia64_relax_ldxmov): Remove abfd parameter.
(elfNN_ia64_install_value, elfNN_ia64_relax_brl): Likewise.
(elfNN_ia64_relax_section, elfNN_ia64_relocate_section,
elfNN_ia64_finish_dynamic_symbol, elfNN_ia64_finish_dynamic_sections):
Fix callers.
(elfNN_ia64_relax_brl): Change bfd_get_64 to bfd_getl64. Change
bfd_put_64 to bfd_putl64.
(elfNN_ia64_relax_ldxmov, elfNN_ia64_install_value): Likewise.
Index: elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.133
diff -p -r1.133 elfxx-ia64.c
*** elfxx-ia64.c 30 Jun 2004 20:23:23 -0000 1.133
--- elfxx-ia64.c 10 Jul 2004 00:01:43 -0000
*************** static bfd_boolean elfNN_ia64_relax_sect
*** 180,186 ****
PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
bfd_boolean *again));
static void elfNN_ia64_relax_ldxmov
! PARAMS((bfd *abfd, bfd_byte *contents, bfd_vma off));
static bfd_boolean is_unwind_section_name
PARAMS ((bfd *abfd, const char *));
static bfd_boolean elfNN_ia64_section_from_shdr
--- 180,186 ----
PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
bfd_boolean *again));
static void elfNN_ia64_relax_ldxmov
! PARAMS((bfd_byte *contents, bfd_vma off));
static bfd_boolean is_unwind_section_name
PARAMS ((bfd *abfd, const char *));
static bfd_boolean elfNN_ia64_section_from_shdr
*************** static bfd_boolean allocate_dynrel_entri
*** 273,279 ****
static bfd_boolean elfNN_ia64_size_dynamic_sections
PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
static bfd_reloc_status_type elfNN_ia64_install_value
! PARAMS ((bfd *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
static void elfNN_ia64_install_dyn_reloc
PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
asection *srel, bfd_vma offset, unsigned int type,
--- 273,279 ----
static bfd_boolean elfNN_ia64_size_dynamic_sections
PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
static bfd_reloc_status_type elfNN_ia64_install_value
! PARAMS ((bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
static void elfNN_ia64_install_dyn_reloc
PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
asection *srel, bfd_vma offset, unsigned int type,
*************** bfd_elfNN_ia64_after_parse (int itanium)
*** 674,680 ****
}
static void
! elfNN_ia64_relax_brl (bfd *abfd, bfd_byte *contents, bfd_vma off)
{
int template;
bfd_byte *hit_addr;
--- 674,680 ----
}
static void
! elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
{
int template;
bfd_byte *hit_addr;
*************** elfNN_ia64_relax_brl (bfd *abfd, bfd_byt
*** 682,689 ****
hit_addr = (bfd_byte *) (contents + off);
hit_addr -= (long) hit_addr & 0x3;
! t0 = bfd_get_64 (abfd, hit_addr);
! t1 = bfd_get_64 (abfd, hit_addr + 8);
/* Keep the instruction in slot 0. */
i0 = (t0 >> 5) & 0x1ffffffffffLL;
--- 682,689 ----
hit_addr = (bfd_byte *) (contents + off);
hit_addr -= (long) hit_addr & 0x3;
! t0 = bfd_getl64 (hit_addr);
! t1 = bfd_getl64 (hit_addr + 8);
/* Keep the instruction in slot 0. */
i0 = (t0 >> 5) & 0x1ffffffffffLL;
*************** elfNN_ia64_relax_brl (bfd *abfd, bfd_byt
*** 700,707 ****
t0 = (i1 << 46) | (i0 << 5) | template;
t1 = (i2 << 23) | (i1 >> 18);
! bfd_put_64 (abfd, t0, hit_addr);
! bfd_put_64 (abfd, t1, hit_addr + 8);
}
/* These functions do relaxation for IA-64 ELF. */
--- 700,707 ----
t0 = (i1 << 46) | (i0 << 5) | template;
t1 = (i2 << 23) | (i1 >> 18);
! bfd_putl64 (t0, hit_addr);
! bfd_putl64 (t1, hit_addr + 8);
}
/* These functions do relaxation for IA-64 ELF. */
*************** elfNN_ia64_relax_section (abfd, sec, lin
*** 967,973 ****
/* If the 60-bit branch is in 21-bit range, optimize it. */
if (r_type == R_IA64_PCREL60B)
{
! elfNN_ia64_relax_brl (abfd, contents, roff);
irel->r_info
= ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
--- 967,973 ----
/* If the 60-bit branch is in 21-bit range, optimize it. */
if (r_type == R_IA64_PCREL60B)
{
! elfNN_ia64_relax_brl (contents, roff);
irel->r_info
= ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
*************** elfNN_ia64_relax_section (abfd, sec, lin
*** 1074,1081 ****
}
/* Fix up the existing branch to hit the trampoline. */
! if (elfNN_ia64_install_value (abfd, contents + roff, offset,
! r_type) != bfd_reloc_ok)
goto error_return;
changed_contents = TRUE;
--- 1074,1081 ----
}
/* Fix up the existing branch to hit the trampoline. */
! if (elfNN_ia64_install_value (contents + roff, offset, r_type)
! != bfd_reloc_ok)
goto error_return;
changed_contents = TRUE;
*************** elfNN_ia64_relax_section (abfd, sec, lin
*** 1114,1120 ****
}
else
{
! elfNN_ia64_relax_ldxmov (abfd, contents, roff);
irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
changed_contents = TRUE;
changed_relocs = TRUE;
--- 1114,1120 ----
}
else
{
! elfNN_ia64_relax_ldxmov (contents, roff);
irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
changed_contents = TRUE;
changed_relocs = TRUE;
*************** elfNN_ia64_relax_section (abfd, sec, lin
*** 1201,1208 ****
}
static void
! elfNN_ia64_relax_ldxmov (abfd, contents, off)
! bfd *abfd;
bfd_byte *contents;
bfd_vma off;
{
--- 1201,1207 ----
}
static void
! elfNN_ia64_relax_ldxmov (contents, off)
bfd_byte *contents;
bfd_vma off;
{
*************** elfNN_ia64_relax_ldxmov (abfd, contents,
*** 1218,1224 ****
abort ();
}
! dword = bfd_get_64 (abfd, contents + off);
insn = (dword >> shift) & 0x1ffffffffffLL;
r1 = (insn >> 6) & 127;
--- 1217,1223 ----
abort ();
}
! dword = bfd_getl64 (contents + off);
insn = (dword >> shift) & 0x1ffffffffffLL;
r1 = (insn >> 6) & 127;
*************** elfNN_ia64_relax_ldxmov (abfd, contents,
*** 1230,1236 ****
dword &= ~(0x1ffffffffffLL << shift);
dword |= (insn << shift);
! bfd_put_64 (abfd, dword, contents + off);
}
/* Return TRUE if NAME is an unwind table section name. */
--- 1229,1235 ----
dword &= ~(0x1ffffffffffLL << shift);
dword |= (insn << shift);
! bfd_putl64 (dword, contents + off);
}
/* Return TRUE if NAME is an unwind table section name. */
*************** elfNN_ia64_size_dynamic_sections (output
*** 3165,3172 ****
}
static bfd_reloc_status_type
! elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
! bfd *abfd;
bfd_byte *hit_addr;
bfd_vma v;
unsigned int r_type;
--- 3164,3170 ----
}
static bfd_reloc_status_type
! elfNN_ia64_install_value (hit_addr, v, r_type)
bfd_byte *hit_addr;
bfd_vma v;
unsigned int r_type;
*************** elfNN_ia64_install_value (abfd, hit_addr
*** 3298,3305 ****
{
case IA64_OPND_IMMU64:
hit_addr -= (long) hit_addr & 0x3;
! t0 = bfd_get_64 (abfd, hit_addr);
! t1 = bfd_get_64 (abfd, hit_addr + 8);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
--- 3296,3303 ----
{
case IA64_OPND_IMMU64:
hit_addr -= (long) hit_addr & 0x3;
! t0 = bfd_getl64 (hit_addr);
! t1 = bfd_getl64 (hit_addr + 8);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
*************** elfNN_ia64_install_value (abfd, hit_addr
*** 3321,3334 ****
| (((val >> 21) & 0x001) << 21) /* ic */
| (((val >> 63) & 0x001) << 36)) << 23; /* i */
! bfd_put_64 (abfd, t0, hit_addr);
! bfd_put_64 (abfd, t1, hit_addr + 8);
break;
case IA64_OPND_TGT64:
hit_addr -= (long) hit_addr & 0x3;
! t0 = bfd_get_64 (abfd, hit_addr);
! t1 = bfd_get_64 (abfd, hit_addr + 8);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
--- 3319,3332 ----
| (((val >> 21) & 0x001) << 21) /* ic */
| (((val >> 63) & 0x001) << 36)) << 23; /* i */
! bfd_putl64 (t0, hit_addr);
! bfd_putl64 (t1, hit_addr + 8);
break;
case IA64_OPND_TGT64:
hit_addr -= (long) hit_addr & 0x3;
! t0 = bfd_getl64 (hit_addr);
! t1 = bfd_getl64 (hit_addr + 8);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
*************** elfNN_ia64_install_value (abfd, hit_addr
*** 3346,3353 ****
t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */
| (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
! bfd_put_64 (abfd, t0, hit_addr);
! bfd_put_64 (abfd, t1, hit_addr + 8);
break;
default:
--- 3344,3351 ----
t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */
| (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
! bfd_putl64 (t0, hit_addr);
! bfd_putl64 (t1, hit_addr + 8);
break;
default:
*************** elfNN_ia64_install_value (abfd, hit_addr
*** 3358,3364 ****
case 2: shift = 23; hit_addr += 6; break;
case 3: return bfd_reloc_notsupported; /* shouldn't happen... */
}
! dword = bfd_get_64 (abfd, hit_addr);
insn = (dword >> shift) & 0x1ffffffffffLL;
op = elf64_ia64_operands + opnd;
--- 3356,3362 ----
case 2: shift = 23; hit_addr += 6; break;
case 3: return bfd_reloc_notsupported; /* shouldn't happen... */
}
! dword = bfd_getl64 (hit_addr);
insn = (dword >> shift) & 0x1ffffffffffLL;
op = elf64_ia64_operands + opnd;
*************** elfNN_ia64_install_value (abfd, hit_addr
*** 3368,3374 ****
dword &= ~(0x1ffffffffffLL << shift);
dword |= (insn << shift);
! bfd_put_64 (abfd, dword, hit_addr);
break;
case IA64_OPND_NIL:
--- 3366,3372 ----
dword &= ~(0x1ffffffffffLL << shift);
dword |= (insn << shift);
! bfd_putl64 (dword, hit_addr);
break;
case IA64_OPND_NIL:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4119,4125 ****
case R_IA64_LTV32LSB:
case R_IA64_LTV64MSB:
case R_IA64_LTV64LSB:
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_GPREL22:
--- 4117,4123 ----
case R_IA64_LTV32LSB:
case R_IA64_LTV64MSB:
case R_IA64_LTV64LSB:
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_GPREL22:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4137,4143 ****
continue;
}
value -= gp_val;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_LTOFF22:
--- 4135,4141 ----
continue;
}
value -= gp_val;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF22:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4147,4153 ****
value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
rel->r_addend, value, R_IA64_DIR64LSB);
value -= gp_val;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_PLTOFF22:
--- 4145,4151 ----
value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
rel->r_addend, value, R_IA64_DIR64LSB);
value -= gp_val;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_PLTOFF22:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4157,4163 ****
dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
value -= gp_val;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_FPTR64I:
--- 4155,4161 ----
dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
value -= gp_val;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_FPTR64I:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4222,4228 ****
dynindx, addend);
}
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_LTOFF_FPTR22:
--- 4220,4226 ----
dynindx, addend);
}
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF_FPTR22:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4264,4270 ****
value = set_got_entry (output_bfd, info, dyn_i, dynindx,
rel->r_addend, value, R_IA64_FPTR64LSB);
value -= gp_val;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
}
break;
--- 4262,4268 ----
value = set_got_entry (output_bfd, info, dyn_i, dynindx,
rel->r_addend, value, R_IA64_FPTR64LSB);
value -= gp_val;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
}
break;
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4345,4351 ****
value -= (input_section->output_section->vma
+ input_section->output_offset
+ rel->r_offset) & ~ (bfd_vma) 0x3;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_SEGREL32MSB:
--- 4343,4349 ----
value -= (input_section->output_section->vma
+ input_section->output_offset
+ rel->r_offset) & ~ (bfd_vma) 0x3;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_SEGREL32MSB:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4389,4396 ****
value -= p->p_vaddr;
else
value = 0;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
! r_type);
}
break;
}
--- 4387,4393 ----
value -= p->p_vaddr;
else
value = 0;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
}
break;
}
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4404,4410 ****
value -= input_section->output_section->vma;
else
value = 0;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_IPLTMSB:
--- 4401,4407 ----
value -= input_section->output_section->vma;
else
value = 0;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_IPLTMSB:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4445,4460 ****
r_type = R_IA64_DIR64MSB;
else
r_type = R_IA64_DIR64LSB;
! elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
! r = elfNN_ia64_install_value (output_bfd, hit_addr + 8, gp_val,
! r_type);
break;
case R_IA64_TPREL14:
case R_IA64_TPREL22:
case R_IA64_TPREL64I:
value -= elfNN_ia64_tprel_base (info);
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_DTPREL14:
--- 4442,4456 ----
r_type = R_IA64_DIR64MSB;
else
r_type = R_IA64_DIR64LSB;
! elfNN_ia64_install_value (hit_addr, value, r_type);
! r = elfNN_ia64_install_value (hit_addr + 8, gp_val, r_type);
break;
case R_IA64_TPREL14:
case R_IA64_TPREL22:
case R_IA64_TPREL64I:
value -= elfNN_ia64_tprel_base (info);
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_DTPREL14:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4463,4469 ****
case R_IA64_DTPREL64LSB:
case R_IA64_DTPREL64MSB:
value -= elfNN_ia64_dtprel_base (info);
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
case R_IA64_LTOFF_TPREL22:
--- 4459,4465 ----
case R_IA64_DTPREL64LSB:
case R_IA64_DTPREL64MSB:
value -= elfNN_ia64_dtprel_base (info);
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF_TPREL22:
*************** elfNN_ia64_relocate_section (output_bfd,
*** 4505,4512 ****
value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
value, got_r_type);
value -= gp_val;
! r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
! r_type);
}
break;
--- 4501,4507 ----
value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
value, got_r_type);
value -= gp_val;
! r = elfNN_ia64_install_value (hit_addr, value, r_type);
}
break;
*************** elfNN_ia64_finish_dynamic_symbol (output
*** 4617,4625 ****
loc = plt_sec->contents + dyn_i->plt_offset;
memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
! elfNN_ia64_install_value (output_bfd, loc, index, R_IA64_IMM22);
! elfNN_ia64_install_value (output_bfd, loc+2, -dyn_i->plt_offset,
! R_IA64_PCREL21B);
plt_addr = (plt_sec->output_section->vma
+ plt_sec->output_offset
--- 4612,4619 ----
loc = plt_sec->contents + dyn_i->plt_offset;
memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
! elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
! elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
plt_addr = (plt_sec->output_section->vma
+ plt_sec->output_offset
*************** elfNN_ia64_finish_dynamic_symbol (output
*** 4632,4639 ****
loc = plt_sec->contents + dyn_i->plt2_offset;
memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
! elfNN_ia64_install_value (output_bfd, loc, pltoff_addr - gp_val,
! R_IA64_IMM22);
/* Mark the symbol as undefined, rather than as defined in the
plt section. Leave the value alone. */
--- 4626,4632 ----
loc = plt_sec->contents + dyn_i->plt2_offset;
memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
! elfNN_ia64_install_value (loc, pltoff_addr - gp_val, R_IA64_IMM22);
/* Mark the symbol as undefined, rather than as defined in the
plt section. Leave the value alone. */
*************** elfNN_ia64_finish_dynamic_sections (abfd
*** 4756,4762 ****
+ sgotplt->output_offset
- gp_val);
! elfNN_ia64_install_value (abfd, loc+1, pltres, R_IA64_GPREL22);
}
}
--- 4749,4755 ----
+ sgotplt->output_offset
- gp_val);
! elfNN_ia64_install_value (loc+1, pltres, R_IA64_GPREL22);
}
}
--
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com