1 // nacl.h -- Native Client support for gold -*- C++ -*-
3 // Copyright (C) 2012-2024 Free Software Foundation, Inc.
5 // This file is part of gold.
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.
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.
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.
22 #include "elfcpp_file.h"
25 #include "target-select.h"
37 Sniff_file(Input_file
* input_file
, off_t offset
)
38 : file_(input_file
->file()), offset_(offset
)
44 Location(off_t file_offset
, off_t data_size
)
45 : offset_(file_offset
), size_(data_size
)
48 inline off_t
offset() const
49 { return this->offset_
; }
51 inline section_size_type
size() const
52 { return this->size_
; }
56 section_size_type size_
;
62 View(File_read
& file
, off_t file_offset
, off_t data_size
)
63 : data_(file
.get_view(file_offset
, 0, data_size
, true, false))
66 const unsigned char* data()
67 { return this->data_
; }
70 const unsigned char* data_
;
73 View
view(off_t file_offset
, off_t data_size
)
75 return View(this->file_
, this->offset_
+ file_offset
, data_size
);
78 View
view(Location loc
)
80 return this->view(loc
.offset(), loc
.size());
85 error(const char* format
, ...) const ATTRIBUTE_PRINTF_2
;
93 template<class base_selector
, class nacl_target
>
94 class Target_selector_nacl
: public base_selector
97 Target_selector_nacl(const char* nacl_abi_name
,
98 const char* bfd_name
, const char* emulation
)
99 : base_selector(), is_nacl_(false), nacl_abi_name_(nacl_abi_name
),
100 bfd_name_(bfd_name
), emulation_(emulation
)
105 do_instantiate_target()
108 return new nacl_target();
109 return this->base_selector::do_instantiate_target();
113 do_recognize(Input_file
* file
, off_t offset
,
114 int machine
, int osabi
, int abiversion
)
116 this->is_nacl_
= file
!= NULL
&& this->recognize_nacl_file(file
, offset
);
118 return this->instantiate_target();
119 return this->base_selector::do_recognize(file
, offset
,
120 machine
, osabi
, abiversion
);
124 do_recognize_by_bfd_name(const char* name
)
126 gold_assert(this->bfd_name_
!= NULL
);
127 this->is_nacl_
= strcmp(name
, this->bfd_name_
) == 0;
129 return this->instantiate_target();
130 return this->base_selector::do_recognize_by_bfd_name(name
);
134 do_supported_bfd_names(std::vector
<const char*>* names
)
136 gold_assert(this->bfd_name_
!= NULL
);
137 this->base_selector::do_supported_bfd_names(names
);
138 names
->push_back(this->bfd_name_
);
142 do_supported_emulations(std::vector
<const char*>* emulations
)
144 gold_assert(this->emulation_
!= NULL
);
145 this->base_selector::do_supported_emulations(emulations
);
146 emulations
->push_back(this->emulation_
);
150 do_target_bfd_name(const Target
* target
)
152 return (!this->is_our_target(target
)
156 : base_selector::do_target_bfd_name(target
)));
161 recognize_nacl_file(Input_file
* input_file
, off_t offset
)
163 if (this->is_big_endian())
165 #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
166 # ifdef HAVE_TARGET_32_BIG
167 if (this->get_size() == 32)
168 return do_recognize_nacl_file
<32, true>(input_file
, offset
);
170 # ifdef HAVE_TARGET_64_BIG
171 if (this->get_size() == 64)
172 return do_recognize_nacl_file
<64, true>(input_file
, offset
);
179 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
180 # ifdef HAVE_TARGET_32_LITTLE
181 if (this->get_size() == 32)
182 return do_recognize_nacl_file
<32, false>(input_file
, offset
);
184 # ifdef HAVE_TARGET_64_LITTLE
185 if (this->get_size() == 64)
186 return do_recognize_nacl_file
<64, false>(input_file
, offset
);
193 template<int size
, bool big_endian
>
195 do_recognize_nacl_file(Input_file
* input_file
, off_t offset
)
197 Sniff_file
file(input_file
, offset
);
198 elfcpp::Elf_file
<size
, big_endian
, Sniff_file
> elf_file(&file
);
199 const unsigned int shnum
= elf_file
.shnum();
200 for (unsigned int shndx
= 1; shndx
< shnum
; ++shndx
)
202 if (elf_file
.section_type(shndx
) == elfcpp::SHT_NOTE
)
204 Sniff_file::Location loc
= elf_file
.section_contents(shndx
);
205 if (loc
.size() < (3 * 4
206 + align_address(sizeof "NaCl", 4)
207 + align_address(nacl_abi_name_
.size() + 1, 4)))
209 Sniff_file::View
view(file
.view(loc
));
210 const unsigned char* note_data
= view
.data();
211 if ((elfcpp::Swap
<32, big_endian
>::readval(note_data
+ 0)
213 && (elfcpp::Swap
<32, big_endian
>::readval(note_data
+ 4)
214 == nacl_abi_name_
.size() + 1)
215 && (elfcpp::Swap
<32, big_endian
>::readval(note_data
+ 8)
216 == elfcpp::NT_VERSION
))
218 const unsigned char* name
= note_data
+ 12;
219 const unsigned char* desc
= (name
220 + align_address(sizeof "NaCl", 4));
221 if (memcmp(name
, "NaCl", sizeof "NaCl") == 0
222 && memcmp(desc
, nacl_abi_name_
.c_str(),
223 nacl_abi_name_
.size() + 1) == 0)
231 // Whether we decided this was the NaCl target variant.
233 // The string found in the NaCl ABI note.
234 std::string nacl_abi_name_
;
235 // BFD name of NaCl target, for compatibility.
236 const char* const bfd_name_
;
237 // GNU linker emulation for this NaCl target, for compatibility.
238 const char* const emulation_
;
241 } // end namespace gold
243 #endif // !defined(GOLD_NACL_H)