OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [bfd/] [format.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Generic BFD support for file formats.
2
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002
3
   Free Software Foundation, Inc.
4
   Written by Cygnus Support.
5
 
6
This file is part of BFD, the Binary File Descriptor library.
7
 
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
 
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
 
22
/*
23
SECTION
24
        File formats
25
 
26
        A format is a BFD concept of high level file contents type. The
27
        formats supported by BFD are:
28
 
29
        o <<bfd_object>>
30
 
31
        The BFD may contain data, symbols, relocations and debug info.
32
 
33
        o <<bfd_archive>>
34
 
35
        The BFD contains other BFDs and an optional index.
36
 
37
        o <<bfd_core>>
38
 
39
        The BFD contains the result of an executable core dump.
40
 
41
*/
42
 
43
#include "bfd.h"
44
#include "sysdep.h"
45
#include "libbfd.h"
46
 
47
/* IMPORT from targets.c.  */
48
extern const size_t _bfd_target_vector_entries;
49
 
50
/*
51
FUNCTION
52
        bfd_check_format
53
 
54
SYNOPSIS
55
        boolean bfd_check_format(bfd *abfd, bfd_format format);
56
 
57
DESCRIPTION
58
        Verify if the file attached to the BFD @var{abfd} is compatible
59
        with the format @var{format} (i.e., one of <<bfd_object>>,
60
        <<bfd_archive>> or <<bfd_core>>).
61
 
62
        If the BFD has been set to a specific target before the
63
        call, only the named target and format combination is
64
        checked. If the target has not been set, or has been set to
65
        <<default>>, then all the known target backends is
66
        interrogated to determine a match.  If the default target
67
        matches, it is used.  If not, exactly one target must recognize
68
        the file, or an error results.
69
 
70
        The function returns <<true>> on success, otherwise <<false>>
71
        with one of the following error codes:
72
 
73
        o <<bfd_error_invalid_operation>> -
74
        if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
75
        <<bfd_core>>.
76
 
77
        o <<bfd_error_system_call>> -
78
        if an error occured during a read - even some file mismatches
79
        can cause bfd_error_system_calls.
80
 
81
        o <<file_not_recognised>> -
82
        none of the backends recognised the file format.
83
 
84
        o <<bfd_error_file_ambiguously_recognized>> -
85
        more than one backend recognised the file format.
86
*/
87
 
88
boolean
89
bfd_check_format (abfd, format)
90
     bfd *abfd;
91
     bfd_format format;
92
{
93
  return bfd_check_format_matches (abfd, format, NULL);
94
}
95
 
96
/*
97
FUNCTION
98
        bfd_check_format_matches
99
 
100
SYNOPSIS
101
        boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching);
102
 
103
DESCRIPTION
104
        Like <<bfd_check_format>>, except when it returns false with
105
        <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
106
        case, if @var{matching} is not NULL, it will be filled in with
107
        a NULL-terminated list of the names of the formats that matched,
108
        allocated with <<malloc>>.
109
        Then the user may choose a format and try again.
110
 
111
        When done with the list that @var{matching} points to, the caller
112
        should free it.
113
*/
114
 
115
boolean
116
bfd_check_format_matches (abfd, format, matching)
117
     bfd *abfd;
118
     bfd_format format;
119
     char ***matching;
120
{
121
  extern const bfd_target binary_vec;
122
  const bfd_target * const *target, *save_targ, *right_targ, *ar_right_targ;
123
  char **matching_vector = NULL;
124
  int match_count;
125
  int ar_match_index;
126
 
127
  if (!bfd_read_p (abfd)
128
      || (unsigned int) abfd->format >= (unsigned int) bfd_type_end)
129
    {
130
      bfd_set_error (bfd_error_invalid_operation);
131
      return false;
132
    }
133
 
134
  if (abfd->format != bfd_unknown)
135
    return abfd->format == format;
136
 
137
  /* Since the target type was defaulted, check them
138
     all in the hope that one will be uniquely recognized.  */
139
  save_targ = abfd->xvec;
140
  match_count = 0;
141
  ar_match_index = _bfd_target_vector_entries;
142
 
143
  if (matching)
144
    {
145
      bfd_size_type amt;
146
 
147
      *matching = NULL;
148
      amt = sizeof (char *) * 2 * _bfd_target_vector_entries;
149
      matching_vector = (char **) bfd_malloc (amt);
150
      if (!matching_vector)
151
        return false;
152
    }
153
 
154
  right_targ = 0;
155
  ar_right_targ = 0;
156
 
157
  /* Presume the answer is yes.  */
158
  abfd->format = format;
159
 
160
  /* If the target type was explicitly specified, just check that target.  */
161
  if (!abfd->target_defaulted)
162
    {
163
      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)   /* rewind! */
164
        return false;
165
 
166
      right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
167
 
168
      if (right_targ)
169
        {
170
          abfd->xvec = right_targ;      /* Set the target as returned.  */
171
 
172
          if (matching)
173
            free (matching_vector);
174
 
175
          return true;                  /* File position has moved, BTW.  */
176
        }
177
 
178
      /* For a long time the code has dropped through to check all
179
         targets if the specified target was wrong.  I don't know why,
180
         and I'm reluctant to change it.  However, in the case of an
181
         archive, it can cause problems.  If the specified target does
182
         not permit archives (e.g., the binary target), then we should
183
         not allow some other target to recognize it as an archive, but
184
         should instead allow the specified target to recognize it as an
185
         object.  When I first made this change, it broke the PE target,
186
         because the specified pei-i386 target did not recognize the
187
         actual pe-i386 archive.  Since there may be other problems of
188
         this sort, I changed this test to check only for the binary
189
         target.  */
190
      if (format == bfd_archive && save_targ == &binary_vec)
191
        {
192
          abfd->xvec = save_targ;
193
          abfd->format = bfd_unknown;
194
 
195
          if (matching)
196
            free (matching_vector);
197
 
198
          bfd_set_error (bfd_error_file_not_recognized);
199
 
200
          return false;
201
        }
202
    }
203
 
204
  for (target = bfd_target_vector; *target != NULL; target++)
205
    {
206
      const bfd_target *temp;
207
      bfd_error_type err;
208
 
209
      if (*target == &binary_vec)
210
        continue;
211
 
212
      abfd->xvec = *target;     /* Change BFD's target temporarily */
213
 
214
      if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
215
        return false;
216
 
217
      /* If _bfd_check_format neglects to set bfd_error, assume
218
         bfd_error_wrong_format.  We didn't used to even pay any
219
         attention to bfd_error, so I suspect that some
220
         _bfd_check_format might have this problem.  */
221
      bfd_set_error (bfd_error_wrong_format);
222
 
223
      temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
224
 
225
      if (temp)
226
        {               /* This format checks out as ok!  */
227
          right_targ = temp;
228
 
229
          /* If this is the default target, accept it, even if other
230
             targets might match.  People who want those other targets
231
             have to set the GNUTARGET variable.  */
232
          if (temp == bfd_default_vector[0])
233
            {
234
              match_count = 1;
235
              break;
236
            }
237
 
238
          if (matching)
239
            matching_vector[match_count] = temp->name;
240
 
241
          match_count++;
242
 
243
#ifdef GNU960
244
          /* Big- and little-endian b.out archives look the same, but it
245
             doesn't matter: there is no difference in their headers, and
246
             member file byte orders will (I hope) be handled appropriately
247
             by bfd.  Ditto for big and little coff archives.  And the 4
248
             coff/b.out object formats are unambiguous.  So accept the
249
             first match we find.  */
250
          break;
251
#endif
252
        }
253
      else if ((err = bfd_get_error ()) == bfd_error_wrong_object_format
254
               || err == bfd_error_file_ambiguously_recognized)
255
        {
256
          /* 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
/*
332
FUNCTION
333
        bfd_set_format
334
 
335
SYNOPSIS
336
        boolean bfd_set_format(bfd *abfd, bfd_format format);
337
 
338
DESCRIPTION
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
 
345
boolean
346
bfd_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 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
/*
373
FUNCTION
374
        bfd_format_string
375
 
376
SYNOPSIS
377
        const char *bfd_format_string(bfd_format format);
378
 
379
DESCRIPTION
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
 
385
const char *
386
bfd_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.