]>
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. */ | |
22 | #include "sysdep.h" | |
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 | |
32 | _bfd_dummy_new_section_hook (ignore, ignore_newsect) | |
33 | bfd *ignore; | |
34 | asection *ignore_newsect; | |
35 | { | |
36 | return true; | |
37 | } | |
38 | ||
39 | boolean | |
40 | bfd_false (ignore) | |
41 | bfd *ignore; | |
42 | { | |
43 | return false; | |
44 | } | |
45 | ||
46 | boolean | |
47 | bfd_true (ignore) | |
48 | bfd *ignore; | |
49 | { | |
50 | return true; | |
51 | } | |
52 | ||
53 | void * | |
54 | bfd_nullvoidptr(ignore) | |
55 | bfd *ignore; | |
56 | { | |
57 | return (void *)NULL; | |
58 | } | |
59 | int | |
60 | bfd_0(ignore) | |
61 | bfd *ignore; | |
62 | { | |
63 | return 0; | |
64 | } | |
65 | unsigned int | |
66 | bfd_0u(ignore) | |
67 | bfd *ignore; | |
68 | { | |
69 | return 0; | |
70 | } | |
71 | ||
72 | void | |
73 | bfd_void(ignore) | |
74 | bfd *ignore; | |
75 | { | |
76 | } | |
77 | ||
78 | boolean | |
79 | _bfd_dummy_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd) | |
80 | bfd *ignore_core_bfd; | |
81 | bfd *ignore_exec_bfd; | |
82 | { | |
83 | bfd_error = invalid_operation; | |
84 | return false; | |
85 | } | |
86 | ||
87 | /* of course you can't initialize a function to be the same as another, grr */ | |
88 | ||
89 | char * | |
90 | _bfd_dummy_core_file_failing_command (ignore_abfd) | |
91 | bfd *ignore_abfd; | |
92 | { | |
93 | return (char *)NULL; | |
94 | } | |
95 | ||
96 | int | |
97 | _bfd_dummy_core_file_failing_signal (ignore_abfd) | |
98 | bfd *ignore_abfd; | |
99 | { | |
100 | return 0; | |
101 | } | |
102 | ||
103 | bfd_target * | |
104 | _bfd_dummy_target (ignore_abfd) | |
105 | bfd *ignore_abfd; | |
106 | { | |
107 | return 0; | |
108 | } | |
109 | \f | |
110 | /** zalloc -- allocate and clear storage */ | |
111 | ||
112 | ||
113 | #ifndef zalloc | |
114 | char * | |
115 | zalloc (size) | |
116 | size_t size; | |
117 | { | |
118 | char *ptr = malloc (size); | |
119 | ||
120 | if ((ptr != NULL) && (size != 0)) | |
121 | bzero (ptr, size); | |
122 | ||
123 | return ptr; | |
124 | } | |
125 | #endif | |
126 | \f | |
127 | /* Some IO code */ | |
128 | ||
129 | ||
130 | /* Note that archive entries don't have streams; they share their parent's. | |
131 | This allows someone to play with the iostream behind bfd's back. | |
132 | ||
133 | Also, note that the origin pointer points to the beginning of a file's | |
134 | contents (0 for non-archive elements). For archive entries this is the | |
135 | first octet in the file, NOT the beginning of the archive header. */ | |
136 | ||
137 | size_t | |
138 | bfd_read (ptr, size, nitems, abfd) | |
139 | void *ptr; | |
140 | size_t size; | |
141 | size_t nitems; | |
142 | bfd *abfd; | |
143 | { | |
144 | return fread (ptr, 1, size*nitems, bfd_cache_lookup(abfd)); | |
145 | } | |
146 | ||
147 | size_t | |
148 | bfd_write (ptr, size, nitems, abfd) | |
149 | void *ptr; | |
150 | size_t size; | |
151 | size_t nitems; | |
152 | bfd *abfd; | |
153 | { | |
154 | return fwrite (ptr, 1, size*nitems, bfd_cache_lookup(abfd)); | |
155 | } | |
156 | ||
157 | int | |
158 | bfd_seek (abfd, position, direction) | |
159 | bfd *abfd; | |
160 | file_ptr position; | |
161 | int direction; | |
162 | { | |
163 | /* For the time being, a bfd may not seek to it's end. The | |
164 | problem is that we don't easily have a way to recognize | |
165 | the end of an element in an archive. */ | |
166 | ||
167 | BFD_ASSERT(direction == SEEK_SET | |
168 | || direction == SEEK_CUR); | |
169 | ||
170 | if (direction == SEEK_SET && abfd->my_archive != NULL) | |
171 | { | |
172 | /* This is a set within an archive, so we need to | |
173 | add the base of the object within the archive */ | |
174 | return(fseek(bfd_cache_lookup(abfd), | |
175 | position + abfd->origin, | |
176 | direction)); | |
177 | } | |
178 | else | |
179 | { | |
180 | return(fseek(bfd_cache_lookup(abfd), position, direction)); | |
181 | } | |
182 | } | |
183 | ||
184 | long | |
185 | bfd_tell (abfd) | |
186 | bfd *abfd; | |
187 | { | |
188 | file_ptr ptr; | |
189 | ||
190 | ptr = ftell (bfd_cache_lookup(abfd)); | |
191 | ||
192 | if (abfd->my_archive) | |
193 | ptr -= abfd->origin; | |
194 | return ptr; | |
195 | } | |
196 | \f | |
197 | /** Make a string table */ | |
198 | ||
199 | /* Add string to table pointed to by table, at location starting with free_ptr. | |
200 | resizes the table if necessary (if it's NULL, creates it, ignoring | |
201 | table_length). Updates free_ptr, table, table_length */ | |
202 | ||
203 | boolean | |
204 | bfd_add_to_string_table (table, new_string, table_length, free_ptr) | |
205 | char **table, **free_ptr; | |
206 | char *new_string; | |
207 | unsigned int *table_length; | |
208 | { | |
209 | size_t string_length = strlen (new_string) + 1; /* include null here */ | |
210 | char *base = *table; | |
211 | size_t space_length = *table_length; | |
212 | unsigned int offset = (base ? *free_ptr - base : 0); | |
213 | ||
214 | if (base == NULL) { | |
215 | /* Avoid a useless regrow if we can (but of course we still | |
216 | take it next time */ | |
217 | space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ? | |
218 | DEFAULT_STRING_SPACE_SIZE : string_length+1); | |
219 | base = zalloc (space_length); | |
220 | ||
221 | if (base == NULL) { | |
222 | bfd_error = no_memory; | |
223 | return false; | |
224 | } | |
225 | } | |
226 | ||
227 | if ((size_t)(offset + string_length) >= space_length) { | |
228 | /* Make sure we will have enough space */ | |
229 | while ((size_t)(offset + string_length) >= space_length) | |
230 | space_length += space_length/2; /* grow by 50% */ | |
231 | ||
232 | base = (char *) realloc (base, space_length); | |
233 | if (base == NULL) { | |
234 | bfd_error = no_memory; | |
235 | return false; | |
236 | } | |
237 | ||
238 | } | |
239 | ||
240 | memcpy (base + offset, new_string, string_length); | |
241 | *table = base; | |
242 | *table_length = space_length; | |
243 | *free_ptr = base + offset + string_length; | |
244 | ||
245 | return true; | |
246 | } | |
247 | \f | |
248 | /** The do-it-yourself (byte) sex-change kit */ | |
249 | ||
250 | /* The middle letter e.g. get<b>short indicates Big or Little endian | |
251 | target machine. It doesn't matter what the byte order of the host | |
252 | machine is; these routines work for either. */ | |
253 | ||
254 | /* FIXME: Should these take a count argument? | |
255 | Answer ([email protected]): No, but perhaps they should be inline | |
256 | functions in swap.h #ifdef __GNUC__. | |
257 | Gprof them later and find out. */ | |
258 | ||
259 | short | |
260 | _do_getbshort (addr) | |
261 | register bfd_byte *addr; | |
262 | { | |
263 | return (addr[0] << 8) | addr[1]; | |
264 | } | |
265 | ||
266 | short | |
267 | _do_getlshort (addr) | |
268 | register bfd_byte *addr; | |
269 | { | |
270 | return (addr[1] << 8) | addr[0]; | |
271 | } | |
272 | ||
273 | void | |
274 | _do_putbshort (data, addr) | |
275 | int data; /* Actually short, but ansi C sucks */ | |
276 | register bfd_byte *addr; | |
277 | { | |
278 | addr[0] = (bfd_byte)(data >> 8); | |
279 | addr[1] = (bfd_byte )data; | |
280 | } | |
281 | ||
282 | void | |
283 | _do_putlshort (data, addr) | |
284 | int data; /* Actually short, but ansi C sucks */ | |
285 | register bfd_byte *addr; | |
286 | { | |
287 | addr[0] = (bfd_byte )data; | |
288 | addr[1] = (bfd_byte)(data >> 8); | |
289 | } | |
290 | ||
291 | long | |
292 | _do_getblong (addr) | |
293 | register bfd_byte *addr; | |
294 | { | |
295 | return ((((addr[0] << 8) | addr[1]) << 8) | addr[2]) << 8 | addr[3]; | |
296 | } | |
297 | ||
298 | long | |
299 | _do_getllong (addr) | |
300 | register bfd_byte *addr; | |
301 | { | |
302 | return ((((addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; | |
303 | } | |
304 | ||
305 | void | |
306 | _do_putblong (data, addr) | |
307 | unsigned long data; | |
308 | register bfd_byte *addr; | |
309 | { | |
310 | addr[0] = (bfd_byte)(data >> 24); | |
311 | addr[1] = (bfd_byte)(data >> 16); | |
312 | addr[2] = (bfd_byte)(data >> 8); | |
313 | addr[3] = (bfd_byte)data; | |
314 | } | |
315 | ||
316 | void | |
317 | _do_putllong (data, addr) | |
318 | unsigned long data; | |
319 | register bfd_byte *addr; | |
320 | { | |
321 | addr[0] = (bfd_byte)data; | |
322 | addr[1] = (bfd_byte)(data >> 8); | |
323 | addr[2] = (bfd_byte)(data >> 16); | |
324 | addr[3] = (bfd_byte)(data >> 24); | |
325 | } | |
326 | ||
327 | ||
328 | ||
329 | ||
330 | ||
331 | ||
332 |