1*fae548d3Szrj // target-select.cc -- select a target for an object file
2*fae548d3Szrj 
3*fae548d3Szrj // Copyright (C) 2006-2020 Free Software Foundation, Inc.
4*fae548d3Szrj // Written by Ian Lance Taylor <iant@google.com>.
5*fae548d3Szrj 
6*fae548d3Szrj // This file is part of gold.
7*fae548d3Szrj 
8*fae548d3Szrj // This program is free software; you can redistribute it and/or modify
9*fae548d3Szrj // it under the terms of the GNU General Public License as published by
10*fae548d3Szrj // the Free Software Foundation; either version 3 of the License, or
11*fae548d3Szrj // (at your option) any later version.
12*fae548d3Szrj 
13*fae548d3Szrj // This program is distributed in the hope that it will be useful,
14*fae548d3Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*fae548d3Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*fae548d3Szrj // GNU General Public License for more details.
17*fae548d3Szrj 
18*fae548d3Szrj // You should have received a copy of the GNU General Public License
19*fae548d3Szrj // along with this program; if not, write to the Free Software
20*fae548d3Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*fae548d3Szrj // MA 02110-1301, USA.
22*fae548d3Szrj 
23*fae548d3Szrj #include "gold.h"
24*fae548d3Szrj 
25*fae548d3Szrj #include <cstdio>
26*fae548d3Szrj #include <cstring>
27*fae548d3Szrj 
28*fae548d3Szrj #include "elfcpp.h"
29*fae548d3Szrj #include "options.h"
30*fae548d3Szrj #include "parameters.h"
31*fae548d3Szrj #include "target-select.h"
32*fae548d3Szrj 
33*fae548d3Szrj namespace
34*fae548d3Szrj {
35*fae548d3Szrj 
36*fae548d3Szrj // The start of the list of target selectors.
37*fae548d3Szrj 
38*fae548d3Szrj gold::Target_selector* target_selectors;
39*fae548d3Szrj 
40*fae548d3Szrj } // End anonymous namespace.
41*fae548d3Szrj 
42*fae548d3Szrj namespace gold
43*fae548d3Szrj {
44*fae548d3Szrj 
45*fae548d3Szrj // Class Set_target_once.
46*fae548d3Szrj 
47*fae548d3Szrj void
do_run_once(void *)48*fae548d3Szrj Set_target_once::do_run_once(void*)
49*fae548d3Szrj {
50*fae548d3Szrj   this->target_selector_->set_target();
51*fae548d3Szrj }
52*fae548d3Szrj 
53*fae548d3Szrj // Construct a Target_selector, which means adding it to the linked
54*fae548d3Szrj // list.  This runs at global constructor time, so we want it to be
55*fae548d3Szrj // fast.
56*fae548d3Szrj 
Target_selector(int machine,int size,bool is_big_endian,const char * bfd_name,const char * emulation)57*fae548d3Szrj Target_selector::Target_selector(int machine, int size, bool is_big_endian,
58*fae548d3Szrj 				 const char* bfd_name, const char* emulation)
59*fae548d3Szrj   : machine_(machine), size_(size), is_big_endian_(is_big_endian),
60*fae548d3Szrj     bfd_name_(bfd_name), emulation_(emulation), instantiated_target_(NULL),
61*fae548d3Szrj     set_target_once_(this)
62*fae548d3Szrj {
63*fae548d3Szrj   this->next_ = target_selectors;
64*fae548d3Szrj   target_selectors = this;
65*fae548d3Szrj }
66*fae548d3Szrj 
67*fae548d3Szrj // Instantiate the target and return it.  Use SET_TARGET_ONCE_ to
68*fae548d3Szrj // avoid instantiating two instances of the same target.
69*fae548d3Szrj 
70*fae548d3Szrj Target*
instantiate_target()71*fae548d3Szrj Target_selector::instantiate_target()
72*fae548d3Szrj {
73*fae548d3Szrj   this->set_target_once_.run_once(NULL);
74*fae548d3Szrj   return this->instantiated_target_;
75*fae548d3Szrj }
76*fae548d3Szrj 
77*fae548d3Szrj // Instantiate the target.  This is called at most once.
78*fae548d3Szrj 
79*fae548d3Szrj void
set_target()80*fae548d3Szrj Target_selector::set_target()
81*fae548d3Szrj {
82*fae548d3Szrj   gold_assert(this->instantiated_target_ == NULL);
83*fae548d3Szrj   this->instantiated_target_ = this->do_instantiate_target();
84*fae548d3Szrj }
85*fae548d3Szrj 
86*fae548d3Szrj // If we instantiated TARGET, return the corresponding BFD name.
87*fae548d3Szrj 
88*fae548d3Szrj const char*
do_target_bfd_name(const Target * target)89*fae548d3Szrj Target_selector::do_target_bfd_name(const Target* target)
90*fae548d3Szrj {
91*fae548d3Szrj   if (!this->is_our_target(target))
92*fae548d3Szrj     return NULL;
93*fae548d3Szrj   const char* my_bfd_name = this->bfd_name();
94*fae548d3Szrj   gold_assert(my_bfd_name != NULL);
95*fae548d3Szrj   return my_bfd_name;
96*fae548d3Szrj }
97*fae548d3Szrj 
98*fae548d3Szrj // Find the target for an ELF file.
99*fae548d3Szrj 
100*fae548d3Szrj Target*
select_target(Input_file * input_file,off_t offset,int machine,int size,bool is_big_endian,int osabi,int abiversion)101*fae548d3Szrj select_target(Input_file* input_file, off_t offset,
102*fae548d3Szrj 	      int machine, int size, bool is_big_endian,
103*fae548d3Szrj 	      int osabi, int abiversion)
104*fae548d3Szrj {
105*fae548d3Szrj   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
106*fae548d3Szrj     {
107*fae548d3Szrj       int pmach = p->machine();
108*fae548d3Szrj       if ((pmach == machine || pmach == elfcpp::EM_NONE)
109*fae548d3Szrj 	  && p->get_size() == size
110*fae548d3Szrj 	  && (p->is_big_endian() ? is_big_endian : !is_big_endian))
111*fae548d3Szrj 	{
112*fae548d3Szrj 	  Target* ret = p->recognize(input_file, offset,
113*fae548d3Szrj 				     machine, osabi, abiversion);
114*fae548d3Szrj 	  if (ret != NULL)
115*fae548d3Szrj 	    return ret;
116*fae548d3Szrj 	}
117*fae548d3Szrj     }
118*fae548d3Szrj   return NULL;
119*fae548d3Szrj }
120*fae548d3Szrj 
121*fae548d3Szrj // Find a target using a BFD name.  This is used to support the
122*fae548d3Szrj // --oformat option.
123*fae548d3Szrj 
124*fae548d3Szrj Target*
select_target_by_bfd_name(const char * name)125*fae548d3Szrj select_target_by_bfd_name(const char* name)
126*fae548d3Szrj {
127*fae548d3Szrj   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
128*fae548d3Szrj     {
129*fae548d3Szrj       const char* pname = p->bfd_name();
130*fae548d3Szrj       if (pname == NULL || strcmp(pname, name) == 0)
131*fae548d3Szrj 	{
132*fae548d3Szrj 	  Target* ret = p->recognize_by_bfd_name(name);
133*fae548d3Szrj 	  if (ret != NULL)
134*fae548d3Szrj 	    return ret;
135*fae548d3Szrj 	}
136*fae548d3Szrj     }
137*fae548d3Szrj   return NULL;
138*fae548d3Szrj }
139*fae548d3Szrj 
140*fae548d3Szrj // Find a target using a GNU linker emulation.  This is used to
141*fae548d3Szrj // support the -m option.
142*fae548d3Szrj 
143*fae548d3Szrj Target*
select_target_by_emulation(const char * name)144*fae548d3Szrj select_target_by_emulation(const char* name)
145*fae548d3Szrj {
146*fae548d3Szrj   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
147*fae548d3Szrj     {
148*fae548d3Szrj       const char* pname = p->emulation();
149*fae548d3Szrj       if (pname == NULL || strcmp(pname, name) == 0)
150*fae548d3Szrj 	{
151*fae548d3Szrj 	  Target* ret = p->recognize_by_emulation(name);
152*fae548d3Szrj 	  if (ret != NULL)
153*fae548d3Szrj 	    return ret;
154*fae548d3Szrj 	}
155*fae548d3Szrj     }
156*fae548d3Szrj   return NULL;
157*fae548d3Szrj }
158*fae548d3Szrj 
159*fae548d3Szrj // Push all the supported BFD names onto a vector.
160*fae548d3Szrj 
161*fae548d3Szrj void
supported_target_names(std::vector<const char * > * names)162*fae548d3Szrj supported_target_names(std::vector<const char*>* names)
163*fae548d3Szrj {
164*fae548d3Szrj   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
165*fae548d3Szrj     p->supported_bfd_names(names);
166*fae548d3Szrj }
167*fae548d3Szrj 
168*fae548d3Szrj // Push all the supported emulations onto a vector.
169*fae548d3Szrj 
170*fae548d3Szrj void
supported_emulation_names(std::vector<const char * > * names)171*fae548d3Szrj supported_emulation_names(std::vector<const char*>* names)
172*fae548d3Szrj {
173*fae548d3Szrj   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
174*fae548d3Szrj     p->supported_emulations(names);
175*fae548d3Szrj }
176*fae548d3Szrj 
177*fae548d3Szrj // Implement the --print-output-format option.
178*fae548d3Szrj 
179*fae548d3Szrj void
print_output_format()180*fae548d3Szrj print_output_format()
181*fae548d3Szrj {
182*fae548d3Szrj   if (!parameters->target_valid())
183*fae548d3Szrj     {
184*fae548d3Szrj       // This case arises when --print-output-format is used with no
185*fae548d3Szrj       // input files.  We need to come up with the right string to
186*fae548d3Szrj       // print based on the other options.  If the user specified the
187*fae548d3Szrj       // format using a --oformat option, use that.  That saves each
188*fae548d3Szrj       // target from having to remember the name that was used to
189*fae548d3Szrj       // select it.  In other cases, we will just have to ask the
190*fae548d3Szrj       // target.
191*fae548d3Szrj       if (parameters->options().user_set_oformat())
192*fae548d3Szrj 	{
193*fae548d3Szrj 	  const char* bfd_name = parameters->options().oformat();
194*fae548d3Szrj 	  Target* target = select_target_by_bfd_name(bfd_name);
195*fae548d3Szrj 	  if (target != NULL)
196*fae548d3Szrj 	    printf("%s\n", bfd_name);
197*fae548d3Szrj 	  else
198*fae548d3Szrj 	    gold_error(_("unrecognized output format %s"), bfd_name);
199*fae548d3Szrj 	  return;
200*fae548d3Szrj 	}
201*fae548d3Szrj 
202*fae548d3Szrj       parameters_force_valid_target();
203*fae548d3Szrj     }
204*fae548d3Szrj 
205*fae548d3Szrj   const Target* target = &parameters->target();
206*fae548d3Szrj   for (Target_selector* p = target_selectors; p != NULL; p = p->next())
207*fae548d3Szrj     {
208*fae548d3Szrj       const char* bfd_name = p->target_bfd_name(target);
209*fae548d3Szrj       if (bfd_name != NULL)
210*fae548d3Szrj 	{
211*fae548d3Szrj 	  printf("%s\n", bfd_name);
212*fae548d3Szrj 	  return;
213*fae548d3Szrj 	}
214*fae548d3Szrj     }
215*fae548d3Szrj 
216*fae548d3Szrj   gold_unreachable();
217*fae548d3Szrj }
218*fae548d3Szrj 
219*fae548d3Szrj } // End namespace gold.
220