| 1 | /* Generic target-file-type support for the BFD library. |
| 2 | Copyright (C) 1990-1991 Free Software Foundation, Inc. |
| 3 | Written by Cygnus Support. |
| 4 | |
| 5 | This file is part of BFD, the Binary File Descriptor library. |
| 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
| 20 | |
| 21 | #include "bfd.h" |
| 22 | #include "sysdep.h" |
| 23 | #include "libbfd.h" |
| 24 | |
| 25 | /* |
| 26 | SECTION |
| 27 | Targets |
| 28 | |
| 29 | DESCRIPTION |
| 30 | Each port of BFD to a different machine requries the creation |
| 31 | of a target back end. All the back end provides to the root |
| 32 | part of BFD is a structure containing pointers to functions |
| 33 | which perform certain low level operations on files. BFD |
| 34 | translates the applications's requests through a pointer into |
| 35 | calls to the back end routines. |
| 36 | |
| 37 | When a file is opened with <<bfd_openr>>, its format and |
| 38 | target are unknown. BFD uses various mechanisms to determine |
| 39 | how to interpret the file. The operations performed are: |
| 40 | |
| 41 | o First a BFD is created by calling the internal routine |
| 42 | <<new_bfd>>, then <<bfd_find_target>> is called with the |
| 43 | target string supplied to <<bfd_openr>> and the new BFD pointer. |
| 44 | |
| 45 | o If a null target string was provided to <<bfd_find_target>>, |
| 46 | it looks up the environment variable <<GNUTARGET>> and uses |
| 47 | that as the target string. |
| 48 | |
| 49 | o If the target string is still NULL, or the target string is |
| 50 | <<default>>, then the first item in the target vector is used |
| 51 | as the target type. @xref{bfd_target}. |
| 52 | |
| 53 | o Otherwise, the elements in the target vector are inspected |
| 54 | one by one, until a match on target name is found. When found, |
| 55 | that is used. |
| 56 | |
| 57 | o Otherwise the error <<invalid_target>> is returned to |
| 58 | <<bfd_openr>>. |
| 59 | |
| 60 | o <<bfd_openr>> attempts to open the file using |
| 61 | <<bfd_open_file>>, and returns the BFD. |
| 62 | |
| 63 | Once the BFD has been opened and the target selected, the file |
| 64 | format may be determined. This is done by calling |
| 65 | <<bfd_check_format>> on the BFD with a suggested format. The |
| 66 | routine returns <<true>> when the application guesses right. |
| 67 | @menu |
| 68 | @* bfd_target:: |
| 69 | @end menu |
| 70 | */ |
| 71 | |
| 72 | |
| 73 | /* |
| 74 | |
| 75 | INODE |
| 76 | bfd_target, , Targets, Targets |
| 77 | DOCDD |
| 78 | SUBSECTION |
| 79 | bfd_target |
| 80 | |
| 81 | DESCRIPTION |
| 82 | This structure contains everything that BFD knows about a |
| 83 | target. It includes things like its byte order, name, what |
| 84 | routines to call to do various operations, etc. |
| 85 | |
| 86 | Every BFD points to a target structure with its <<xvec>> |
| 87 | member. |
| 88 | |
| 89 | Shortcut for declaring fields which are prototyped function |
| 90 | pointers, while avoiding anguish on compilers that don't |
| 91 | support protos. |
| 92 | |
| 93 | .#define SDEF(ret, name, arglist) \ |
| 94 | . PROTO(ret,(*name),arglist) |
| 95 | .#define SDEF_FMT(ret, name, arglist) \ |
| 96 | . PROTO(ret,(*name[bfd_type_end]),arglist) |
| 97 | |
| 98 | These macros are used to dispatch to functions through the |
| 99 | bfd_target vector. They are used in a number of macros further |
| 100 | down in @file{bfd.h}, and are also used when calling various |
| 101 | routines by hand inside the BFD implementation. The "arglist" |
| 102 | argument must be parenthesized; it contains all the arguments |
| 103 | to the called function. |
| 104 | |
| 105 | They make the documentation (more) unpleasant to read, so if |
| 106 | someone wants to fix this and not break the above, please do. |
| 107 | |
| 108 | .#define BFD_SEND(bfd, message, arglist) \ |
| 109 | . ((*((bfd)->xvec->message)) arglist) |
| 110 | |
| 111 | For operations which index on the BFD format |
| 112 | |
| 113 | .#define BFD_SEND_FMT(bfd, message, arglist) \ |
| 114 | . (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) |
| 115 | |
| 116 | This is the struct which defines the type of BFD this is. The |
| 117 | <<xvec>> member of the struct <<bfd>> itself points here. Each |
| 118 | module that implements access to a different target under BFD, |
| 119 | defines one of these. |
| 120 | |
| 121 | |
| 122 | FIXME, these names should be rationalised with the names of |
| 123 | the entry points which call them. Too bad we can't have one |
| 124 | macro to define them both! |
| 125 | |
| 126 | .typedef struct bfd_target |
| 127 | .{ |
| 128 | |
| 129 | Identifies the kind of target, eg SunOS4, Ultrix, etc. |
| 130 | |
| 131 | . char *name; |
| 132 | |
| 133 | The "flavour" of a back end is a general indication about the contents |
| 134 | of a file. |
| 135 | |
| 136 | . enum target_flavour { |
| 137 | . bfd_target_unknown_flavour, |
| 138 | . bfd_target_aout_flavour, |
| 139 | . bfd_target_coff_flavour, |
| 140 | . bfd_target_elf_flavour, |
| 141 | . bfd_target_ieee_flavour, |
| 142 | . bfd_target_oasys_flavour, |
| 143 | . bfd_target_tekhex_flavour, |
| 144 | . bfd_target_srec_flavour, |
| 145 | . bfd_target_hppa_flavour} flavour; |
| 146 | |
| 147 | The order of bytes within the data area of a file. |
| 148 | |
| 149 | . boolean byteorder_big_p; |
| 150 | |
| 151 | The order of bytes within the header parts of a file. |
| 152 | |
| 153 | . boolean header_byteorder_big_p; |
| 154 | |
| 155 | This is a mask of all the flags which an executable may have set - |
| 156 | from the set <<NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. |
| 157 | |
| 158 | . flagword object_flags; |
| 159 | |
| 160 | This is a mask of all the flags which a section may have set - from |
| 161 | the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. |
| 162 | |
| 163 | . flagword section_flags; |
| 164 | |
| 165 | The pad character for filenames within an archive header. |
| 166 | |
| 167 | . char ar_pad_char; |
| 168 | |
| 169 | The maximum number of characters in an archive header. |
| 170 | |
| 171 | . unsigned short ar_max_namelen; |
| 172 | |
| 173 | The minimum alignment restriction for any section. |
| 174 | |
| 175 | . unsigned int align_power_min; |
| 176 | |
| 177 | Entries for byte swapping for data. These are different to the other |
| 178 | entry points, since they don't take BFD as first arg. Certain other handlers |
| 179 | could do the same. |
| 180 | |
| 181 | . SDEF (bfd_vma, bfd_getx64, (bfd_byte *)); |
| 182 | . SDEF (void, bfd_putx64, (bfd_vma, bfd_byte *)); |
| 183 | . SDEF (bfd_vma, bfd_getx32, (bfd_byte *)); |
| 184 | . SDEF (void, bfd_putx32, (bfd_vma, bfd_byte *)); |
| 185 | . SDEF (bfd_vma, bfd_getx16, (bfd_byte *)); |
| 186 | . SDEF (void, bfd_putx16, (bfd_vma, bfd_byte *)); |
| 187 | |
| 188 | Byte swapping for the headers |
| 189 | |
| 190 | . SDEF (bfd_vma, bfd_h_getx64, (bfd_byte *)); |
| 191 | . SDEF (void, bfd_h_putx64, (bfd_vma, bfd_byte *)); |
| 192 | . SDEF (bfd_vma, bfd_h_getx32, (bfd_byte *)); |
| 193 | . SDEF (void, bfd_h_putx32, (bfd_vma, bfd_byte *)); |
| 194 | . SDEF (bfd_vma, bfd_h_getx16, (bfd_byte *)); |
| 195 | . SDEF (void, bfd_h_putx16, (bfd_vma, bfd_byte *)); |
| 196 | |
| 197 | Format dependent routines, these turn into vectors of entry points |
| 198 | within the target vector structure; one for each format to check. |
| 199 | |
| 200 | Check the format of a file being read. Return bfd_target * or zero. |
| 201 | |
| 202 | . SDEF_FMT (struct bfd_target *, _bfd_check_format, (bfd *)); |
| 203 | |
| 204 | Set the format of a file being written. |
| 205 | |
| 206 | . SDEF_FMT (boolean, _bfd_set_format, (bfd *)); |
| 207 | |
| 208 | Write cached information into a file being written, at bfd_close. |
| 209 | |
| 210 | . SDEF_FMT (boolean, _bfd_write_contents, (bfd *)); |
| 211 | |
| 212 | The following functions are defined in <<JUMP_TABLE>>. The idea is |
| 213 | that the back end writer of <<foo>> names all the routines |
| 214 | <<foo_>>@var{entry_point}, <<JUMP_TABLE>> will built the entries |
| 215 | in this structure in the right order. |
| 216 | |
| 217 | Core file entry points |
| 218 | |
| 219 | . SDEF (char *, _core_file_failing_command, (bfd *)); |
| 220 | . SDEF (int, _core_file_failing_signal, (bfd *)); |
| 221 | . SDEF (boolean, _core_file_matches_executable_p, (bfd *, bfd *)); |
| 222 | |
| 223 | Archive entry points |
| 224 | |
| 225 | . SDEF (boolean, _bfd_slurp_armap, (bfd *)); |
| 226 | . SDEF (boolean, _bfd_slurp_extended_name_table, (bfd *)); |
| 227 | . SDEF (void, _bfd_truncate_arname, (bfd *, CONST char *, char *)); |
| 228 | . SDEF (boolean, write_armap, (bfd *arch, |
| 229 | . unsigned int elength, |
| 230 | . struct orl *map, |
| 231 | . unsigned int orl_count, |
| 232 | . int stridx)); |
| 233 | |
| 234 | Standard stuff. |
| 235 | |
| 236 | . SDEF (boolean, _close_and_cleanup, (bfd *)); |
| 237 | . SDEF (boolean, _bfd_set_section_contents, (bfd *, sec_ptr, PTR, |
| 238 | . file_ptr, bfd_size_type)); |
| 239 | . SDEF (boolean, _bfd_get_section_contents, (bfd *, sec_ptr, PTR, |
| 240 | . file_ptr, bfd_size_type)); |
| 241 | . SDEF (boolean, _new_section_hook, (bfd *, sec_ptr)); |
| 242 | |
| 243 | Symbols and relocations |
| 244 | |
| 245 | . SDEF (unsigned int, _get_symtab_upper_bound, (bfd *)); |
| 246 | . SDEF (unsigned int, _bfd_canonicalize_symtab, |
| 247 | . (bfd *, struct symbol_cache_entry **)); |
| 248 | . SDEF (unsigned int, _get_reloc_upper_bound, (bfd *, sec_ptr)); |
| 249 | . SDEF (unsigned int, _bfd_canonicalize_reloc, (bfd *, sec_ptr, arelent **, |
| 250 | . struct symbol_cache_entry**)); |
| 251 | . SDEF (struct symbol_cache_entry *, _bfd_make_empty_symbol, (bfd *)); |
| 252 | . SDEF (void, _bfd_print_symbol, (bfd *, PTR, struct symbol_cache_entry *, |
| 253 | . bfd_print_symbol_type)); |
| 254 | .#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e)) |
| 255 | . SDEF (alent *, _get_lineno, (bfd *, struct symbol_cache_entry *)); |
| 256 | . |
| 257 | . SDEF (boolean, _bfd_set_arch_mach, (bfd *, enum bfd_architecture, |
| 258 | . unsigned long)); |
| 259 | . |
| 260 | . SDEF (bfd *, openr_next_archived_file, (bfd *arch, bfd *prev)); |
| 261 | . SDEF (boolean, _bfd_find_nearest_line, |
| 262 | . (bfd *abfd, struct sec *section, |
| 263 | . struct symbol_cache_entry **symbols,bfd_vma offset, |
| 264 | . CONST char **file, CONST char **func, unsigned int *line)); |
| 265 | . SDEF (int, _bfd_stat_arch_elt, (bfd *, struct stat *)); |
| 266 | . |
| 267 | . SDEF (int, _bfd_sizeof_headers, (bfd *, boolean)); |
| 268 | . |
| 269 | . SDEF (void, _bfd_debug_info_start, (bfd *)); |
| 270 | . SDEF (void, _bfd_debug_info_end, (bfd *)); |
| 271 | . SDEF (void, _bfd_debug_info_accumulate, (bfd *, struct sec *)); |
| 272 | . SDEF (bfd_byte *, _bfd_get_relocated_section_contents, (bfd*,struct bfd_seclet_struct *, bfd_byte *data)); |
| 273 | . SDEF (boolean,_bfd_relax_section,(bfd *, struct sec *, struct symbol_cache_entry **)); |
| 274 | Special entry points for gdb to swap in coff symbol table parts |
| 275 | |
| 276 | . SDEF(void, _bfd_coff_swap_aux_in,( |
| 277 | . bfd *abfd , |
| 278 | . PTR ext, |
| 279 | . int type, |
| 280 | . int class , |
| 281 | . PTR in)); |
| 282 | . |
| 283 | . SDEF(void, _bfd_coff_swap_sym_in,( |
| 284 | . bfd *abfd , |
| 285 | . PTR ext, |
| 286 | . PTR in)); |
| 287 | . |
| 288 | . SDEF(void, _bfd_coff_swap_lineno_in, ( |
| 289 | . bfd *abfd, |
| 290 | . PTR ext, |
| 291 | . PTR in)); |
| 292 | . |
| 293 | |
| 294 | Special entry points for gas to swap coff parts |
| 295 | |
| 296 | . SDEF(unsigned int, _bfd_coff_swap_aux_out,( |
| 297 | . bfd *abfd, |
| 298 | . PTR in, |
| 299 | . int type, |
| 300 | . int class, |
| 301 | . PTR ext)); |
| 302 | . |
| 303 | . SDEF(unsigned int, _bfd_coff_swap_sym_out,( |
| 304 | . bfd *abfd, |
| 305 | . PTR in, |
| 306 | . PTR ext)); |
| 307 | . |
| 308 | . SDEF(unsigned int, _bfd_coff_swap_lineno_out,( |
| 309 | . bfd *abfd, |
| 310 | . PTR in, |
| 311 | . PTR ext)); |
| 312 | . |
| 313 | . SDEF(unsigned int, _bfd_coff_swap_reloc_out,( |
| 314 | . bfd *abfd, |
| 315 | . PTR src, |
| 316 | . PTR dst)); |
| 317 | . |
| 318 | . SDEF(unsigned int, _bfd_coff_swap_filehdr_out,( |
| 319 | . bfd *abfd, |
| 320 | . PTR in, |
| 321 | . PTR out)); |
| 322 | . |
| 323 | . SDEF(unsigned int, _bfd_coff_swap_aouthdr_out,( |
| 324 | . bfd *abfd, |
| 325 | . PTR in, |
| 326 | . PTR out)); |
| 327 | . |
| 328 | . SDEF(unsigned int, _bfd_coff_swap_scnhdr_out,( |
| 329 | . bfd *abfd, |
| 330 | . PTR in, |
| 331 | . PTR out)); |
| 332 | . |
| 333 | . {* See documentation on reloc types. *} |
| 334 | . SDEF (CONST struct reloc_howto_struct *, |
| 335 | . reloc_type_lookup, |
| 336 | . (bfd *abfd, bfd_reloc_code_real_type code)); |
| 337 | . |
| 338 | . {* Complete and utter crock, currently used for the assembler |
| 339 | . when creating COFF files. *} |
| 340 | . SDEF (asymbol *, _bfd_make_debug_symbol, ( |
| 341 | . bfd *abfd, |
| 342 | . void *ptr, |
| 343 | . unsigned long size)); |
| 344 | |
| 345 | Data for use by back-end routines; e.g., for a.out, includes whether |
| 346 | this particular target maps ZMAGIC files contiguously or with text and |
| 347 | data separated. Could perhaps also be used to eliminate some of the |
| 348 | above COFF-specific fields. |
| 349 | |
| 350 | . PTR backend_data; |
| 351 | .} bfd_target; |
| 352 | |
| 353 | */ |
| 354 | |
| 355 | /* The default is to define a target_vector containing all the targets. |
| 356 | By setting MINIMIZE=1 on the "make" command line, the user can change this |
| 357 | to a vector containing just DEFAULT_VECTOR and any required |
| 358 | traditional-core-file handler. (This is to save space in the executables.) |
| 359 | The config files can also override the default large vector by giving an |
| 360 | explicit SELECT_VECS macro. */ |
| 361 | |
| 362 | #if MINIMIZE && defined(DEFAULT_VECTOR) && !defined(SELECT_VECS) |
| 363 | #ifdef TRAD_CORE |
| 364 | #define SELECT_VECS &DEFAULT_VECTOR,&trad_core_vec |
| 365 | #else |
| 366 | #define SELECT_VECS &DEFAULT_VECTOR |
| 367 | #endif |
| 368 | #endif |
| 369 | |
| 370 | /* All known xvecs. They are listed a second time below, since |
| 371 | we can't intermix extern's and initializers. */ |
| 372 | extern bfd_target ecoff_little_vec; |
| 373 | extern bfd_target ecoff_big_vec; |
| 374 | extern bfd_target sunos_big_vec; |
| 375 | extern bfd_target demo_64_vec; |
| 376 | extern bfd_target srec_vec; |
| 377 | extern bfd_target tekhex_vec; |
| 378 | extern bfd_target b_out_vec_little_host; |
| 379 | extern bfd_target b_out_vec_big_host; |
| 380 | extern bfd_target icoff_little_vec; |
| 381 | extern bfd_target icoff_big_vec; |
| 382 | extern bfd_target elf_little_vec; |
| 383 | extern bfd_target elf_big_vec; |
| 384 | extern bfd_target ieee_vec; |
| 385 | extern bfd_target oasys_vec; |
| 386 | extern bfd_target m88kbcs_vec; |
| 387 | extern bfd_target m68kcoff_vec; |
| 388 | extern bfd_target i386coff_vec; |
| 389 | extern bfd_target i386aout_vec; |
| 390 | extern bfd_target i386linux_vec; |
| 391 | extern bfd_target a29kcoff_big_vec; |
| 392 | extern bfd_target trad_core_vec; |
| 393 | extern bfd_target rs6000coff_vec; |
| 394 | extern bfd_target h8300coff_vec; |
| 395 | extern bfd_target z8kcoff_vec; |
| 396 | extern bfd_target we32kcoff_vec; |
| 397 | #ifdef hp9000s800 |
| 398 | extern bfd_target hppa_vec; |
| 399 | #endif |
| 400 | |
| 401 | #ifdef DEFAULT_VECTOR |
| 402 | extern bfd_target DEFAULT_VECTOR; |
| 403 | #endif |
| 404 | |
| 405 | #ifdef SELECT_VECS |
| 406 | |
| 407 | bfd_target *target_vector[] = { |
| 408 | SELECT_VECS, |
| 409 | 0 |
| 410 | }; |
| 411 | |
| 412 | #else |
| 413 | |
| 414 | bfd_target *target_vector[] = { |
| 415 | |
| 416 | #ifdef DEFAULT_VECTOR |
| 417 | &DEFAULT_VECTOR, |
| 418 | #endif |
| 419 | |
| 420 | &i386coff_vec, |
| 421 | &i386aout_vec, |
| 422 | &ecoff_little_vec, |
| 423 | &ecoff_big_vec, |
| 424 | &ieee_vec, |
| 425 | #if 1 |
| 426 | /* We have no oasys tools anymore, so we can't test any of this |
| 427 | anymore. If you want to test the stuff yourself, go ahead... |
| 428 | steve@cygnus.com */ |
| 429 | &oasys_vec, |
| 430 | #endif |
| 431 | &sunos_big_vec, |
| 432 | #ifdef HOST_64_BIT |
| 433 | &demo_64_vec, /* Only compiled if host has long-long support */ |
| 434 | #endif |
| 435 | &h8300coff_vec, |
| 436 | &z8kcoff_vec, |
| 437 | &m88kbcs_vec, |
| 438 | &srec_vec, |
| 439 | /* &tekhex_vec,*/ |
| 440 | &icoff_little_vec, |
| 441 | &icoff_big_vec, |
| 442 | &elf_little_vec, |
| 443 | &elf_big_vec, |
| 444 | &b_out_vec_little_host, |
| 445 | &b_out_vec_big_host, |
| 446 | &m68kcoff_vec, |
| 447 | &a29kcoff_big_vec, |
| 448 | &rs6000coff_vec, |
| 449 | #ifdef hp9000s800 |
| 450 | &hppa_vec, |
| 451 | #endif |
| 452 | &we32kcoff_vec, |
| 453 | |
| 454 | #ifdef TRAD_CORE |
| 455 | &trad_core_vec, |
| 456 | #endif |
| 457 | NULL, /* end of list marker */ |
| 458 | }; |
| 459 | |
| 460 | #endif |
| 461 | |
| 462 | /* default_vector[0] contains either the address of the default vector, |
| 463 | if there is one, or zero if there isn't. */ |
| 464 | |
| 465 | bfd_target *default_vector[] = { |
| 466 | #ifdef DEFAULT_VECTOR |
| 467 | &DEFAULT_VECTOR, |
| 468 | #endif |
| 469 | 0, |
| 470 | }; |
| 471 | |
| 472 | |
| 473 | |
| 474 | |
| 475 | /* |
| 476 | FUNCTION |
| 477 | bfd_find_target |
| 478 | |
| 479 | DESCRIPTION |
| 480 | Returns a pointer to the transfer vector for the object target |
| 481 | named target_name. If target_name is NULL, chooses the one in |
| 482 | the environment variable GNUTARGET; if that is null or not |
| 483 | defined thenthe first entry in the target list is chosen. |
| 484 | Passing in the string "default" or setting the environment |
| 485 | variable to "default" will cause the first entry in the target |
| 486 | list to be returned, and "target_defaulted" will be set in the |
| 487 | BFD. This causes <<bfd_check_format>> to loop over all the |
| 488 | targets to find the one that matches the file being read. |
| 489 | |
| 490 | SYNOPSIS |
| 491 | bfd_target *bfd_find_target(CONST char *, bfd *); |
| 492 | */ |
| 493 | |
| 494 | bfd_target * |
| 495 | DEFUN(bfd_find_target,(target_name, abfd), |
| 496 | CONST char *target_name AND |
| 497 | bfd *abfd) |
| 498 | { |
| 499 | bfd_target **target; |
| 500 | extern char *getenv (); |
| 501 | CONST char *targname = (target_name ? target_name : |
| 502 | (CONST char *) getenv ("GNUTARGET")); |
| 503 | |
| 504 | /* This is safe; the vector cannot be null */ |
| 505 | if (targname == NULL || !strcmp (targname, "default")) { |
| 506 | abfd->target_defaulted = true; |
| 507 | return abfd->xvec = target_vector[0]; |
| 508 | } |
| 509 | |
| 510 | abfd->target_defaulted = false; |
| 511 | |
| 512 | for (target = &target_vector[0]; *target != NULL; target++) { |
| 513 | if (!strcmp (targname, (*target)->name)) |
| 514 | return abfd->xvec = *target; |
| 515 | } |
| 516 | |
| 517 | bfd_error = invalid_target; |
| 518 | return NULL; |
| 519 | } |
| 520 | |
| 521 | |
| 522 | /* |
| 523 | FUNCTION |
| 524 | bfd_target_list |
| 525 | |
| 526 | DESCRIPTION |
| 527 | This function returns a freshly malloced NULL-terminated |
| 528 | vector of the names of all the valid BFD targets. Do not |
| 529 | modify the names |
| 530 | |
| 531 | SYNOPSIS |
| 532 | CONST char **bfd_target_list(void); |
| 533 | |
| 534 | */ |
| 535 | |
| 536 | CONST char ** |
| 537 | DEFUN_VOID(bfd_target_list) |
| 538 | { |
| 539 | int vec_length= 0; |
| 540 | bfd_target **target; |
| 541 | CONST char **name_list, **name_ptr; |
| 542 | |
| 543 | for (target = &target_vector[0]; *target != NULL; target++) |
| 544 | vec_length++; |
| 545 | |
| 546 | name_ptr = |
| 547 | name_list = (CONST char **) zalloc ((vec_length + 1) * sizeof (char **)); |
| 548 | |
| 549 | if (name_list == NULL) { |
| 550 | bfd_error = no_memory; |
| 551 | return NULL; |
| 552 | } |
| 553 | |
| 554 | for (target = &target_vector[0]; *target != NULL; target++) |
| 555 | *(name_ptr++) = (*target)->name; |
| 556 | |
| 557 | return name_list; |
| 558 | } |