Problems with building ia64 big endian code on FreeBSD

Jim Wilson
Fri Jul 9 21:02:00 GMT 2004

On Fri, 2004-07-09 at 02:49, Dietmar Hahn wrote:
> I tried to build a big endian object on a itanium2 (ia64) machine with 
> FreeBSD.

FreeBSD is little endian.  We tried to include bi-endian support when
developing the toolchain, but so far there are no known bi-endian
systems, and as a result, the bi-endian support has never been tested. 
There are likely a lot of minor bugs in it.

As far as I know, freebsd can't run big-endian code, so I am not sure
why you would want to generate that.

> cc -ansi -Wall -O -Wa,-mlp64 -mbig-endian -Wa,-mbe -c tst.c

The compiler is buggy if you have to pass -mbe and/or -mlp64 options to
the assembler.  This compiler should pass these down automatically. 
However, since freebsd doesn't have multiple ABI or multiple endianness
support, it isn't surprising that this stuff is currently missing.

> The problem is the type FPTR64LSB - I think it has to be FPTR64MSB.

Yes.  The problem here is that the only thing the -mbe option does is
set the ELF header flag that marks this as a big-endian object file. 
That isn't good enough.  I have attached a patch to fix this.

> ./configure --target=ia64-hp-hpux --enable-64-bit-bfd

In general, substituting an ia64-hpux assembler is not a good idea, as
HPUX does a number of things differently than other ia64 targets.  It is
big endian by default, so it is OK if you just want to check for
endianness problems.

> Now I used the second as to build the objects. Later in linking (with the ld 
> build with target=ia64-freebsd5.0) to the final object without relocations 
> the linker built buggy code.

The only current big endian target is ia64-hpux, and I don't know if GNU
ld works correctly for that target yet.  I think maybe only GNU as
does.  Hence there could be big-endian bugs in the linker that haven't
been discovered yet.

> 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.

So the problem here presumably is that big-endian object files actually
have little-endian code and big-endian data, so we can't just blindly
call bfd_{get,put}_64.  We need to explicitly call the little endian
version for instruction relocs.  This one I will have to test to make
sure I don't screw it up, so it will come later.
Jim Wilson, GNU Tools Support,
-------------- next part --------------
2004-07-09  James E Wilson  <>

	* config/tc-ia64.c (default_big_endian): New.
	(dot_byteorder, md_begin): Use it.
	(md_parse_option): Set it.
Index: tc-ia64.c
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.112
diff -p -r1.112 tc-ia64.c
*** tc-ia64.c	4 Jul 2004 00:29:21 -0000	1.112
--- tc-ia64.c	9 Jul 2004 20:42:51 -0000
*************** struct label_fix
*** 153,160 ****
--- 153,164 ----
    struct symbol *sym;
+ /* This is the endianness of the current section.  */
  extern int target_big_endian;
+ /* This is the default endianness.  */
+ static int default_big_endian = TARGET_BYTES_BIG_ENDIAN;
  void (*ia64_number_to_chars) PARAMS ((char *, valueT, int));
  static void ia64_float_to_chars_bigendian
*************** dot_byteorder (byteorder)
*** 4406,4413 ****
    if (byteorder == -1)
        if (seginfo->tc_segment_info_data.endian == 0)
! 	seginfo->tc_segment_info_data.endian
        byteorder = seginfo->tc_segment_info_data.endian == 1;
--- 4410,4416 ----
    if (byteorder == -1)
        if (seginfo->tc_segment_info_data.endian == 0)
! 	seginfo->tc_segment_info_data.endian = default_big_endian ? 1 : 2;
        byteorder = seginfo->tc_segment_info_data.endian == 1;
*************** md_parse_option (c, arg)
*** 6528,6537 ****
--- 6531,6542 ----
        else if (strcmp (arg, "le") == 0)
  	  md.flags &= ~EF_IA_64_BE;
+ 	  default_big_endian = 0;
        else if (strcmp (arg, "be") == 0)
  	  md.flags |= EF_IA_64_BE;
+ 	  default_big_endian = 1;
  	return 0;
*************** md_begin ()
*** 6704,6710 ****
    /* Make sure function pointers get initialized.  */
    target_big_endian = -1;
!   dot_byteorder (TARGET_BYTES_BIG_ENDIAN);
    alias_hash = hash_new ();
    alias_name_hash = hash_new ();
--- 6709,6715 ----
    /* Make sure function pointers get initialized.  */
    target_big_endian = -1;
!   dot_byteorder (default_big_endian);
    alias_hash = hash_new ();
    alias_name_hash = hash_new ();

More information about the Binutils mailing list