xref: /openbsd-src/gnu/usr.bin/binutils/bfd/coff-ia64.c (revision d2201f2f89f0be1a0be6f7568000ed297414a06d)
15f210c2aSfgsch /* BFD back-end for HP/Intel IA-64 COFF files.
2*d2201f2fSdrahn    Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
35f210c2aSfgsch    Contributed by David Mosberger <davidm@hpl.hp.com>
45f210c2aSfgsch 
55f210c2aSfgsch This file is part of BFD, the Binary File Descriptor library.
65f210c2aSfgsch 
75f210c2aSfgsch This program is free software; you can redistribute it and/or modify
85f210c2aSfgsch it under the terms of the GNU General Public License as published by
95f210c2aSfgsch the Free Software Foundation; either version 2 of the License, or
105f210c2aSfgsch (at your option) any later version.
115f210c2aSfgsch 
125f210c2aSfgsch This program is distributed in the hope that it will be useful,
135f210c2aSfgsch but WITHOUT ANY WARRANTY; without even the implied warranty of
145f210c2aSfgsch MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155f210c2aSfgsch GNU General Public License for more details.
165f210c2aSfgsch 
175f210c2aSfgsch You should have received a copy of the GNU General Public License
185f210c2aSfgsch along with this program; if not, write to the Free Software
195f210c2aSfgsch Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
205f210c2aSfgsch 
215f210c2aSfgsch #include "bfd.h"
225f210c2aSfgsch #include "sysdep.h"
235f210c2aSfgsch #include "libbfd.h"
245f210c2aSfgsch #include "coff/ia64.h"
255f210c2aSfgsch #include "coff/internal.h"
265f210c2aSfgsch #include "coff/pe.h"
275f210c2aSfgsch #include "libcoff.h"
285f210c2aSfgsch 
295f210c2aSfgsch #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
305f210c2aSfgsch /* The page size is a guess based on ELF.  */
315f210c2aSfgsch 
325f210c2aSfgsch #define COFF_PAGE_SIZE 0x1000
335f210c2aSfgsch 
345f210c2aSfgsch static reloc_howto_type howto_table[] =
355f210c2aSfgsch {
365f210c2aSfgsch   EMPTY_HOWTO (0),
375f210c2aSfgsch };
385f210c2aSfgsch 
395f210c2aSfgsch #define BADMAG(x) IA64BADMAG(x)
405f210c2aSfgsch #define IA64 1			/* Customize coffcode.h */
415f210c2aSfgsch 
425f210c2aSfgsch #ifdef COFF_WITH_pep
435f210c2aSfgsch # undef AOUTSZ
445f210c2aSfgsch # define AOUTSZ		PEPAOUTSZ
455f210c2aSfgsch # define PEAOUTHDR	PEPAOUTHDR
465f210c2aSfgsch #endif
475f210c2aSfgsch 
485f210c2aSfgsch #define RTYPE2HOWTO(cache_ptr, dst) \
495f210c2aSfgsch 	    (cache_ptr)->howto = howto_table + (dst)->r_type;
505f210c2aSfgsch 
515f210c2aSfgsch #ifdef COFF_WITH_PE
52*d2201f2fSdrahn /* Return TRUE if this relocation should
535f210c2aSfgsch    appear in the output .reloc section.  */
545f210c2aSfgsch 
55*d2201f2fSdrahn static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
56*d2201f2fSdrahn 
57*d2201f2fSdrahn static bfd_boolean
in_reloc_p(abfd,howto)585f210c2aSfgsch in_reloc_p(abfd, howto)
595f210c2aSfgsch      bfd * abfd ATTRIBUTE_UNUSED;
605f210c2aSfgsch      reloc_howto_type *howto ATTRIBUTE_UNUSED;
615f210c2aSfgsch {
62*d2201f2fSdrahn   return FALSE;			/* We don't do relocs for now...  */
635f210c2aSfgsch }
645f210c2aSfgsch #endif
655f210c2aSfgsch 
665f210c2aSfgsch #include "coffcode.h"
675f210c2aSfgsch 
68*d2201f2fSdrahn static const bfd_target *ia64coff_object_p PARAMS ((bfd *));
69*d2201f2fSdrahn 
705f210c2aSfgsch static const bfd_target *
ia64coff_object_p(abfd)715f210c2aSfgsch ia64coff_object_p (abfd)
725f210c2aSfgsch      bfd *abfd;
735f210c2aSfgsch {
745f210c2aSfgsch #ifdef COFF_IMAGE_WITH_PE
755f210c2aSfgsch   {
765f210c2aSfgsch     struct external_PEI_DOS_hdr dos_hdr;
775f210c2aSfgsch     struct external_PEI_IMAGE_hdr image_hdr;
785f210c2aSfgsch     file_ptr offset;
795f210c2aSfgsch 
80*d2201f2fSdrahn     if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
81*d2201f2fSdrahn 	|| (bfd_bread (&dos_hdr, (bfd_size_type) sizeof (dos_hdr), abfd)
82*d2201f2fSdrahn 	    != sizeof (dos_hdr)))
835f210c2aSfgsch       {
845f210c2aSfgsch 	if (bfd_get_error () != bfd_error_system_call)
855f210c2aSfgsch 	  bfd_set_error (bfd_error_wrong_format);
865f210c2aSfgsch 	return NULL;
875f210c2aSfgsch       }
885f210c2aSfgsch 
895f210c2aSfgsch     /* There are really two magic numbers involved; the magic number
905f210c2aSfgsch        that says this is a NT executable (PEI) and the magic number
915f210c2aSfgsch        that determines the architecture.  The former is DOSMAGIC,
925f210c2aSfgsch        stored in the e_magic field.  The latter is stored in the
935f210c2aSfgsch        f_magic field.  If the NT magic number isn't valid, the
945f210c2aSfgsch        architecture magic number could be mimicked by some other
955f210c2aSfgsch        field (specifically, the number of relocs in section 3).  Since
965f210c2aSfgsch        this routine can only be called correctly for a PEI file, check
975f210c2aSfgsch        the e_magic number here, and, if it doesn't match, clobber the
985f210c2aSfgsch        f_magic number so that we don't get a false match.  */
99*d2201f2fSdrahn     if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
1005f210c2aSfgsch       {
1015f210c2aSfgsch 	bfd_set_error (bfd_error_wrong_format);
1025f210c2aSfgsch 	return NULL;
1035f210c2aSfgsch       }
1045f210c2aSfgsch 
105*d2201f2fSdrahn     offset = H_GET_32 (abfd, dos_hdr.e_lfanew);
106*d2201f2fSdrahn     if (bfd_seek (abfd, offset, SEEK_SET) != 0
107*d2201f2fSdrahn 	|| (bfd_bread (&image_hdr, (bfd_size_type) sizeof (image_hdr), abfd)
108*d2201f2fSdrahn 	    != sizeof (image_hdr)))
1095f210c2aSfgsch       {
1105f210c2aSfgsch 	if (bfd_get_error () != bfd_error_system_call)
1115f210c2aSfgsch 	  bfd_set_error (bfd_error_wrong_format);
1125f210c2aSfgsch 	return NULL;
1135f210c2aSfgsch       }
1145f210c2aSfgsch 
115*d2201f2fSdrahn     if (H_GET_32 (abfd, image_hdr.nt_signature)
1165f210c2aSfgsch 	!= 0x4550)
1175f210c2aSfgsch       {
1185f210c2aSfgsch 	bfd_set_error (bfd_error_wrong_format);
1195f210c2aSfgsch 	return NULL;
1205f210c2aSfgsch       }
1215f210c2aSfgsch 
1225f210c2aSfgsch     /* Here is the hack.  coff_object_p wants to read filhsz bytes to
1235f210c2aSfgsch        pick up the COFF header for PE, see "struct external_PEI_filehdr"
1245f210c2aSfgsch        in include/coff/pe.h.  We adjust so that that will work. */
125*d2201f2fSdrahn     if (bfd_seek (abfd, offset - sizeof (dos_hdr), SEEK_SET) != 0)
1265f210c2aSfgsch       {
1275f210c2aSfgsch 	if (bfd_get_error () != bfd_error_system_call)
1285f210c2aSfgsch 	  bfd_set_error (bfd_error_wrong_format);
1295f210c2aSfgsch 	return NULL;
1305f210c2aSfgsch       }
1315f210c2aSfgsch   }
1325f210c2aSfgsch #endif
1335f210c2aSfgsch 
1345f210c2aSfgsch   return coff_object_p (abfd);
1355f210c2aSfgsch }
1365f210c2aSfgsch 
1375f210c2aSfgsch const bfd_target
1385f210c2aSfgsch #ifdef TARGET_SYM
1395f210c2aSfgsch   TARGET_SYM =
1405f210c2aSfgsch #else
1415f210c2aSfgsch   ia64coff_vec =
1425f210c2aSfgsch #endif
1435f210c2aSfgsch {
1445f210c2aSfgsch #ifdef TARGET_NAME
1455f210c2aSfgsch   TARGET_NAME,
1465f210c2aSfgsch #else
1475f210c2aSfgsch   "coff-ia64",			/* name */
1485f210c2aSfgsch #endif
1495f210c2aSfgsch   bfd_target_coff_flavour,
1505f210c2aSfgsch   BFD_ENDIAN_LITTLE,		/* data byte order is little */
1515f210c2aSfgsch   BFD_ENDIAN_LITTLE,		/* header byte order is little */
1525f210c2aSfgsch 
1535f210c2aSfgsch   (HAS_RELOC | EXEC_P |		/* object flags */
1545f210c2aSfgsch    HAS_LINENO | HAS_DEBUG |
1555f210c2aSfgsch    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1565f210c2aSfgsch 
1575f210c2aSfgsch #ifndef COFF_WITH_PE
1585f210c2aSfgsch   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
1595f210c2aSfgsch    | SEC_CODE | SEC_DATA),
1605f210c2aSfgsch #else
1615f210c2aSfgsch   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
1625f210c2aSfgsch    | SEC_CODE | SEC_DATA
1635f210c2aSfgsch    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
1645f210c2aSfgsch #endif
1655f210c2aSfgsch 
1665f210c2aSfgsch #ifdef TARGET_UNDERSCORE
1675f210c2aSfgsch   TARGET_UNDERSCORE,		/* leading underscore */
1685f210c2aSfgsch #else
1695f210c2aSfgsch   0,				/* leading underscore */
1705f210c2aSfgsch #endif
1715f210c2aSfgsch   '/',				/* ar_pad_char */
1725f210c2aSfgsch   15,				/* ar_max_namelen */
1735f210c2aSfgsch 
1745f210c2aSfgsch   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1755f210c2aSfgsch      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1765f210c2aSfgsch      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1775f210c2aSfgsch   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1785f210c2aSfgsch      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1795f210c2aSfgsch      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
1805f210c2aSfgsch 
1815f210c2aSfgsch /* Note that we allow an object file to be treated as a core file as well.  */
1825f210c2aSfgsch     {_bfd_dummy_target, ia64coff_object_p, /* bfd_check_format */
1835f210c2aSfgsch        bfd_generic_archive_p, ia64coff_object_p},
1845f210c2aSfgsch     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
1855f210c2aSfgsch        bfd_false},
1865f210c2aSfgsch     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
1875f210c2aSfgsch        _bfd_write_archive_contents, bfd_false},
1885f210c2aSfgsch 
1895f210c2aSfgsch      BFD_JUMP_TABLE_GENERIC (coff),
1905f210c2aSfgsch      BFD_JUMP_TABLE_COPY (coff),
1915f210c2aSfgsch      BFD_JUMP_TABLE_CORE (_bfd_nocore),
1925f210c2aSfgsch      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
1935f210c2aSfgsch      BFD_JUMP_TABLE_SYMBOLS (coff),
1945f210c2aSfgsch      BFD_JUMP_TABLE_RELOCS (coff),
1955f210c2aSfgsch      BFD_JUMP_TABLE_WRITE (coff),
1965f210c2aSfgsch      BFD_JUMP_TABLE_LINK (coff),
1975f210c2aSfgsch      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1985f210c2aSfgsch 
1995f210c2aSfgsch   NULL,
2005f210c2aSfgsch 
2015f210c2aSfgsch   COFF_SWAP_TABLE
2025f210c2aSfgsch };
203