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