]>
Commit | Line | Data |
---|---|---|
4a81b561 DHW |
1 | /* Copyright (C) 1990, 1991 Free Software Foundation, Inc. |
2 | ||
3 | This file is part of BFD, the Binary File Diddler. | |
4 | ||
5 | BFD is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 1, or (at your option) | |
8 | any later version. | |
9 | ||
10 | BFD is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with BFD; see the file COPYING. If not, write to | |
17 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
18 | ||
19 | /* $Id$ */ | |
20 | ||
21 | /*** libbfd.c -- random bfd support routines used internally only. */ | |
7ed4093a | 22 | #include <sysdep.h> |
4a81b561 DHW |
23 | #include "bfd.h" |
24 | #include "libbfd.h" | |
25 | ||
26 | ||
27 | \f | |
28 | /** Dummies for targets that don't want or need to implement | |
29 | certain operations */ | |
30 | ||
31 | boolean | |
536b27a5 SC |
32 | DEFUN(_bfd_dummy_new_section_hook,(ignore, ignore_newsect), |
33 | bfd *ignore AND | |
34 | asection *ignore_newsect) | |
4a81b561 DHW |
35 | { |
36 | return true; | |
37 | } | |
38 | ||
39 | boolean | |
536b27a5 SC |
40 | DEFUN(bfd_false ,(ignore), |
41 | bfd *ignore) | |
4a81b561 DHW |
42 | { |
43 | return false; | |
44 | } | |
45 | ||
46 | boolean | |
536b27a5 SC |
47 | DEFUN(bfd_true,(ignore), |
48 | bfd *ignore) | |
4a81b561 DHW |
49 | { |
50 | return true; | |
51 | } | |
52 | ||
d0ec7a8e | 53 | PTR |
536b27a5 SC |
54 | DEFUN(bfd_nullvoidptr,(ignore), |
55 | bfd *ignore) | |
4a81b561 | 56 | { |
d0ec7a8e | 57 | return (PTR)NULL; |
4a81b561 | 58 | } |
fc723380 | 59 | |
4a81b561 | 60 | int |
536b27a5 SC |
61 | DEFUN(bfd_0,(ignore), |
62 | bfd *ignore) | |
4a81b561 DHW |
63 | { |
64 | return 0; | |
65 | } | |
fc723380 | 66 | |
4a81b561 | 67 | unsigned int |
536b27a5 SC |
68 | DEFUN(bfd_0u,(ignore), |
69 | bfd *ignore) | |
4a81b561 DHW |
70 | { |
71 | return 0; | |
72 | } | |
73 | ||
74 | void | |
536b27a5 SC |
75 | DEFUN(bfd_void,(ignore), |
76 | bfd *ignore) | |
4a81b561 DHW |
77 | { |
78 | } | |
79 | ||
80 | boolean | |
536b27a5 SC |
81 | DEFUN(_bfd_dummy_core_file_matches_executable_p,(ignore_core_bfd, ignore_exec_bfd), |
82 | bfd *ignore_core_bfd AND | |
83 | bfd *ignore_exec_bfd) | |
4a81b561 DHW |
84 | { |
85 | bfd_error = invalid_operation; | |
86 | return false; | |
87 | } | |
88 | ||
89 | /* of course you can't initialize a function to be the same as another, grr */ | |
90 | ||
91 | char * | |
0f268757 | 92 | DEFUN(_bfd_dummy_core_file_failing_command,(ignore_abfd), |
536b27a5 | 93 | bfd *ignore_abfd) |
4a81b561 DHW |
94 | { |
95 | return (char *)NULL; | |
96 | } | |
97 | ||
98 | int | |
536b27a5 SC |
99 | DEFUN(_bfd_dummy_core_file_failing_signal,(ignore_abfd), |
100 | bfd *ignore_abfd) | |
4a81b561 DHW |
101 | { |
102 | return 0; | |
103 | } | |
104 | ||
105 | bfd_target * | |
536b27a5 SC |
106 | DEFUN(_bfd_dummy_target,(ignore_abfd), |
107 | bfd *ignore_abfd) | |
4a81b561 DHW |
108 | { |
109 | return 0; | |
110 | } | |
111 | \f | |
112 | /** zalloc -- allocate and clear storage */ | |
113 | ||
114 | ||
115 | #ifndef zalloc | |
116 | char * | |
536b27a5 SC |
117 | DEFUN(zalloc,(size), |
118 | bfd_size_type size) | |
4a81b561 | 119 | { |
7ed4093a | 120 | char *ptr = (char *) malloc ((int)size); |
4a81b561 DHW |
121 | |
122 | if ((ptr != NULL) && (size != 0)) | |
301dfc71 | 123 | memset(ptr,0, size); |
4a81b561 DHW |
124 | |
125 | return ptr; | |
126 | } | |
127 | #endif | |
128 | \f | |
129 | /* Some IO code */ | |
130 | ||
131 | ||
132 | /* Note that archive entries don't have streams; they share their parent's. | |
133 | This allows someone to play with the iostream behind bfd's back. | |
134 | ||
135 | Also, note that the origin pointer points to the beginning of a file's | |
136 | contents (0 for non-archive elements). For archive entries this is the | |
137 | first octet in the file, NOT the beginning of the archive header. */ | |
138 | ||
7ed4093a SC |
139 | static |
140 | int DEFUN(real_read,(where, a,b, file), | |
6f715d66 SC |
141 | PTR where AND |
142 | int a AND | |
143 | int b AND | |
144 | FILE *file) | |
7ed4093a SC |
145 | { |
146 | return fread(where, a,b,file); | |
147 | } | |
23b0b558 | 148 | bfd_size_type |
7ed4093a SC |
149 | DEFUN(bfd_read,(ptr, size, nitems, abfd), |
150 | PTR ptr AND | |
151 | bfd_size_type size AND | |
152 | bfd_size_type nitems AND | |
153 | bfd *abfd) | |
4a81b561 | 154 | { |
7ed4093a | 155 | return (bfd_size_type)real_read (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd)); |
4a81b561 DHW |
156 | } |
157 | ||
23b0b558 | 158 | bfd_size_type |
7ed4093a SC |
159 | DEFUN(bfd_write,(ptr, size, nitems, abfd), |
160 | PTR ptr AND | |
161 | bfd_size_type size AND | |
162 | bfd_size_type nitems AND | |
163 | bfd *abfd) | |
4a81b561 | 164 | { |
7ed4093a | 165 | return fwrite (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd)); |
4a81b561 DHW |
166 | } |
167 | ||
168 | int | |
7ed4093a SC |
169 | DEFUN(bfd_seek,(abfd, position, direction), |
170 | bfd * CONST abfd AND | |
171 | CONST file_ptr position AND | |
172 | CONST int direction) | |
4a81b561 | 173 | { |
6f715d66 SC |
174 | /* For the time being, a bfd may not seek to it's end. The |
175 | problem is that we don't easily have a way to recognize | |
176 | the end of an element in an archive. */ | |
177 | ||
178 | BFD_ASSERT(direction == SEEK_SET | |
179 | || direction == SEEK_CUR); | |
180 | ||
181 | if (direction == SEEK_SET && abfd->my_archive != NULL) | |
182 | { | |
183 | /* This is a set within an archive, so we need to | |
184 | add the base of the object within the archive */ | |
185 | return(fseek(bfd_cache_lookup(abfd), | |
186 | position + abfd->origin, | |
187 | direction)); | |
188 | } | |
189 | else | |
190 | { | |
191 | return(fseek(bfd_cache_lookup(abfd), position, direction)); | |
192 | } | |
4a81b561 DHW |
193 | } |
194 | ||
195 | long | |
536b27a5 SC |
196 | DEFUN(bfd_tell,(abfd), |
197 | bfd *abfd) | |
4a81b561 | 198 | { |
6f715d66 | 199 | file_ptr ptr; |
4a81b561 | 200 | |
6f715d66 | 201 | ptr = ftell (bfd_cache_lookup(abfd)); |
4a81b561 | 202 | |
6f715d66 SC |
203 | if (abfd->my_archive) |
204 | ptr -= abfd->origin; | |
205 | return ptr; | |
4a81b561 DHW |
206 | } |
207 | \f | |
208 | /** Make a string table */ | |
209 | ||
6f715d66 SC |
210 | /*>bfd.h< |
211 | Add string to table pointed to by table, at location starting with free_ptr. | |
4a81b561 DHW |
212 | resizes the table if necessary (if it's NULL, creates it, ignoring |
213 | table_length). Updates free_ptr, table, table_length */ | |
214 | ||
215 | boolean | |
536b27a5 SC |
216 | DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr), |
217 | char **table AND | |
536b27a5 | 218 | char *new_string AND |
5ad1d830 SC |
219 | unsigned int *table_length AND |
220 | char **free_ptr) | |
4a81b561 DHW |
221 | { |
222 | size_t string_length = strlen (new_string) + 1; /* include null here */ | |
223 | char *base = *table; | |
224 | size_t space_length = *table_length; | |
225 | unsigned int offset = (base ? *free_ptr - base : 0); | |
226 | ||
227 | if (base == NULL) { | |
228 | /* Avoid a useless regrow if we can (but of course we still | |
229 | take it next time */ | |
230 | space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ? | |
6f715d66 | 231 | DEFAULT_STRING_SPACE_SIZE : string_length+1); |
4a81b561 DHW |
232 | base = zalloc (space_length); |
233 | ||
234 | if (base == NULL) { | |
235 | bfd_error = no_memory; | |
236 | return false; | |
237 | } | |
238 | } | |
239 | ||
240 | if ((size_t)(offset + string_length) >= space_length) { | |
241 | /* Make sure we will have enough space */ | |
242 | while ((size_t)(offset + string_length) >= space_length) | |
243 | space_length += space_length/2; /* grow by 50% */ | |
244 | ||
245 | base = (char *) realloc (base, space_length); | |
246 | if (base == NULL) { | |
247 | bfd_error = no_memory; | |
248 | return false; | |
249 | } | |
250 | ||
251 | } | |
252 | ||
253 | memcpy (base + offset, new_string, string_length); | |
254 | *table = base; | |
255 | *table_length = space_length; | |
256 | *free_ptr = base + offset + string_length; | |
257 | ||
258 | return true; | |
259 | } | |
260 | \f | |
261 | /** The do-it-yourself (byte) sex-change kit */ | |
262 | ||
263 | /* The middle letter e.g. get<b>short indicates Big or Little endian | |
264 | target machine. It doesn't matter what the byte order of the host | |
265 | machine is; these routines work for either. */ | |
266 | ||
267 | /* FIXME: Should these take a count argument? | |
268 | Answer ([email protected]): No, but perhaps they should be inline | |
6f715d66 SC |
269 | functions in swap.h #ifdef __GNUC__. |
270 | Gprof them later and find out. */ | |
271 | ||
272 | /*proto* | |
273 | *i bfd_put_size | |
274 | *i bfd_get_size | |
275 | These macros as used for reading and writing raw data in sections; | |
276 | each access (except for bytes) is vectored through the target format | |
277 | of the bfd and mangled accordingly. The mangling performs any | |
278 | necessary endian translations and removes alignment restrictions. | |
279 | *+ | |
280 | #define bfd_put_8(abfd, val, ptr) \ | |
281 | (*((char *)ptr) = (char)val) | |
282 | #define bfd_get_8(abfd, ptr) \ | |
283 | (*((char *)ptr)) | |
284 | #define bfd_put_16(abfd, val, ptr) \ | |
285 | BFD_SEND(abfd, bfd_putx16, (val,ptr)) | |
286 | #define bfd_get_16(abfd, ptr) \ | |
287 | BFD_SEND(abfd, bfd_getx16, (ptr)) | |
288 | #define bfd_put_32(abfd, val, ptr) \ | |
289 | BFD_SEND(abfd, bfd_putx32, (val,ptr)) | |
290 | #define bfd_get_32(abfd, ptr) \ | |
291 | BFD_SEND(abfd, bfd_getx32, (ptr)) | |
292 | #define bfd_put_64(abfd, val, ptr) \ | |
293 | BFD_SEND(abfd, bfd_putx64, (val, ptr)) | |
294 | #define bfd_get_64(abfd, ptr) \ | |
295 | BFD_SEND(abfd, bfd_getx64, (ptr)) | |
296 | *- | |
297 | *-*/ | |
298 | ||
299 | /*proto* | |
300 | *i bfd_h_put_size | |
301 | *i bfd_h_get_size | |
302 | These macros have the same function as their @code{bfd_get_x} | |
303 | bretherin, except that they are used for removing information for the | |
304 | header records of object files. Believe it or not, some object files | |
305 | keep their header records in big endian order, and their data in little | |
306 | endan order. | |
307 | *+ | |
308 | #define bfd_h_put_8(abfd, val, ptr) \ | |
309 | (*((char *)ptr) = (char)val) | |
310 | #define bfd_h_get_8(abfd, ptr) \ | |
311 | (*((char *)ptr)) | |
312 | #define bfd_h_put_16(abfd, val, ptr) \ | |
313 | BFD_SEND(abfd, bfd_h_putx16,(val,ptr)) | |
314 | #define bfd_h_get_16(abfd, ptr) \ | |
315 | BFD_SEND(abfd, bfd_h_getx16,(ptr)) | |
316 | #define bfd_h_put_32(abfd, val, ptr) \ | |
317 | BFD_SEND(abfd, bfd_h_putx32,(val,ptr)) | |
318 | #define bfd_h_get_32(abfd, ptr) \ | |
319 | BFD_SEND(abfd, bfd_h_getx32,(ptr)) | |
320 | #define bfd_h_put_64(abfd, val, ptr) \ | |
321 | BFD_SEND(abfd, bfd_h_putx64,(val, ptr)) | |
322 | #define bfd_h_get_64(abfd, ptr) \ | |
323 | BFD_SEND(abfd, bfd_h_getx64,(ptr)) | |
324 | *- | |
325 | *-*/ | |
4a81b561 | 326 | |
7ed4093a | 327 | unsigned int |
536b27a5 SC |
328 | DEFUN(_do_getb16,(addr), |
329 | register bfd_byte *addr) | |
4a81b561 | 330 | { |
6f715d66 | 331 | return (addr[0] << 8) | addr[1]; |
4a81b561 DHW |
332 | } |
333 | ||
7ed4093a | 334 | unsigned int |
536b27a5 SC |
335 | DEFUN(_do_getl16,(addr), |
336 | register bfd_byte *addr) | |
4a81b561 | 337 | { |
6f715d66 | 338 | return (addr[1] << 8) | addr[0]; |
4a81b561 DHW |
339 | } |
340 | ||
341 | void | |
536b27a5 SC |
342 | DEFUN(_do_putb16,(data, addr), |
343 | int data AND | |
344 | register bfd_byte *addr) | |
4a81b561 | 345 | { |
6f715d66 SC |
346 | addr[0] = (bfd_byte)(data >> 8); |
347 | addr[1] = (bfd_byte )data; | |
4a81b561 DHW |
348 | } |
349 | ||
350 | void | |
536b27a5 | 351 | DEFUN(_do_putl16,(data, addr), |
6f715d66 | 352 | int data AND |
536b27a5 | 353 | register bfd_byte *addr) |
4a81b561 | 354 | { |
6f715d66 SC |
355 | addr[0] = (bfd_byte )data; |
356 | addr[1] = (bfd_byte)(data >> 8); | |
4a81b561 DHW |
357 | } |
358 | ||
7ed4093a | 359 | unsigned int |
536b27a5 SC |
360 | DEFUN(_do_getb32,(addr), |
361 | register bfd_byte *addr) | |
4a81b561 | 362 | { |
6f715d66 | 363 | return ((((addr[0] << 8) | addr[1]) << 8) | addr[2]) << 8 | addr[3]; |
4a81b561 DHW |
364 | } |
365 | ||
7ed4093a SC |
366 | unsigned int |
367 | _do_getl32 (addr) | |
6f715d66 | 368 | register bfd_byte *addr; |
4a81b561 | 369 | { |
6f715d66 | 370 | return ((((addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; |
4a81b561 DHW |
371 | } |
372 | ||
7ed4093a | 373 | bfd_64_type |
536b27a5 SC |
374 | DEFUN(_do_getb64,(addr), |
375 | register bfd_byte *addr) | |
7ed4093a | 376 | { |
536b27a5 | 377 | #ifdef HOST_64_BIT |
7ed4093a | 378 | bfd_64_type low, high; |
536b27a5 | 379 | |
7ed4093a | 380 | high= ((((((((addr[0]) << 8) | |
6f715d66 SC |
381 | addr[1]) << 8) | |
382 | addr[2]) << 8) | | |
383 | addr[3]) ); | |
7ed4093a SC |
384 | |
385 | low = ((((((((addr[4]) << 8) | | |
6f715d66 SC |
386 | addr[5]) << 8) | |
387 | addr[6]) << 8) | | |
388 | addr[7])); | |
7ed4093a SC |
389 | |
390 | return high << 32 | low; | |
391 | #else | |
6f715d66 | 392 | bfd_64_type foo; |
7ed4093a | 393 | BFD_FAIL(); |
6f715d66 | 394 | return foo; |
7ed4093a SC |
395 | #endif |
396 | ||
397 | } | |
398 | ||
399 | bfd_64_type | |
5ad1d830 | 400 | DEFUN(_do_getl64,(addr), |
536b27a5 | 401 | register bfd_byte *addr) |
7ed4093a | 402 | { |
6f715d66 | 403 | |
536b27a5 | 404 | #ifdef HOST_64_BIT |
6f715d66 | 405 | bfd_64_type low, high; |
7ed4093a | 406 | high= (((((((addr[7] << 8) | |
6f715d66 SC |
407 | addr[6]) << 8) | |
408 | addr[5]) << 8) | | |
409 | addr[4])); | |
7ed4093a SC |
410 | |
411 | low = (((((((addr[3] << 8) | | |
6f715d66 SC |
412 | addr[2]) << 8) | |
413 | addr[1]) << 8) | | |
414 | addr[0]) ); | |
7ed4093a SC |
415 | |
416 | return high << 32 | low; | |
417 | #else | |
6f715d66 | 418 | bfd_64_type foo; |
7ed4093a | 419 | BFD_FAIL(); |
6f715d66 | 420 | return foo; |
7ed4093a | 421 | #endif |
6f715d66 | 422 | |
7ed4093a SC |
423 | } |
424 | ||
4a81b561 | 425 | void |
536b27a5 SC |
426 | DEFUN(_do_putb32,(data, addr), |
427 | unsigned long data AND | |
428 | register bfd_byte *addr) | |
4a81b561 | 429 | { |
6f715d66 SC |
430 | addr[0] = (bfd_byte)(data >> 24); |
431 | addr[1] = (bfd_byte)(data >> 16); | |
432 | addr[2] = (bfd_byte)(data >> 8); | |
433 | addr[3] = (bfd_byte)data; | |
4a81b561 DHW |
434 | } |
435 | ||
436 | void | |
536b27a5 SC |
437 | DEFUN(_do_putl32,(data, addr), |
438 | unsigned long data AND | |
439 | register bfd_byte *addr) | |
4a81b561 | 440 | { |
6f715d66 SC |
441 | addr[0] = (bfd_byte)data; |
442 | addr[1] = (bfd_byte)(data >> 8); | |
443 | addr[2] = (bfd_byte)(data >> 16); | |
444 | addr[3] = (bfd_byte)(data >> 24); | |
4a81b561 | 445 | } |
7ed4093a | 446 | void |
536b27a5 | 447 | DEFUN(_do_putb64,(data, addr), |
6f715d66 SC |
448 | bfd_64_type data AND |
449 | register bfd_byte *addr) | |
7ed4093a | 450 | { |
536b27a5 SC |
451 | #ifdef HOST_64_BIT |
452 | addr[0] = (bfd_byte)(data >> (7*8)); | |
453 | addr[1] = (bfd_byte)(data >> (6*8)); | |
454 | addr[2] = (bfd_byte)(data >> (5*8)); | |
455 | addr[3] = (bfd_byte)(data >> (4*8)); | |
456 | addr[4] = (bfd_byte)(data >> (3*8)); | |
457 | addr[5] = (bfd_byte)(data >> (2*8)); | |
458 | addr[6] = (bfd_byte)(data >> (1*8)); | |
459 | addr[7] = (bfd_byte)(data >> (0*8)); | |
7ed4093a | 460 | #else |
536b27a5 | 461 | BFD_FAIL(); |
7ed4093a SC |
462 | #endif |
463 | ||
464 | } | |
465 | ||
466 | void | |
536b27a5 SC |
467 | DEFUN(_do_putl64,(data, addr), |
468 | bfd_64_type data AND | |
469 | register bfd_byte *addr) | |
7ed4093a | 470 | { |
536b27a5 SC |
471 | #ifdef HOST_64_BIT |
472 | addr[7] = (bfd_byte)(data >> (7*8)); | |
473 | addr[6] = (bfd_byte)(data >> (6*8)); | |
474 | addr[5] = (bfd_byte)(data >> (5*8)); | |
475 | addr[4] = (bfd_byte)(data >> (4*8)); | |
476 | addr[3] = (bfd_byte)(data >> (3*8)); | |
477 | addr[2] = (bfd_byte)(data >> (2*8)); | |
478 | addr[1] = (bfd_byte)(data >> (1*8)); | |
479 | addr[0] = (bfd_byte)(data >> (0*8)); | |
7ed4093a | 480 | #else |
536b27a5 | 481 | BFD_FAIL(); |
7ed4093a SC |
482 | #endif |
483 | ||
484 | } | |
485 | ||
2203f786 JG |
486 | \f |
487 | /* Default implementation */ | |
4a81b561 | 488 | |
2203f786 | 489 | boolean |
7ed4093a SC |
490 | DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count), |
491 | bfd *abfd AND | |
492 | sec_ptr section AND | |
493 | PTR location AND | |
494 | file_ptr offset AND | |
495 | bfd_size_type count) | |
2203f786 JG |
496 | { |
497 | if (count == 0) | |
6f715d66 | 498 | return true; |
7ed4093a | 499 | if ((bfd_size_type)offset >= section->size |
6f715d66 SC |
500 | || bfd_seek(abfd,(file_ptr)( section->filepos + offset), SEEK_SET) == -1 |
501 | || bfd_read(location, (bfd_size_type)1, count, abfd) != count) | |
502 | return (false); /* on error */ | |
2203f786 JG |
503 | return (true); |
504 | } | |
6f715d66 SC |
505 | |
506 | /*proto-internal* | |
507 | *i bfd_log2 | |
508 | Return the log base 2 of the value supplied, rounded up. eg an arg | |
509 | of 1025 would return 11. | |
510 | *; PROTO(bfd_vma, bfd_log2,(bfd_vma x)); | |
511 | *-*/ | |
512 | ||
513 | bfd_vma bfd_log2(x) | |
514 | bfd_vma x; | |
515 | { | |
516 | bfd_vma result = 0; | |
517 | while ( (bfd_vma)(1<< result) < x) | |
518 | result++; | |
519 | return result; | |
520 | } |