184865Sobrien/* BFD back-end for HP/Intel IA-64 COFF files.
2218822Sdim   Copyright 1999, 2000, 2001, 2002, 2007 Free Software Foundation, Inc.
384865Sobrien   Contributed by David Mosberger <davidm@hpl.hp.com>
484865Sobrien
584865SobrienThis file is part of BFD, the Binary File Descriptor library.
684865Sobrien
784865SobrienThis program is free software; you can redistribute it and/or modify
884865Sobrienit under the terms of the GNU General Public License as published by
984865Sobrienthe Free Software Foundation; either version 2 of the License, or
1084865Sobrien(at your option) any later version.
1184865Sobrien
1284865SobrienThis program is distributed in the hope that it will be useful,
1384865Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1484865SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1584865SobrienGNU General Public License for more details.
1684865Sobrien
1784865SobrienYou should have received a copy of the GNU General Public License
1884865Sobrienalong with this program; if not, write to the Free Software
19218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2084865Sobrien
21218822Sdim#include "sysdep.h"
2284865Sobrien#include "bfd.h"
2384865Sobrien#include "libbfd.h"
2484865Sobrien#include "coff/ia64.h"
2584865Sobrien#include "coff/internal.h"
2684865Sobrien#include "coff/pe.h"
2784865Sobrien#include "libcoff.h"
2884865Sobrien
2984865Sobrien#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
3084865Sobrien/* The page size is a guess based on ELF.  */
3184865Sobrien
3284865Sobrien#define COFF_PAGE_SIZE 0x1000
3384865Sobrien
3484865Sobrienstatic reloc_howto_type howto_table[] =
3584865Sobrien{
3684865Sobrien  EMPTY_HOWTO (0),
3784865Sobrien};
3884865Sobrien
3984865Sobrien#define BADMAG(x) IA64BADMAG(x)
4084865Sobrien#define IA64 1			/* Customize coffcode.h */
4184865Sobrien
4284865Sobrien#ifdef COFF_WITH_pep
4384865Sobrien# undef AOUTSZ
4484865Sobrien# define AOUTSZ		PEPAOUTSZ
4584865Sobrien# define PEAOUTHDR	PEPAOUTHDR
4684865Sobrien#endif
4784865Sobrien
4884865Sobrien#define RTYPE2HOWTO(cache_ptr, dst) \
4984865Sobrien	    (cache_ptr)->howto = howto_table + (dst)->r_type;
5084865Sobrien
5184865Sobrien#ifdef COFF_WITH_PE
52130561Sobrien/* Return TRUE if this relocation should
5384865Sobrien   appear in the output .reloc section.  */
5484865Sobrien
55130561Sobrienstatic bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
5689857Sobrien
57130561Sobrienstatic bfd_boolean
5884865Sobrienin_reloc_p(abfd, howto)
5984865Sobrien     bfd * abfd ATTRIBUTE_UNUSED;
6084865Sobrien     reloc_howto_type *howto ATTRIBUTE_UNUSED;
6184865Sobrien{
62130561Sobrien  return FALSE;			/* We don't do relocs for now...  */
6384865Sobrien}
6484865Sobrien#endif
6584865Sobrien
6684865Sobrien#include "coffcode.h"
6784865Sobrien
6889857Sobrienstatic const bfd_target *ia64coff_object_p PARAMS ((bfd *));
6989857Sobrien
7084865Sobrienstatic const bfd_target *
7184865Sobrienia64coff_object_p (abfd)
7284865Sobrien     bfd *abfd;
7384865Sobrien{
7484865Sobrien#ifdef COFF_IMAGE_WITH_PE
7584865Sobrien  {
7684865Sobrien    struct external_PEI_DOS_hdr dos_hdr;
7784865Sobrien    struct external_PEI_IMAGE_hdr image_hdr;
7884865Sobrien    file_ptr offset;
7984865Sobrien
8089857Sobrien    if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
8189857Sobrien	|| (bfd_bread (&dos_hdr, (bfd_size_type) sizeof (dos_hdr), abfd)
8289857Sobrien	    != sizeof (dos_hdr)))
8384865Sobrien      {
8484865Sobrien	if (bfd_get_error () != bfd_error_system_call)
8584865Sobrien	  bfd_set_error (bfd_error_wrong_format);
8684865Sobrien	return NULL;
8784865Sobrien      }
8884865Sobrien
8984865Sobrien    /* There are really two magic numbers involved; the magic number
9084865Sobrien       that says this is a NT executable (PEI) and the magic number
9184865Sobrien       that determines the architecture.  The former is DOSMAGIC,
9284865Sobrien       stored in the e_magic field.  The latter is stored in the
9384865Sobrien       f_magic field.  If the NT magic number isn't valid, the
9484865Sobrien       architecture magic number could be mimicked by some other
9584865Sobrien       field (specifically, the number of relocs in section 3).  Since
9684865Sobrien       this routine can only be called correctly for a PEI file, check
9784865Sobrien       the e_magic number here, and, if it doesn't match, clobber the
9884865Sobrien       f_magic number so that we don't get a false match.  */
9989857Sobrien    if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
10084865Sobrien      {
10184865Sobrien	bfd_set_error (bfd_error_wrong_format);
10284865Sobrien	return NULL;
10384865Sobrien      }
10484865Sobrien
10589857Sobrien    offset = H_GET_32 (abfd, dos_hdr.e_lfanew);
10689857Sobrien    if (bfd_seek (abfd, offset, SEEK_SET) != 0
10789857Sobrien	|| (bfd_bread (&image_hdr, (bfd_size_type) sizeof (image_hdr), abfd)
10889857Sobrien	    != sizeof (image_hdr)))
10984865Sobrien      {
11084865Sobrien	if (bfd_get_error () != bfd_error_system_call)
11184865Sobrien	  bfd_set_error (bfd_error_wrong_format);
11284865Sobrien	return NULL;
11384865Sobrien      }
11484865Sobrien
11589857Sobrien    if (H_GET_32 (abfd, image_hdr.nt_signature)
11684865Sobrien	!= 0x4550)
11784865Sobrien      {
11884865Sobrien	bfd_set_error (bfd_error_wrong_format);
11984865Sobrien	return NULL;
12084865Sobrien      }
12184865Sobrien
12284865Sobrien    /* Here is the hack.  coff_object_p wants to read filhsz bytes to
12384865Sobrien       pick up the COFF header for PE, see "struct external_PEI_filehdr"
12484865Sobrien       in include/coff/pe.h.  We adjust so that that will work. */
12589857Sobrien    if (bfd_seek (abfd, offset - sizeof (dos_hdr), SEEK_SET) != 0)
12684865Sobrien      {
12784865Sobrien	if (bfd_get_error () != bfd_error_system_call)
12884865Sobrien	  bfd_set_error (bfd_error_wrong_format);
12984865Sobrien	return NULL;
13084865Sobrien      }
13184865Sobrien  }
13284865Sobrien#endif
13384865Sobrien
13484865Sobrien  return coff_object_p (abfd);
13584865Sobrien}
13684865Sobrien
13784865Sobrienconst bfd_target
13884865Sobrien#ifdef TARGET_SYM
13984865Sobrien  TARGET_SYM =
14084865Sobrien#else
14184865Sobrien  ia64coff_vec =
14284865Sobrien#endif
14384865Sobrien{
14484865Sobrien#ifdef TARGET_NAME
14584865Sobrien  TARGET_NAME,
14684865Sobrien#else
14784865Sobrien  "coff-ia64",			/* name */
14884865Sobrien#endif
14984865Sobrien  bfd_target_coff_flavour,
15084865Sobrien  BFD_ENDIAN_LITTLE,		/* data byte order is little */
15184865Sobrien  BFD_ENDIAN_LITTLE,		/* header byte order is little */
15284865Sobrien
15384865Sobrien  (HAS_RELOC | EXEC_P |		/* object flags */
15484865Sobrien   HAS_LINENO | HAS_DEBUG |
15584865Sobrien   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
15684865Sobrien
15784865Sobrien#ifndef COFF_WITH_PE
15884865Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
15984865Sobrien   | SEC_CODE | SEC_DATA),
16084865Sobrien#else
16184865Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
16284865Sobrien   | SEC_CODE | SEC_DATA
16384865Sobrien   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
16484865Sobrien#endif
16584865Sobrien
16684865Sobrien#ifdef TARGET_UNDERSCORE
16784865Sobrien  TARGET_UNDERSCORE,		/* leading underscore */
16884865Sobrien#else
16984865Sobrien  0,				/* leading underscore */
17084865Sobrien#endif
17184865Sobrien  '/',				/* ar_pad_char */
17284865Sobrien  15,				/* ar_max_namelen */
17384865Sobrien
17484865Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
17584865Sobrien     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
17684865Sobrien     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
17784865Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
17884865Sobrien     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
17984865Sobrien     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
18084865Sobrien
18184865Sobrien/* Note that we allow an object file to be treated as a core file as well.  */
18284865Sobrien    {_bfd_dummy_target, ia64coff_object_p, /* bfd_check_format */
18384865Sobrien       bfd_generic_archive_p, ia64coff_object_p},
18484865Sobrien    {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
18584865Sobrien       bfd_false},
18684865Sobrien    {bfd_false, coff_write_object_contents, /* bfd_write_contents */
18784865Sobrien       _bfd_write_archive_contents, bfd_false},
18884865Sobrien
18984865Sobrien     BFD_JUMP_TABLE_GENERIC (coff),
19084865Sobrien     BFD_JUMP_TABLE_COPY (coff),
19184865Sobrien     BFD_JUMP_TABLE_CORE (_bfd_nocore),
19284865Sobrien     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
19384865Sobrien     BFD_JUMP_TABLE_SYMBOLS (coff),
19484865Sobrien     BFD_JUMP_TABLE_RELOCS (coff),
19584865Sobrien     BFD_JUMP_TABLE_WRITE (coff),
19684865Sobrien     BFD_JUMP_TABLE_LINK (coff),
19784865Sobrien     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
19884865Sobrien
19984865Sobrien  NULL,
20084865Sobrien
20184865Sobrien  COFF_SWAP_TABLE
20284865Sobrien};
203