]>
Commit | Line | Data |
---|---|---|
4e6f9223 SC |
1 | /* Generic target-file-type support for the BFD library. |
2 | Copyright (C) 1990-1991 Free Software Foundation, Inc. | |
3 | Written by Cygnus Support. | |
4a81b561 | 4 | |
4e6f9223 | 5 | This file is part of BFD, the Binary File Descriptor library. |
4a81b561 | 6 | |
4e6f9223 | 7 | This program is free software; you can redistribute it and/or modify |
4a81b561 | 8 | it under the terms of the GNU General Public License as published by |
4e6f9223 SC |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. | |
4a81b561 | 11 | |
4e6f9223 | 12 | This program is distributed in the hope that it will be useful, |
4a81b561 DHW |
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 | |
4e6f9223 SC |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
4a81b561 DHW |
20 | |
21 | /* $Id$ */ | |
22 | ||
7ed4093a | 23 | #include <sysdep.h> |
4a81b561 DHW |
24 | #include "bfd.h" |
25 | #include "libbfd.h" | |
26 | ||
6f715d66 SC |
27 | /*doc* |
28 | @section Targets | |
29 | Each port of BFD to a different machine requries the creation of a | |
4e6f9223 | 30 | target back end. All the back end provides to the root part of BFD is |
6f715d66 SC |
31 | a structure containing pointers to functions which perform certain low |
32 | level operations on files. BFD translates the applications's requests | |
33 | through a pointer into calls to the back end routines. | |
34 | ||
35 | When a file is opened with @code{bfd_openr}, its format and target are | |
36 | unknown. BFD uses various mechanisms to determine how to interpret the | |
3f85ebce | 37 | file. The operations performed are: |
6f715d66 SC |
38 | @itemize @bullet |
39 | @item | |
4e6f9223 | 40 | First a BFD is created by calling the internal routine |
6f715d66 | 41 | @code{new_bfd}, then @code{bfd_find_target} is called with the target |
4e6f9223 | 42 | string supplied to @code{bfd_openr} and the new BFD pointer. |
6f715d66 SC |
43 | @item |
44 | If a null target string was provided to | |
45 | @code{bfd_find_target}, it looks up the environment variable | |
46 | @code{GNUTARGET} and uses that as the target string. | |
47 | @item | |
48 | If the target string is still NULL, or the target string | |
49 | is @code{default}, then the first item in the target vector is used as | |
4e6f9223 | 50 | the target type. @xref{bfd_target}. |
6f715d66 SC |
51 | @item |
52 | Otherwise, the elements in the target vector are | |
53 | inspected one by one, until a match on target name is found. When | |
54 | found, that is used. | |
55 | @item | |
56 | Otherwise the error @code{invalid_target} is returned to | |
57 | @code{bfd_openr}. | |
58 | @item | |
59 | @code{bfd_openr} attempts to open the file using | |
4e6f9223 | 60 | @code{bfd_open_file}, and returns the BFD. |
6f715d66 | 61 | @end itemize |
4e6f9223 | 62 | Once the BFD has been opened and the target selected, the file format |
6f715d66 | 63 | may be determined. This is done by calling @code{bfd_check_format} on |
4e6f9223 | 64 | the BFD with a suggested format. The routine returns @code{true} when |
6f715d66 SC |
65 | the application guesses right. |
66 | */ | |
67 | ||
68 | ||
69 | /*proto* bfd_target | |
70 | @node bfd_target | |
71 | @subsection bfd_target | |
72 | This structure contains everything that BFD knows about a target. | |
73 | It includes things like its byte order, name, what routines to call | |
74 | to do various operations, etc. | |
75 | ||
76 | Every BFD points to a target structure with its "xvec" member. | |
77 | ||
78 | ||
79 | Shortcut for declaring fields which are prototyped function pointers, | |
80 | while avoiding anguish on compilers that don't support protos. | |
81 | ||
82 | $#define SDEF(ret, name, arglist) \ | |
83 | $ PROTO(ret,(*name),arglist) | |
84 | $#define SDEF_FMT(ret, name, arglist) \ | |
85 | $ PROTO(ret,(*name[bfd_type_end]),arglist) | |
86 | ||
87 | These macros are used to dispatch to functions through the bfd_target | |
4e6f9223 SC |
88 | vector. They are used in a number of macros further down in @file{bfd.h}, and |
89 | are also used when calling various routines by hand inside the BFD | |
6f715d66 SC |
90 | implementation. The "arglist" argument must be parenthesized; it |
91 | contains all the arguments to the called function. | |
92 | ||
93 | $#define BFD_SEND(bfd, message, arglist) \ | |
94 | $ ((*((bfd)->xvec->message)) arglist) | |
95 | ||
4e6f9223 | 96 | For operations which index on the BFD format |
6f715d66 SC |
97 | |
98 | $#define BFD_SEND_FMT(bfd, message, arglist) \ | |
99 | $ (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) | |
100 | ||
101 | This is the struct which defines the type of BFD this is. The | |
4e6f9223 | 102 | "xvec" member of the struct @code{bfd} itself points here. Each module |
6f715d66 SC |
103 | that implements access to a different target under BFD, defines |
104 | one of these. | |
105 | ||
106 | FIXME, these names should be rationalised with the names of the | |
107 | entry points which call them. Too bad we can't have one macro to | |
108 | define them both! | |
109 | ||
110 | *+++ | |
111 | ||
112 | $typedef struct bfd_target | |
113 | ${ | |
114 | ||
115 | identifies the kind of target, eg SunOS4, Ultrix, etc | |
116 | ||
117 | $ char *name; | |
118 | ||
119 | The "flavour" of a back end is a general indication about the contents | |
120 | of a file. | |
121 | ||
122 | $ enum target_flavour_enum { | |
123 | $ bfd_target_aout_flavour_enum, | |
124 | $ bfd_target_coff_flavour_enum, | |
3f85ebce | 125 | $ bfd_target_elf_flavour_enum, |
6f715d66 SC |
126 | $ bfd_target_ieee_flavour_enum, |
127 | $ bfd_target_oasys_flavour_enum, | |
128 | $ bfd_target_srec_flavour_enum} flavour; | |
129 | ||
130 | The order of bytes within the data area of a file. | |
131 | ||
132 | $ boolean byteorder_big_p; | |
133 | ||
134 | The order of bytes within the header parts of a file. | |
135 | ||
136 | $ boolean header_byteorder_big_p; | |
137 | ||
138 | This is a mask of all the flags which an executable may have set - | |
139 | from the set @code{NO_FLAGS}, @code{HAS_RELOC}, ...@code{D_PAGED}. | |
140 | ||
141 | $ flagword object_flags; | |
142 | ||
143 | This is a mask of all the flags which a section may have set - from | |
144 | the set @code{SEC_NO_FLAGS}, @code{SEC_ALLOC}, ...@code{SET_NEVER_LOAD}. | |
145 | ||
146 | $ flagword section_flags; | |
147 | ||
148 | The pad character for filenames within an archive header. | |
149 | ||
150 | $ char ar_pad_char; | |
151 | ||
152 | The maximum number of characters in an archive header. | |
153 | ||
154 | $ unsigned short ar_max_namelen; | |
155 | ||
156 | The minimum alignment restriction for any section. | |
157 | ||
158 | $ unsigned int align_power_min; | |
159 | ||
160 | Entries for byte swapping for data. These are different to the other | |
4e6f9223 | 161 | entry points, since they don't take BFD as first arg. Certain other handlers |
6f715d66 SC |
162 | could do the same. |
163 | ||
81f3996f SC |
164 | $ SDEF (bfd_vma, bfd_getx64, (bfd_byte *)); |
165 | $ SDEF (void, bfd_putx64, (bfd_vma, bfd_byte *)); | |
166 | $ SDEF (bfd_vma, bfd_getx32, (bfd_byte *)); | |
167 | $ SDEF (void, bfd_putx32, (bfd_vma, bfd_byte *)); | |
168 | $ SDEF (bfd_vma, bfd_getx16, (bfd_byte *)); | |
169 | $ SDEF (void, bfd_putx16, (bfd_vma, bfd_byte *)); | |
6f715d66 SC |
170 | |
171 | Byte swapping for the headers | |
172 | ||
4e6f9223 | 173 | $ SDEF (bfd_vma, bfd_h_getx64, (bfd_byte *)); |
81f3996f SC |
174 | $ SDEF (void, bfd_h_putx64, (bfd_vma, bfd_byte *)); |
175 | $ SDEF (bfd_vma, bfd_h_getx32, (bfd_byte *)); | |
176 | $ SDEF (void, bfd_h_putx32, (bfd_vma, bfd_byte *)); | |
177 | $ SDEF (bfd_vma, bfd_h_getx16, (bfd_byte *)); | |
178 | $ SDEF (void, bfd_h_putx16, (bfd_vma, bfd_byte *)); | |
6f715d66 SC |
179 | |
180 | Format dependent routines, these turn into vectors of entry points | |
181 | within the target vector structure; one for each format to check. | |
182 | ||
183 | Check the format of a file being read. Return bfd_target * or zero. | |
184 | ||
185 | $ SDEF_FMT (struct bfd_target *, _bfd_check_format, (bfd *)); | |
186 | ||
187 | Set the format of a file being written. | |
188 | ||
189 | $ SDEF_FMT (boolean, _bfd_set_format, (bfd *)); | |
190 | ||
191 | Write cached information into a file being written, at bfd_close. | |
192 | ||
193 | $ SDEF_FMT (boolean, _bfd_write_contents, (bfd *)); | |
194 | ||
195 | The following functions are defined in @code{JUMP_TABLE}. The idea is | |
196 | that the back end writer of @code{foo} names all the routines | |
197 | @code{foo_}@var{entry_point}, @code{JUMP_TABLE} will built the entries | |
198 | in this structure in the right order. | |
199 | ||
200 | Core file entry points | |
201 | ||
202 | $ SDEF (char *, _core_file_failing_command, (bfd *)); | |
203 | $ SDEF (int, _core_file_failing_signal, (bfd *)); | |
204 | $ SDEF (boolean, _core_file_matches_executable_p, (bfd *, bfd *)); | |
205 | ||
206 | Archive entry points | |
207 | ||
208 | $ SDEF (boolean, _bfd_slurp_armap, (bfd *)); | |
209 | $ SDEF (boolean, _bfd_slurp_extended_name_table, (bfd *)); | |
210 | $ SDEF (void, _bfd_truncate_arname, (bfd *, CONST char *, char *)); | |
211 | $ SDEF (boolean, write_armap, (bfd *arch, | |
212 | $ unsigned int elength, | |
213 | $ struct orl *map, | |
214 | $ int orl_count, | |
215 | $ int stridx)); | |
216 | ||
217 | Standard stuff. | |
218 | ||
219 | $ SDEF (boolean, _close_and_cleanup, (bfd *)); | |
220 | $ SDEF (boolean, _bfd_set_section_contents, (bfd *, sec_ptr, PTR, | |
221 | $ file_ptr, bfd_size_type)); | |
222 | $ SDEF (boolean, _bfd_get_section_contents, (bfd *, sec_ptr, PTR, | |
223 | $ file_ptr, bfd_size_type)); | |
224 | $ SDEF (boolean, _new_section_hook, (bfd *, sec_ptr)); | |
225 | ||
226 | Symbols and reloctions | |
227 | ||
228 | $ SDEF (unsigned int, _get_symtab_upper_bound, (bfd *)); | |
229 | $ SDEF (unsigned int, _bfd_canonicalize_symtab, | |
230 | $ (bfd *, struct symbol_cache_entry **)); | |
231 | $ SDEF (unsigned int, _get_reloc_upper_bound, (bfd *, sec_ptr)); | |
232 | $ SDEF (unsigned int, _bfd_canonicalize_reloc, (bfd *, sec_ptr, arelent **, | |
233 | $ struct symbol_cache_entry**)); | |
234 | $ SDEF (struct symbol_cache_entry *, _bfd_make_empty_symbol, (bfd *)); | |
235 | $ SDEF (void, _bfd_print_symbol, (bfd *, PTR, struct symbol_cache_entry *, | |
236 | $ bfd_print_symbol_enum_type)); | |
237 | $#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e)) | |
238 | $ SDEF (alent *, _get_lineno, (bfd *, struct symbol_cache_entry *)); | |
239 | $ | |
240 | $ SDEF (boolean, _bfd_set_arch_mach, (bfd *, enum bfd_architecture, | |
241 | $ unsigned long)); | |
242 | $ | |
243 | $ SDEF (bfd *, openr_next_archived_file, (bfd *arch, bfd *prev)); | |
244 | $ SDEF (boolean, _bfd_find_nearest_line, | |
245 | $ (bfd *abfd, struct sec *section, | |
246 | $ struct symbol_cache_entry **symbols,bfd_vma offset, | |
247 | $ CONST char **file, CONST char **func, unsigned int *line)); | |
248 | $ SDEF (int, _bfd_stat_arch_elt, (bfd *, struct stat *)); | |
249 | $ | |
250 | $ SDEF (int, _bfd_sizeof_headers, (bfd *, boolean)); | |
251 | $ | |
252 | $ SDEF (void, _bfd_debug_info_start, (bfd *)); | |
253 | $ SDEF (void, _bfd_debug_info_end, (bfd *)); | |
254 | $ SDEF (void, _bfd_debug_info_accumulate, (bfd *, struct sec *)); | |
255 | ||
256 | Special entry points for gdb to swap in coff symbol table parts | |
257 | ||
258 | $ SDEF(void, _bfd_coff_swap_aux_in,( | |
259 | $ bfd *abfd , | |
260 | $ PTR ext, | |
261 | $ int type, | |
262 | $ int class , | |
263 | $ PTR in)); | |
264 | $ | |
265 | $ SDEF(void, _bfd_coff_swap_sym_in,( | |
266 | $ bfd *abfd , | |
267 | $ PTR ext, | |
268 | $ PTR in)); | |
269 | $ | |
270 | $ SDEF(void, _bfd_coff_swap_lineno_in, ( | |
271 | $ bfd *abfd, | |
272 | $ PTR ext, | |
273 | $ PTR in)); | |
274 | $ | |
275 | $} bfd_target; | |
276 | ||
277 | *--- | |
278 | ||
279 | */ | |
23b0b558 JG |
280 | extern bfd_target ecoff_little_vec; |
281 | extern bfd_target ecoff_big_vec; | |
2b1d8a50 | 282 | extern bfd_target sunos_big_vec; |
7ed4093a | 283 | extern bfd_target demo_64_vec; |
4a81b561 DHW |
284 | extern bfd_target srec_vec; |
285 | extern bfd_target b_out_vec_little_host; | |
286 | extern bfd_target b_out_vec_big_host; | |
287 | extern bfd_target icoff_little_vec; | |
288 | extern bfd_target icoff_big_vec; | |
3f85ebce JG |
289 | extern bfd_target elf_little_vec; |
290 | extern bfd_target elf_big_vec; | |
aacf30e3 DHW |
291 | extern bfd_target ieee_vec; |
292 | extern bfd_target oasys_vec; | |
293 | extern bfd_target m88k_bcs_vec; | |
c407897e | 294 | extern bfd_target m68kcoff_vec; |
20fdc627 | 295 | extern bfd_target i386coff_vec; |
41f50af0 | 296 | extern bfd_target a29kcoff_big_vec; |
4e6f9223 SC |
297 | |
298 | #ifdef SELECT_VECS | |
299 | ||
300 | bfd_target *target_vector[] = { | |
301 | SELECT_VECS, | |
302 | 0 | |
303 | ||
304 | }; | |
305 | #else | |
c0e5039e JG |
306 | #ifdef DEFAULT_VECTOR |
307 | extern bfd_target DEFAULT_VECTOR; | |
308 | #endif | |
309 | ||
7d774e01 | 310 | #ifdef GNU960 |
6f715d66 SC |
311 | #define ICOFF_LITTLE_VEC icoff_little_vec |
312 | #define ICOFF_BIG_VEC icoff_big_vec | |
313 | #define B_OUT_VEC_LITTLE_HOST b_out_vec_little_host | |
314 | #define B_OUT_VEC_BIG_HOST b_out_vec_big_host | |
7d774e01 | 315 | #endif /* GNU960 */ |
9846338e | 316 | |
9872a49c | 317 | #ifndef RESTRICTED |
6f715d66 SC |
318 | #define ECOFF_LITTLE_VEC ecoff_little_vec |
319 | #define ECOFF_BIG_VEC ecoff_big_vec | |
320 | #define ICOFF_LITTLE_VEC icoff_little_vec | |
321 | #define ICOFF_BIG_VEC icoff_big_vec | |
3f85ebce JG |
322 | #define ELF_LITTLE_VEC elf_little_vec |
323 | #define ELF_BIG_VEC elf_big_vec | |
6f715d66 SC |
324 | #define ZB_OUT_VEC_LITTLE_HOST b_out_vec_little_host |
325 | #define ZB_OUT_VEC_BIG_HOST b_out_vec_big_host | |
326 | #define SUNOS_VEC_BIG_HOST sunos_big_vec | |
327 | #define DEMO_64_VEC demo_64_vec | |
328 | #define OASYS_VEC oasys_vec | |
329 | #define IEEE_VEC ieee_vec | |
330 | #define M88K_BCS_VEC m88k_bcs_vec | |
331 | #define SREC_VEC srec_vec | |
332 | #define M68KCOFF_VEC m68kcoff_vec | |
333 | #define I386COFF_VEC i386coff_vec | |
41f50af0 | 334 | #define A29KCOFF_BIG_VEC a29kcoff_big_vec |
9872a49c | 335 | #endif |
4e6f9223 | 336 | |
7d774e01 | 337 | bfd_target *target_vector[] = { |
9846338e | 338 | |
7d774e01 | 339 | #ifdef DEFAULT_VECTOR |
6f715d66 | 340 | &DEFAULT_VECTOR, |
7d774e01 RP |
341 | #endif /* DEFAULT_VECTOR */ |
342 | ||
6f715d66 SC |
343 | #ifdef I386COFF_VEC |
344 | &I386COFF_VEC, | |
345 | #endif /* I386COFF_VEC */ | |
20fdc627 | 346 | |
23b0b558 | 347 | #ifdef ECOFF_LITTLE_VEC |
6f715d66 | 348 | &ECOFF_LITTLE_VEC, |
23b0b558 JG |
349 | #endif |
350 | ||
351 | #ifdef ECOFF_BIG_VEC | |
6f715d66 | 352 | &ECOFF_BIG_VEC, |
23b0b558 | 353 | #endif |
7d774e01 | 354 | #ifdef IEEE_VEC |
6f715d66 | 355 | &IEEE_VEC, |
7d774e01 RP |
356 | #endif /* IEEE_VEC */ |
357 | ||
358 | #ifdef OASYS_VEC | |
6f715d66 | 359 | &OASYS_VEC, |
7d774e01 RP |
360 | #endif /* OASYS_VEC */ |
361 | ||
2b1d8a50 | 362 | #ifdef SUNOS_VEC_BIG_HOST |
6f715d66 | 363 | &SUNOS_VEC_BIG_HOST, |
2b1d8a50 | 364 | #endif /* SUNOS_BIG_VEC */ |
7d774e01 | 365 | |
7ed4093a SC |
366 | |
367 | #ifdef HOST_64_BIT | |
368 | #ifdef DEMO_64_VEC | |
6f715d66 | 369 | &DEMO_64_VEC, |
7ed4093a SC |
370 | #endif |
371 | #endif | |
372 | ||
7d774e01 | 373 | #ifdef M88K_BCS_VEC |
6f715d66 | 374 | &M88K_BCS_VEC, |
7d774e01 RP |
375 | #endif /* M88K_BCS_VEC */ |
376 | ||
377 | #ifdef SREC_VEC | |
6f715d66 | 378 | &SREC_VEC, |
7d774e01 | 379 | #endif /* SREC_VEC */ |
6f715d66 | 380 | |
7d774e01 | 381 | #ifdef ICOFF_LITTLE_VEC |
6f715d66 | 382 | &ICOFF_LITTLE_VEC, |
7d774e01 RP |
383 | #endif /* ICOFF_LITTLE_VEC */ |
384 | ||
385 | #ifdef ICOFF_BIG_VEC | |
6f715d66 | 386 | &ICOFF_BIG_VEC, |
7d774e01 RP |
387 | #endif /* ICOFF_BIG_VEC */ |
388 | ||
3f85ebce JG |
389 | #ifdef ELF_LITTLE_VEC |
390 | &ELF_LITTLE_VEC, | |
391 | #endif /* ELF_LITTLE_VEC */ | |
392 | ||
393 | #ifdef ELF_BIG_VEC | |
394 | &ELF_BIG_VEC, | |
395 | #endif /* ELF_BIG_VEC */ | |
396 | ||
7d774e01 | 397 | #ifdef B_OUT_VEC_LITTLE_HOST |
6f715d66 | 398 | &B_OUT_VEC_LITTLE_HOST, |
7d774e01 | 399 | #endif /* B_OUT_VEC_LITTLE_HOST */ |
9846338e | 400 | |
7d774e01 | 401 | #ifdef B_OUT_VEC_BIG_HOST |
6f715d66 | 402 | &B_OUT_VEC_BIG_HOST, |
7d774e01 | 403 | #endif /* B_OUT_VEC_BIG_HOST */ |
9846338e | 404 | |
6f715d66 SC |
405 | #ifdef M68KCOFF_VEC |
406 | &M68KCOFF_VEC, | |
407 | #endif /* M68KCOFF_VEC */ | |
20fdc627 | 408 | |
41f50af0 SC |
409 | #ifdef A29KCOFF_BIG_VEC |
410 | &A29KCOFF_BIG_VEC, | |
411 | #endif /* A29KCOFF_BIG_VEC */ | |
412 | ||
6f715d66 | 413 | NULL, /* end of list marker */ |
7d774e01 | 414 | }; |
c0e5039e | 415 | |
4e6f9223 | 416 | #endif |
c0e5039e JG |
417 | |
418 | /* default_vector[0] contains either the address of the default vector, | |
419 | if there is one, or zero if there isn't. */ | |
420 | ||
421 | bfd_target *default_vector[] = { | |
422 | #ifdef DEFAULT_VECTOR | |
6f715d66 | 423 | &DEFAULT_VECTOR, |
c0e5039e | 424 | #endif |
6f715d66 | 425 | 0, |
c0e5039e | 426 | }; |
6f715d66 SC |
427 | |
428 | ||
429 | ||
430 | ||
431 | /*proto* | |
432 | *i bfd_find_target | |
433 | Returns a pointer to the transfer vector for the object target | |
434 | named target_name. If target_name is NULL, chooses the one in the | |
435 | environment variable GNUTARGET; if that is null or not defined then | |
436 | the first entry in the target list is chosen. Passing in the | |
437 | string "default" or setting the environment variable to "default" | |
438 | will cause the first entry in the target list to be returned, | |
4e6f9223 SC |
439 | and "target_defaulted" will be set in the BFD. This causes |
440 | @code{bfd_check_format} to loop over all the targets to find the one | |
6f715d66 SC |
441 | that matches the file being read. |
442 | *; PROTO(bfd_target *, bfd_find_target,(CONST char *, bfd *)); | |
443 | *-*/ | |
444 | ||
445 | bfd_target * | |
446 | DEFUN(bfd_find_target,(target_name, abfd), | |
447 | CONST char *target_name AND | |
448 | bfd *abfd) | |
449 | { | |
450 | bfd_target **target; | |
451 | extern char *getenv (); | |
452 | CONST char *targname = (target_name ? target_name : getenv ("GNUTARGET")); | |
453 | ||
454 | /* This is safe; the vector cannot be null */ | |
455 | if (targname == NULL || !strcmp (targname, "default")) { | |
456 | abfd->target_defaulted = true; | |
457 | return abfd->xvec = target_vector[0]; | |
458 | } | |
459 | ||
460 | abfd->target_defaulted = false; | |
461 | ||
462 | for (target = &target_vector[0]; *target != NULL; target++) { | |
463 | if (!strcmp (targname, (*target)->name)) | |
464 | return abfd->xvec = *target; | |
465 | } | |
466 | ||
467 | bfd_error = invalid_target; | |
468 | return NULL; | |
469 | } | |
470 | ||
471 | ||
472 | /*proto* | |
473 | *i bfd_target_list | |
474 | This function returns a freshly malloced NULL-terminated vector of the | |
4e6f9223 | 475 | names of all the valid BFD targets. Do not modify the names |
6f715d66 SC |
476 | *; PROTO(CONST char **,bfd_target_list,()); |
477 | ||
478 | *-*/ | |
479 | ||
480 | CONST char ** | |
481 | DEFUN_VOID(bfd_target_list) | |
482 | { | |
483 | int vec_length= 0; | |
484 | bfd_target **target; | |
4e6f9223 | 485 | CONST char **name_list, **name_ptr; |
6f715d66 SC |
486 | |
487 | for (target = &target_vector[0]; *target != NULL; target++) | |
488 | vec_length++; | |
489 | ||
490 | name_ptr = | |
491 | name_list = (CONST char **) zalloc ((vec_length + 1) * sizeof (char **)); | |
492 | ||
493 | if (name_list == NULL) { | |
494 | bfd_error = no_memory; | |
495 | return NULL; | |
496 | } | |
497 | ||
6f715d66 SC |
498 | for (target = &target_vector[0]; *target != NULL; target++) |
499 | *(name_ptr++) = (*target)->name; | |
500 | ||
501 | return name_list; | |
502 | } |