1/* Binutils emulation layer.
2   Copyright (C) 2002-2017 Free Software Foundation, Inc.
3   Written by Tom Rix, Red Hat Inc.
4
5   This file is part of GNU Binutils.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20   MA 02110-1301, USA.  */
21
22#include "binemul.h"
23#include "bfdlink.h"
24#include "coff/internal.h"
25#include "coff/xcoff.h"
26#include "libcoff.h"
27#include "libxcoff.h"
28
29/* Default to <bigaf>.  */
30/* FIXME: write only variable.  */
31static bfd_boolean big_archive = TRUE;
32
33/* Whether to include 32 bit objects.  */
34static bfd_boolean X32 = TRUE;
35
36/* Whether to include 64 bit objects.  */
37static bfd_boolean X64 = FALSE;
38
39static void
40ar_emul_aix_usage (FILE *fp)
41{
42  AR_EMUL_USAGE_PRINT_OPTION_HEADER (fp);
43  /* xgettext:c-format */
44  fprintf (fp, _("  [-g]         - 32 bit small archive\n"));
45  fprintf (fp, _("  [-X32]       - ignores 64 bit objects\n"));
46  fprintf (fp, _("  [-X64]       - ignores 32 bit objects\n"));
47  fprintf (fp, _("  [-X32_64]    - accepts 32 and 64 bit objects\n"));
48}
49
50static bfd_boolean
51check_aix (bfd *try_bfd)
52{
53  extern const bfd_target rs6000_xcoff_vec;
54  extern const bfd_target rs6000_xcoff64_vec;
55  extern const bfd_target rs6000_xcoff64_aix_vec;
56
57  if (bfd_check_format (try_bfd, bfd_object))
58    {
59      if (!X32 && try_bfd->xvec == &rs6000_xcoff_vec)
60	return FALSE;
61
62      if (!X64 && (try_bfd->xvec == &rs6000_xcoff64_vec
63		   || try_bfd->xvec == &rs6000_xcoff64_aix_vec))
64	return FALSE;
65    }
66  return TRUE;
67}
68
69static bfd_boolean
70ar_emul_aix_append (bfd **after_bfd, char *file_name, const char *target,
71		    bfd_boolean verbose, bfd_boolean flatten)
72{
73  bfd *new_bfd;
74
75  new_bfd = bfd_openr (file_name, target);
76  AR_EMUL_ELEMENT_CHECK (new_bfd, file_name);
77
78  return do_ar_emul_append (after_bfd, new_bfd, verbose, flatten, check_aix);
79}
80
81static bfd_boolean
82ar_emul_aix_replace (bfd **after_bfd, char *file_name, const char *target,
83		     bfd_boolean verbose)
84{
85  bfd *new_bfd;
86
87  new_bfd = bfd_openr (file_name, target);
88  AR_EMUL_ELEMENT_CHECK (new_bfd, file_name);
89
90  if (!check_aix (new_bfd))
91    return FALSE;
92
93  AR_EMUL_REPLACE_PRINT_VERBOSE (verbose, file_name);
94
95  new_bfd->archive_next = *after_bfd;
96  *after_bfd = new_bfd;
97
98  return TRUE;
99}
100
101static bfd_boolean
102ar_emul_aix_parse_arg (char *arg)
103{
104  if (CONST_STRNEQ (arg, "-X32_64"))
105    {
106      big_archive = TRUE;
107      X32 = TRUE;
108      X64 = TRUE;
109    }
110  else if (CONST_STRNEQ (arg, "-X32"))
111    {
112      big_archive = TRUE;
113      X32 = TRUE;
114      X64 = FALSE;
115    }
116  else if (CONST_STRNEQ (arg, "-X64"))
117    {
118      big_archive = TRUE;
119      X32 = FALSE;
120      X64 = TRUE;
121    }
122  else if (CONST_STRNEQ (arg, "-g"))
123    {
124      big_archive = FALSE;
125      X32 = TRUE;
126      X64 = FALSE;
127    }
128  else
129    return FALSE;
130
131  return TRUE;
132}
133
134struct bin_emulation_xfer_struct bin_aix_emulation =
135{
136  ar_emul_aix_usage,
137  ar_emul_aix_append,
138  ar_emul_aix_replace,
139  ar_emul_aix_parse_arg,
140};
141