format.c revision 107492
1102729Sobrien/* Generic BFD support for file formats. 2102729Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002 3218822Sdim Free Software Foundation, Inc. 4102729Sobrien Written by Cygnus Support. 5218822Sdim 6102729SobrienThis file is part of BFD, the Binary File Descriptor library. 7102729Sobrien 8102729SobrienThis program is free software; you can redistribute it and/or modify 9102729Sobrienit under the terms of the GNU General Public License as published by 10102729Sobrienthe Free Software Foundation; either version 2 of the License, or 11102729Sobrien(at your option) any later version. 12102729Sobrien 13102729SobrienThis program is distributed in the hope that it will be useful, 14102729Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 15102729SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16102729SobrienGNU General Public License for more details. 17102729Sobrien 18102729SobrienYou should have received a copy of the GNU General Public License 19218822Sdimalong with this program; if not, write to the Free Software 20102729SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 21102729Sobrien 22102729Sobrien/* 23102729SobrienSECTION 24102729Sobrien File formats 25102729Sobrien 26102729Sobrien A format is a BFD concept of high level file contents type. The 27102729Sobrien formats supported by BFD are: 28102729Sobrien 29218822Sdim o <<bfd_object>> 30218822Sdim 31102729Sobrien The BFD may contain data, symbols, relocations and debug info. 32102729Sobrien 33102729Sobrien o <<bfd_archive>> 34102729Sobrien 35102729Sobrien The BFD contains other BFDs and an optional index. 36102729Sobrien 37102729Sobrien o <<bfd_core>> 38102729Sobrien 39102729Sobrien The BFD contains the result of an executable core dump. 40102729Sobrien 41102729Sobrien*/ 42102729Sobrien 43102729Sobrien#include "bfd.h" 44102729Sobrien#include "sysdep.h" 45102729Sobrien#include "libbfd.h" 46102729Sobrien 47102729Sobrien/* IMPORT from targets.c. */ 48102729Sobrienextern const size_t _bfd_target_vector_entries; 49102729Sobrien 50102729Sobrien/* 51102729SobrienFUNCTION 52102729Sobrien bfd_check_format 53102729Sobrien 54102729SobrienSYNOPSIS 55102729Sobrien boolean bfd_check_format(bfd *abfd, bfd_format format); 56102729Sobrien 57102729SobrienDESCRIPTION 58102729Sobrien Verify if the file attached to the BFD @var{abfd} is compatible 59102729Sobrien with the format @var{format} (i.e., one of <<bfd_object>>, 60102729Sobrien <<bfd_archive>> or <<bfd_core>>). 61102729Sobrien 62102729Sobrien If the BFD has been set to a specific target before the 63102729Sobrien call, only the named target and format combination is 64102729Sobrien checked. If the target has not been set, or has been set to 65102729Sobrien <<default>>, then all the known target backends is 66102729Sobrien interrogated to determine a match. If the default target 67102729Sobrien matches, it is used. If not, exactly one target must recognize 68102729Sobrien the file, or an error results. 69102729Sobrien 70102729Sobrien The function returns <<true>> on success, otherwise <<false>> 71102729Sobrien with one of the following error codes: 72102729Sobrien 73102729Sobrien o <<bfd_error_invalid_operation>> - 74102729Sobrien if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or 75102729Sobrien <<bfd_core>>. 76218822Sdim 77218822Sdim o <<bfd_error_system_call>> - 78102729Sobrien if an error occured during a read - even some file mismatches 79102729Sobrien can cause bfd_error_system_calls. 80102729Sobrien 81102729Sobrien o <<file_not_recognised>> - 82102729Sobrien none of the backends recognised the file format. 83102729Sobrien 84102729Sobrien o <<bfd_error_file_ambiguously_recognized>> - 85102729Sobrien more than one backend recognised the file format. 86102729Sobrien*/ 87102729Sobrien 88102729Sobrienboolean 89102729Sobrienbfd_check_format (abfd, format) 90102729Sobrien bfd *abfd; 91102729Sobrien bfd_format format; 92102729Sobrien{ 93102729Sobrien return bfd_check_format_matches (abfd, format, NULL); 94102729Sobrien} 95102729Sobrien 96102729Sobrien/* 97102729SobrienFUNCTION 98102729Sobrien bfd_check_format_matches 99102729Sobrien 100102729SobrienSYNOPSIS 101102729Sobrien boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); 102102729Sobrien 103102729SobrienDESCRIPTION 104102729Sobrien Like <<bfd_check_format>>, except when it returns false with 105102729Sobrien <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. In that 106102729Sobrien case, if @var{matching} is not NULL, it will be filled in with 107102729Sobrien a NULL-terminated list of the names of the formats that matched, 108102729Sobrien allocated with <<malloc>>. 109102729Sobrien Then the user may choose a format and try again. 110102729Sobrien 111102729Sobrien When done with the list that @var{matching} points to, the caller 112102729Sobrien should free it. 113102729Sobrien*/ 114218822Sdim 115102729Sobrienboolean 116102729Sobrienbfd_check_format_matches (abfd, format, matching) 117102729Sobrien bfd *abfd; 118102729Sobrien bfd_format format; 119218822Sdim char ***matching; 120102729Sobrien{ 121218822Sdim extern const bfd_target binary_vec; 122102729Sobrien const bfd_target * const *target, *save_targ, *right_targ, *ar_right_targ; 123102729Sobrien char **matching_vector = NULL; 124102729Sobrien int match_count; 125102729Sobrien int ar_match_index; 126102729Sobrien 127102729Sobrien if (!bfd_read_p (abfd) 128102729Sobrien || (unsigned int) abfd->format >= (unsigned int) bfd_type_end) 129102729Sobrien { 130102729Sobrien bfd_set_error (bfd_error_invalid_operation); 131218822Sdim return false; 132102729Sobrien } 133102729Sobrien 134102729Sobrien if (abfd->format != bfd_unknown) 135102729Sobrien return (boolean) (abfd->format == format); 136102729Sobrien 137102729Sobrien /* Since the target type was defaulted, check them 138102729Sobrien all in the hope that one will be uniquely recognized. */ 139102729Sobrien save_targ = abfd->xvec; 140102729Sobrien match_count = 0; 141102729Sobrien ar_match_index = _bfd_target_vector_entries; 142102729Sobrien 143102729Sobrien if (matching) 144102729Sobrien { 145102729Sobrien bfd_size_type amt; 146102729Sobrien 147102729Sobrien *matching = NULL; 148102729Sobrien amt = sizeof (char *) * 2 * _bfd_target_vector_entries; 149102729Sobrien matching_vector = (char **) bfd_malloc (amt); 150102729Sobrien if (!matching_vector) 151102729Sobrien return false; 152102729Sobrien } 153102729Sobrien 154102729Sobrien right_targ = 0; 155102729Sobrien ar_right_targ = 0; 156102729Sobrien 157102729Sobrien /* Presume the answer is yes. */ 158102729Sobrien abfd->format = format; 159102729Sobrien 160102729Sobrien /* If the target type was explicitly specified, just check that target. */ 161218822Sdim if (!abfd->target_defaulted) 162102729Sobrien { 163218822Sdim if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */ 164102729Sobrien return false; 165102729Sobrien 166218822Sdim right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); 167102729Sobrien 168102729Sobrien if (right_targ) 169102729Sobrien { 170102729Sobrien abfd->xvec = right_targ; /* Set the target as returned. */ 171102729Sobrien 172102729Sobrien if (matching) 173102729Sobrien free (matching_vector); 174102729Sobrien 175102729Sobrien return true; /* File position has moved, BTW. */ 176102729Sobrien } 177102729Sobrien 178102729Sobrien /* For a long time the code has dropped through to check all 179218822Sdim targets if the specified target was wrong. I don't know why, 180218822Sdim and I'm reluctant to change it. However, in the case of an 181218822Sdim archive, it can cause problems. If the specified target does 182218822Sdim not permit archives (e.g., the binary target), then we should 183102729Sobrien not allow some other target to recognize it as an archive, but 184218822Sdim should instead allow the specified target to recognize it as an 185102729Sobrien object. When I first made this change, it broke the PE target, 186102729Sobrien because the specified pei-i386 target did not recognize the 187102729Sobrien actual pe-i386 archive. Since there may be other problems of 188102729Sobrien this sort, I changed this test to check only for the binary 189102729Sobrien target. */ 190218822Sdim if (format == bfd_archive && save_targ == &binary_vec) 191102729Sobrien { 192102729Sobrien abfd->xvec = save_targ; 193102729Sobrien abfd->format = bfd_unknown; 194102729Sobrien 195102729Sobrien if (matching) 196102729Sobrien free (matching_vector); 197102729Sobrien 198102729Sobrien bfd_set_error (bfd_error_file_not_recognized); 199102729Sobrien 200102729Sobrien return false; 201102729Sobrien } 202102729Sobrien } 203102729Sobrien 204102729Sobrien for (target = bfd_target_vector; *target != NULL; target++) 205102729Sobrien { 206102729Sobrien const bfd_target *temp; 207102729Sobrien bfd_error_type err; 208102729Sobrien 209102729Sobrien if (*target == &binary_vec) 210102729Sobrien continue; 211102729Sobrien 212102729Sobrien abfd->xvec = *target; /* Change BFD's target temporarily */ 213102729Sobrien 214102729Sobrien if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 215102729Sobrien return false; 216102729Sobrien 217102729Sobrien /* If _bfd_check_format neglects to set bfd_error, assume 218102729Sobrien bfd_error_wrong_format. We didn't used to even pay any 219102729Sobrien attention to bfd_error, so I suspect that some 220102729Sobrien _bfd_check_format might have this problem. */ 221102729Sobrien bfd_set_error (bfd_error_wrong_format); 222102729Sobrien 223102729Sobrien temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); 224102729Sobrien 225102729Sobrien if (temp) 226102729Sobrien { /* This format checks out as ok! */ 227102729Sobrien right_targ = temp; 228102729Sobrien 229102729Sobrien /* If this is the default target, accept it, even if other 230102729Sobrien targets might match. People who want those other targets 231102729Sobrien have to set the GNUTARGET variable. */ 232102729Sobrien if (temp == bfd_default_vector[0]) 233102729Sobrien { 234102729Sobrien match_count = 1; 235102729Sobrien break; 236102729Sobrien } 237102729Sobrien 238102729Sobrien if (matching) 239102729Sobrien matching_vector[match_count] = temp->name; 240102729Sobrien 241102729Sobrien match_count++; 242102729Sobrien 243102729Sobrien#ifdef GNU960 244102729Sobrien /* Big- and little-endian b.out archives look the same, but it 245102729Sobrien doesn't matter: there is no difference in their headers, and 246102729Sobrien member file byte orders will (I hope) be handled appropriately 247102729Sobrien by bfd. Ditto for big and little coff archives. And the 4 248102729Sobrien coff/b.out object formats are unambiguous. So accept the 249102729Sobrien first match we find. */ 250102729Sobrien break; 251102729Sobrien#endif 252102729Sobrien } 253102729Sobrien else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format 254102729Sobrien || err == bfd_error_file_ambiguously_recognized) 255102729Sobrien { 256102729Sobrien /* An archive with objects of the wrong type, or an 257 ambiguous match. We want this target to match if we get 258 no better matches. */ 259 if (ar_right_targ != bfd_default_vector[0]) 260 ar_right_targ = *target; 261 if (matching) 262 matching_vector[ar_match_index] = (*target)->name; 263 ar_match_index++; 264 } 265 else if (err != bfd_error_wrong_format) 266 { 267 abfd->xvec = save_targ; 268 abfd->format = bfd_unknown; 269 270 if (matching) 271 free (matching_vector); 272 273 return false; 274 } 275 } 276 277 if (match_count == 0) 278 { 279 /* Try partial matches. */ 280 right_targ = ar_right_targ; 281 if (right_targ == bfd_default_vector[0]) 282 { 283 match_count = 1; 284 } 285 else 286 { 287 match_count = ar_match_index - _bfd_target_vector_entries; 288 if (matching && match_count > 1) 289 { 290 memcpy (matching_vector, 291 matching_vector + _bfd_target_vector_entries, 292 sizeof (char *) * match_count); 293 } 294 } 295 } 296 297 if (match_count == 1) 298 { 299 abfd->xvec = right_targ; /* Change BFD's target permanently. */ 300 301 if (matching) 302 free (matching_vector); 303 304 return true; /* File position has moved, BTW. */ 305 } 306 307 abfd->xvec = save_targ; /* Restore original target type. */ 308 abfd->format = bfd_unknown; /* Restore original format. */ 309 310 if (match_count == 0) 311 { 312 bfd_set_error (bfd_error_file_not_recognized); 313 314 if (matching) 315 free (matching_vector); 316 } 317 else 318 { 319 bfd_set_error (bfd_error_file_ambiguously_recognized); 320 321 if (matching) 322 { 323 *matching = matching_vector; 324 matching_vector[match_count] = NULL; 325 } 326 } 327 328 return false; 329} 330 331/* 332FUNCTION 333 bfd_set_format 334 335SYNOPSIS 336 boolean bfd_set_format(bfd *abfd, bfd_format format); 337 338DESCRIPTION 339 This function sets the file format of the BFD @var{abfd} to the 340 format @var{format}. If the target set in the BFD does not 341 support the format requested, the format is invalid, or the BFD 342 is not open for writing, then an error occurs. 343*/ 344 345boolean 346bfd_set_format (abfd, format) 347 bfd *abfd; 348 bfd_format format; 349{ 350 if (bfd_read_p (abfd) 351 || (unsigned int) abfd->format >= (unsigned int) bfd_type_end) 352 { 353 bfd_set_error (bfd_error_invalid_operation); 354 return false; 355 } 356 357 if (abfd->format != bfd_unknown) 358 return (boolean) (abfd->format == format); 359 360 /* Presume the answer is yes. */ 361 abfd->format = format; 362 363 if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) 364 { 365 abfd->format = bfd_unknown; 366 return false; 367 } 368 369 return true; 370} 371 372/* 373FUNCTION 374 bfd_format_string 375 376SYNOPSIS 377 const char *bfd_format_string(bfd_format format); 378 379DESCRIPTION 380 Return a pointer to a const string 381 <<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>, 382 depending upon the value of @var{format}. 383*/ 384 385const char * 386bfd_format_string (format) 387 bfd_format format; 388{ 389 if (((int)format <(int) bfd_unknown) 390 || ((int)format >=(int) bfd_type_end)) 391 return "invalid"; 392 393 switch (format) 394 { 395 case bfd_object: 396 return "object"; /* Linker/assember/compiler output. */ 397 case bfd_archive: 398 return "archive"; /* Object archive file. */ 399 case bfd_core: 400 return "core"; /* Core dump. */ 401 default: 402 return "unknown"; 403 } 404} 405