pef.c revision 1.1.1.11 1 1.1 skrll /* PEF support for BFD.
2 1.1.1.11 christos Copyright (C) 1999-2025 Free Software Foundation, Inc.
3 1.1 skrll
4 1.1 skrll This file is part of BFD, the Binary File Descriptor library.
5 1.1 skrll
6 1.1 skrll This program is free software; you can redistribute it and/or modify
7 1.1 skrll it under the terms of the GNU General Public License as published by
8 1.1 skrll the Free Software Foundation; either version 3 of the License, or
9 1.1 skrll (at your option) any later version.
10 1.1 skrll
11 1.1 skrll This program is distributed in the hope that it will be useful,
12 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 skrll GNU General Public License for more details.
15 1.1 skrll
16 1.1 skrll You should have received a copy of the GNU General Public License
17 1.1 skrll along with this program; if not, write to the Free Software
18 1.1 skrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 skrll MA 02110-1301, USA. */
20 1.1 skrll
21 1.1.1.3 christos /* PEF (Preferred Executable Format) is the binary file format for late
22 1.1.1.3 christos classic Mac OS versions (before Darwin). It is supported by both m68k
23 1.1.1.3 christos and PowerPc. It is also called CFM (Code Fragment Manager). */
24 1.1.1.3 christos
25 1.1 skrll #include "sysdep.h"
26 1.1 skrll #include "safe-ctype.h"
27 1.1 skrll #include "pef.h"
28 1.1 skrll #include "pef-traceback.h"
29 1.1 skrll #include "bfd.h"
30 1.1 skrll #include "libbfd.h"
31 1.1 skrll #include "libiberty.h"
32 1.1 skrll
33 1.1 skrll #ifndef BFD_IO_FUNCS
34 1.1 skrll #define BFD_IO_FUNCS 0
35 1.1 skrll #endif
36 1.1 skrll
37 1.1.1.6 christos #define bfd_pef_close_and_cleanup _bfd_generic_close_and_cleanup
38 1.1.1.6 christos #define bfd_pef_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
39 1.1.1.6 christos #define bfd_pef_new_section_hook _bfd_generic_new_section_hook
40 1.1.1.6 christos #define bfd_pef_bfd_is_local_label_name bfd_generic_is_local_label_name
41 1.1.1.7 christos #define bfd_pef_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false
42 1.1.1.6 christos #define bfd_pef_get_lineno _bfd_nosymbols_get_lineno
43 1.1.1.6 christos #define bfd_pef_find_nearest_line _bfd_nosymbols_find_nearest_line
44 1.1.1.10 christos #define bfd_pef_find_nearest_line_with_alt _bfd_nosymbols_find_nearest_line_with_alt
45 1.1.1.6 christos #define bfd_pef_find_line _bfd_nosymbols_find_line
46 1.1.1.6 christos #define bfd_pef_find_inliner_info _bfd_nosymbols_find_inliner_info
47 1.1.1.4 christos #define bfd_pef_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string
48 1.1.1.6 christos #define bfd_pef_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
49 1.1.1.6 christos #define bfd_pef_read_minisymbols _bfd_generic_read_minisymbols
50 1.1.1.6 christos #define bfd_pef_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
51 1.1.1.6 christos #define bfd_pef_set_arch_mach _bfd_generic_set_arch_mach
52 1.1.1.6 christos #define bfd_pef_get_section_contents _bfd_generic_get_section_contents
53 1.1.1.6 christos #define bfd_pef_set_section_contents _bfd_generic_set_section_contents
54 1.1 skrll #define bfd_pef_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
55 1.1.1.6 christos #define bfd_pef_bfd_relax_section bfd_generic_relax_section
56 1.1.1.6 christos #define bfd_pef_bfd_gc_sections bfd_generic_gc_sections
57 1.1.1.6 christos #define bfd_pef_bfd_lookup_section_flags bfd_generic_lookup_section_flags
58 1.1.1.6 christos #define bfd_pef_bfd_merge_sections bfd_generic_merge_sections
59 1.1 skrll #define bfd_pef_bfd_is_group_section bfd_generic_is_group_section
60 1.1.1.8 christos #define bfd_pef_bfd_group_name bfd_generic_group_name
61 1.1.1.6 christos #define bfd_pef_bfd_discard_group bfd_generic_discard_group
62 1.1.1.6 christos #define bfd_pef_section_already_linked _bfd_generic_section_already_linked
63 1.1.1.6 christos #define bfd_pef_bfd_define_common_symbol bfd_generic_define_common_symbol
64 1.1.1.7 christos #define bfd_pef_bfd_link_hide_symbol _bfd_generic_link_hide_symbol
65 1.1.1.6 christos #define bfd_pef_bfd_define_start_stop bfd_generic_define_start_stop
66 1.1.1.6 christos #define bfd_pef_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
67 1.1.1.6 christos #define bfd_pef_bfd_link_add_symbols _bfd_generic_link_add_symbols
68 1.1.1.6 christos #define bfd_pef_bfd_link_just_syms _bfd_generic_link_just_syms
69 1.1.1.2 christos #define bfd_pef_bfd_copy_link_hash_symbol_type \
70 1.1.1.2 christos _bfd_generic_copy_link_hash_symbol_type
71 1.1.1.6 christos #define bfd_pef_bfd_final_link _bfd_generic_final_link
72 1.1.1.6 christos #define bfd_pef_bfd_link_split_section _bfd_generic_link_split_section
73 1.1.1.6 christos #define bfd_pef_bfd_link_check_relocs _bfd_generic_link_check_relocs
74 1.1 skrll
75 1.1 skrll static int
76 1.1 skrll bfd_pef_parse_traceback_table (bfd *abfd,
77 1.1 skrll asection *section,
78 1.1 skrll unsigned char *buf,
79 1.1 skrll size_t len,
80 1.1 skrll size_t pos,
81 1.1 skrll asymbol *sym,
82 1.1 skrll FILE *file)
83 1.1 skrll {
84 1.1 skrll struct traceback_table table;
85 1.1 skrll size_t offset;
86 1.1 skrll const char *s;
87 1.1 skrll asymbol tmpsymbol;
88 1.1 skrll
89 1.1 skrll if (sym == NULL)
90 1.1 skrll sym = & tmpsymbol;
91 1.1 skrll
92 1.1 skrll sym->name = NULL;
93 1.1 skrll sym->value = 0;
94 1.1 skrll sym->the_bfd = abfd;
95 1.1 skrll sym->section = section;
96 1.1 skrll sym->flags = 0;
97 1.1 skrll sym->udata.i = 0;
98 1.1 skrll
99 1.1 skrll /* memcpy is fine since all fields are unsigned char. */
100 1.1 skrll if ((pos + 8) > len)
101 1.1 skrll return -1;
102 1.1 skrll memcpy (&table, buf + pos, 8);
103 1.1 skrll
104 1.1 skrll /* Calling code relies on returned symbols having a name and
105 1.1 skrll correct offset. */
106 1.1 skrll if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS))
107 1.1 skrll return -1;
108 1.1 skrll
109 1.1 skrll if (! (table.flags2 & TB_NAME_PRESENT))
110 1.1 skrll return -1;
111 1.1 skrll
112 1.1.1.2 christos if (! (table.flags1 & TB_HAS_TBOFF))
113 1.1 skrll return -1;
114 1.1 skrll
115 1.1 skrll offset = 8;
116 1.1 skrll
117 1.1 skrll if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams))
118 1.1 skrll offset += 4;
119 1.1 skrll
120 1.1 skrll if (table.flags1 & TB_HAS_TBOFF)
121 1.1 skrll {
122 1.1 skrll struct traceback_table_tboff off;
123 1.1 skrll
124 1.1 skrll if ((pos + offset + 4) > len)
125 1.1 skrll return -1;
126 1.1 skrll off.tb_offset = bfd_getb32 (buf + pos + offset);
127 1.1 skrll offset += 4;
128 1.1 skrll
129 1.1 skrll /* Need to subtract 4 because the offset includes the 0x0L
130 1.1 skrll preceding the table. */
131 1.1 skrll if (file != NULL)
132 1.1 skrll fprintf (file, " [offset = 0x%lx]", off.tb_offset);
133 1.1 skrll
134 1.1 skrll if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset)))
135 1.1 skrll return -1;
136 1.1 skrll
137 1.1 skrll sym->value = pos - off.tb_offset - 4;
138 1.1 skrll }
139 1.1 skrll
140 1.1 skrll if (table.flags2 & TB_INT_HNDL)
141 1.1 skrll offset += 4;
142 1.1 skrll
143 1.1 skrll if (table.flags1 & TB_HAS_CTL)
144 1.1 skrll {
145 1.1 skrll struct traceback_table_anchors anchors;
146 1.1 skrll
147 1.1 skrll if ((pos + offset + 4) > len)
148 1.1 skrll return -1;
149 1.1 skrll anchors.ctl_info = bfd_getb32 (buf + pos + offset);
150 1.1 skrll offset += 4;
151 1.1 skrll
152 1.1 skrll if (anchors.ctl_info > 1024)
153 1.1 skrll return -1;
154 1.1 skrll
155 1.1 skrll offset += anchors.ctl_info * 4;
156 1.1 skrll }
157 1.1 skrll
158 1.1 skrll if (table.flags2 & TB_NAME_PRESENT)
159 1.1 skrll {
160 1.1 skrll struct traceback_table_routine name;
161 1.1 skrll char *namebuf;
162 1.1 skrll
163 1.1 skrll if ((pos + offset + 2) > len)
164 1.1 skrll return -1;
165 1.1 skrll name.name_len = bfd_getb16 (buf + pos + offset);
166 1.1 skrll offset += 2;
167 1.1 skrll
168 1.1 skrll if (name.name_len > 4096)
169 1.1 skrll return -1;
170 1.1 skrll
171 1.1 skrll if ((pos + offset + name.name_len) > len)
172 1.1 skrll return -1;
173 1.1 skrll
174 1.1 skrll namebuf = bfd_alloc (abfd, name.name_len + 1);
175 1.1 skrll if (namebuf == NULL)
176 1.1 skrll return -1;
177 1.1 skrll
178 1.1 skrll memcpy (namebuf, buf + pos + offset, name.name_len);
179 1.1 skrll namebuf[name.name_len] = '\0';
180 1.1 skrll
181 1.1 skrll /* Strip leading period inserted by compiler. */
182 1.1 skrll if (namebuf[0] == '.')
183 1.1.1.10 christos memmove (namebuf, namebuf + 1, name.name_len);
184 1.1 skrll
185 1.1 skrll sym->name = namebuf;
186 1.1 skrll
187 1.1 skrll for (s = sym->name; (*s != '\0'); s++)
188 1.1 skrll if (! ISPRINT (*s))
189 1.1 skrll return -1;
190 1.1 skrll
191 1.1 skrll offset += name.name_len;
192 1.1 skrll }
193 1.1 skrll
194 1.1 skrll if (table.flags2 & TB_USES_ALLOCA)
195 1.1 skrll offset += 4;
196 1.1 skrll
197 1.1 skrll if (table.flags4 & TB_HAS_VEC_INFO)
198 1.1 skrll offset += 4;
199 1.1 skrll
200 1.1 skrll if (file != NULL)
201 1.1 skrll fprintf (file, " [length = 0x%lx]", (unsigned long) offset);
202 1.1 skrll
203 1.1 skrll return offset;
204 1.1 skrll }
205 1.1 skrll
206 1.1 skrll static void
207 1.1 skrll bfd_pef_print_symbol (bfd *abfd,
208 1.1 skrll void * afile,
209 1.1 skrll asymbol *symbol,
210 1.1 skrll bfd_print_symbol_type how)
211 1.1 skrll {
212 1.1 skrll FILE *file = (FILE *) afile;
213 1.1.1.11 christos const char *symname = (symbol->name != bfd_symbol_error_name
214 1.1.1.11 christos ? symbol->name : _("<corrupt>"));
215 1.1 skrll
216 1.1 skrll switch (how)
217 1.1 skrll {
218 1.1 skrll case bfd_print_symbol_name:
219 1.1.1.11 christos fprintf (file, "%s", symname);
220 1.1 skrll break;
221 1.1 skrll default:
222 1.1 skrll bfd_print_symbol_vandf (abfd, (void *) file, symbol);
223 1.1.1.11 christos fprintf (file, " %-5s %s", symbol->section->name, symname);
224 1.1.1.11 christos if (startswith (symname, "__traceback_"))
225 1.1 skrll {
226 1.1.1.8 christos unsigned char *buf;
227 1.1 skrll size_t offset = symbol->value + 4;
228 1.1 skrll size_t len = symbol->udata.i;
229 1.1 skrll
230 1.1.1.8 christos buf = bfd_malloc (len);
231 1.1.1.8 christos if (buf == NULL
232 1.1.1.8 christos || !bfd_get_section_contents (abfd, symbol->section, buf,
233 1.1.1.8 christos offset, len)
234 1.1.1.8 christos || bfd_pef_parse_traceback_table (abfd, symbol->section, buf,
235 1.1.1.8 christos len, 0, NULL, file) < 0)
236 1.1 skrll fprintf (file, " [ERROR]");
237 1.1.1.5 christos free (buf);
238 1.1 skrll }
239 1.1 skrll }
240 1.1 skrll }
241 1.1 skrll
242 1.1 skrll static void
243 1.1 skrll bfd_pef_convert_architecture (unsigned long architecture,
244 1.1 skrll enum bfd_architecture *type,
245 1.1 skrll unsigned long *subtype)
246 1.1 skrll {
247 1.1 skrll const unsigned long ARCH_POWERPC = 0x70777063; /* 'pwpc'. */
248 1.1 skrll const unsigned long ARCH_M68K = 0x6d36386b; /* 'm68k'. */
249 1.1 skrll
250 1.1 skrll *subtype = bfd_arch_unknown;
251 1.1 skrll *type = bfd_arch_unknown;
252 1.1 skrll
253 1.1 skrll if (architecture == ARCH_POWERPC)
254 1.1 skrll *type = bfd_arch_powerpc;
255 1.1 skrll else if (architecture == ARCH_M68K)
256 1.1 skrll *type = bfd_arch_m68k;
257 1.1 skrll }
258 1.1 skrll
259 1.1.1.9 christos static bool
260 1.1 skrll bfd_pef_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
261 1.1 skrll {
262 1.1.1.9 christos return true;
263 1.1 skrll }
264 1.1 skrll
265 1.1 skrll static const char *bfd_pef_section_name (bfd_pef_section *section)
266 1.1 skrll {
267 1.1 skrll switch (section->section_kind)
268 1.1 skrll {
269 1.1 skrll case BFD_PEF_SECTION_CODE: return "code";
270 1.1 skrll case BFD_PEF_SECTION_UNPACKED_DATA: return "unpacked-data";
271 1.1 skrll case BFD_PEF_SECTION_PACKED_DATA: return "packed-data";
272 1.1 skrll case BFD_PEF_SECTION_CONSTANT: return "constant";
273 1.1 skrll case BFD_PEF_SECTION_LOADER: return "loader";
274 1.1 skrll case BFD_PEF_SECTION_DEBUG: return "debug";
275 1.1 skrll case BFD_PEF_SECTION_EXEC_DATA: return "exec-data";
276 1.1 skrll case BFD_PEF_SECTION_EXCEPTION: return "exception";
277 1.1 skrll case BFD_PEF_SECTION_TRACEBACK: return "traceback";
278 1.1 skrll default: return "unknown";
279 1.1 skrll }
280 1.1 skrll }
281 1.1 skrll
282 1.1 skrll static unsigned long bfd_pef_section_flags (bfd_pef_section *section)
283 1.1 skrll {
284 1.1 skrll switch (section->section_kind)
285 1.1 skrll {
286 1.1 skrll case BFD_PEF_SECTION_CODE:
287 1.1 skrll return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
288 1.1 skrll case BFD_PEF_SECTION_UNPACKED_DATA:
289 1.1 skrll case BFD_PEF_SECTION_PACKED_DATA:
290 1.1 skrll case BFD_PEF_SECTION_CONSTANT:
291 1.1 skrll case BFD_PEF_SECTION_LOADER:
292 1.1 skrll case BFD_PEF_SECTION_DEBUG:
293 1.1 skrll case BFD_PEF_SECTION_EXEC_DATA:
294 1.1 skrll case BFD_PEF_SECTION_EXCEPTION:
295 1.1 skrll case BFD_PEF_SECTION_TRACEBACK:
296 1.1 skrll default:
297 1.1 skrll return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
298 1.1 skrll }
299 1.1 skrll }
300 1.1 skrll
301 1.1 skrll static asection *
302 1.1 skrll bfd_pef_make_bfd_section (bfd *abfd, bfd_pef_section *section)
303 1.1 skrll {
304 1.1 skrll asection *bfdsec;
305 1.1 skrll const char *name = bfd_pef_section_name (section);
306 1.1 skrll
307 1.1 skrll bfdsec = bfd_make_section_anyway (abfd, name);
308 1.1 skrll if (bfdsec == NULL)
309 1.1 skrll return NULL;
310 1.1 skrll
311 1.1 skrll bfdsec->vma = section->default_address + section->container_offset;
312 1.1 skrll bfdsec->lma = section->default_address + section->container_offset;
313 1.1 skrll bfdsec->size = section->container_length;
314 1.1 skrll bfdsec->filepos = section->container_offset;
315 1.1 skrll bfdsec->alignment_power = section->alignment;
316 1.1 skrll
317 1.1 skrll bfdsec->flags = bfd_pef_section_flags (section);
318 1.1 skrll
319 1.1 skrll return bfdsec;
320 1.1 skrll }
321 1.1 skrll
322 1.1 skrll int
323 1.1 skrll bfd_pef_parse_loader_header (bfd *abfd ATTRIBUTE_UNUSED,
324 1.1 skrll unsigned char *buf,
325 1.1 skrll size_t len,
326 1.1 skrll bfd_pef_loader_header *header)
327 1.1 skrll {
328 1.1 skrll BFD_ASSERT (len == 56);
329 1.1 skrll
330 1.1 skrll header->main_section = bfd_getb32 (buf);
331 1.1 skrll header->main_offset = bfd_getb32 (buf + 4);
332 1.1 skrll header->init_section = bfd_getb32 (buf + 8);
333 1.1 skrll header->init_offset = bfd_getb32 (buf + 12);
334 1.1 skrll header->term_section = bfd_getb32 (buf + 16);
335 1.1 skrll header->term_offset = bfd_getb32 (buf + 20);
336 1.1 skrll header->imported_library_count = bfd_getb32 (buf + 24);
337 1.1 skrll header->total_imported_symbol_count = bfd_getb32 (buf + 28);
338 1.1 skrll header->reloc_section_count = bfd_getb32 (buf + 32);
339 1.1 skrll header->reloc_instr_offset = bfd_getb32 (buf + 36);
340 1.1 skrll header->loader_strings_offset = bfd_getb32 (buf + 40);
341 1.1 skrll header->export_hash_offset = bfd_getb32 (buf + 44);
342 1.1 skrll header->export_hash_table_power = bfd_getb32 (buf + 48);
343 1.1 skrll header->exported_symbol_count = bfd_getb32 (buf + 52);
344 1.1 skrll
345 1.1 skrll return 0;
346 1.1 skrll }
347 1.1 skrll
348 1.1 skrll int
349 1.1 skrll bfd_pef_parse_imported_library (bfd *abfd ATTRIBUTE_UNUSED,
350 1.1 skrll unsigned char *buf,
351 1.1 skrll size_t len,
352 1.1 skrll bfd_pef_imported_library *header)
353 1.1 skrll {
354 1.1 skrll BFD_ASSERT (len == 24);
355 1.1 skrll
356 1.1 skrll header->name_offset = bfd_getb32 (buf);
357 1.1 skrll header->old_implementation_version = bfd_getb32 (buf + 4);
358 1.1 skrll header->current_version = bfd_getb32 (buf + 8);
359 1.1 skrll header->imported_symbol_count = bfd_getb32 (buf + 12);
360 1.1 skrll header->first_imported_symbol = bfd_getb32 (buf + 16);
361 1.1 skrll header->options = buf[20];
362 1.1 skrll header->reserved_a = buf[21];
363 1.1 skrll header->reserved_b = bfd_getb16 (buf + 22);
364 1.1 skrll
365 1.1 skrll return 0;
366 1.1 skrll }
367 1.1 skrll
368 1.1 skrll int
369 1.1 skrll bfd_pef_parse_imported_symbol (bfd *abfd ATTRIBUTE_UNUSED,
370 1.1 skrll unsigned char *buf,
371 1.1 skrll size_t len,
372 1.1 skrll bfd_pef_imported_symbol *symbol)
373 1.1 skrll {
374 1.1 skrll unsigned long value;
375 1.1 skrll
376 1.1 skrll BFD_ASSERT (len == 4);
377 1.1 skrll
378 1.1 skrll value = bfd_getb32 (buf);
379 1.1.1.2 christos symbol->symbol_class = value >> 24;
380 1.1 skrll symbol->name = value & 0x00ffffff;
381 1.1 skrll
382 1.1 skrll return 0;
383 1.1 skrll }
384 1.1 skrll
385 1.1 skrll int
386 1.1 skrll bfd_pef_scan_section (bfd *abfd, bfd_pef_section *section)
387 1.1 skrll {
388 1.1 skrll unsigned char buf[28];
389 1.1 skrll
390 1.1.1.10 christos if (bfd_seek (abfd, section->header_offset, SEEK_SET) != 0
391 1.1.1.10 christos || bfd_read (buf, 28, abfd) != 28)
392 1.1 skrll return -1;
393 1.1 skrll
394 1.1 skrll section->name_offset = bfd_h_get_32 (abfd, buf);
395 1.1 skrll section->default_address = bfd_h_get_32 (abfd, buf + 4);
396 1.1 skrll section->total_length = bfd_h_get_32 (abfd, buf + 8);
397 1.1 skrll section->unpacked_length = bfd_h_get_32 (abfd, buf + 12);
398 1.1 skrll section->container_length = bfd_h_get_32 (abfd, buf + 16);
399 1.1 skrll section->container_offset = bfd_h_get_32 (abfd, buf + 20);
400 1.1 skrll section->section_kind = buf[24];
401 1.1 skrll section->share_kind = buf[25];
402 1.1 skrll section->alignment = buf[26];
403 1.1 skrll section->reserved = buf[27];
404 1.1 skrll
405 1.1 skrll section->bfd_section = bfd_pef_make_bfd_section (abfd, section);
406 1.1 skrll if (section->bfd_section == NULL)
407 1.1 skrll return -1;
408 1.1 skrll
409 1.1 skrll return 0;
410 1.1 skrll }
411 1.1 skrll
412 1.1 skrll void
413 1.1 skrll bfd_pef_print_loader_header (bfd *abfd ATTRIBUTE_UNUSED,
414 1.1 skrll bfd_pef_loader_header *header,
415 1.1 skrll FILE *file)
416 1.1 skrll {
417 1.1 skrll fprintf (file, "main_section: %ld\n", header->main_section);
418 1.1 skrll fprintf (file, "main_offset: %lu\n", header->main_offset);
419 1.1 skrll fprintf (file, "init_section: %ld\n", header->init_section);
420 1.1 skrll fprintf (file, "init_offset: %lu\n", header->init_offset);
421 1.1 skrll fprintf (file, "term_section: %ld\n", header->term_section);
422 1.1 skrll fprintf (file, "term_offset: %lu\n", header->term_offset);
423 1.1 skrll fprintf (file, "imported_library_count: %lu\n",
424 1.1 skrll header->imported_library_count);
425 1.1 skrll fprintf (file, "total_imported_symbol_count: %lu\n",
426 1.1 skrll header->total_imported_symbol_count);
427 1.1 skrll fprintf (file, "reloc_section_count: %lu\n", header->reloc_section_count);
428 1.1 skrll fprintf (file, "reloc_instr_offset: %lu\n", header->reloc_instr_offset);
429 1.1 skrll fprintf (file, "loader_strings_offset: %lu\n",
430 1.1 skrll header->loader_strings_offset);
431 1.1 skrll fprintf (file, "export_hash_offset: %lu\n", header->export_hash_offset);
432 1.1 skrll fprintf (file, "export_hash_table_power: %lu\n",
433 1.1 skrll header->export_hash_table_power);
434 1.1 skrll fprintf (file, "exported_symbol_count: %lu\n",
435 1.1 skrll header->exported_symbol_count);
436 1.1 skrll }
437 1.1 skrll
438 1.1 skrll int
439 1.1 skrll bfd_pef_print_loader_section (bfd *abfd, FILE *file)
440 1.1 skrll {
441 1.1 skrll bfd_pef_loader_header header;
442 1.1 skrll asection *loadersec = NULL;
443 1.1 skrll unsigned char *loaderbuf = NULL;
444 1.1 skrll size_t loaderlen = 0;
445 1.1 skrll
446 1.1 skrll loadersec = bfd_get_section_by_name (abfd, "loader");
447 1.1 skrll if (loadersec == NULL)
448 1.1 skrll return -1;
449 1.1 skrll
450 1.1 skrll loaderlen = loadersec->size;
451 1.1.1.9 christos if (loaderlen < 56)
452 1.1.1.9 christos return -1;
453 1.1.1.9 christos if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) != 0)
454 1.1.1.9 christos return -1;
455 1.1.1.9 christos loaderbuf = _bfd_malloc_and_read (abfd, loaderlen, loaderlen);
456 1.1.1.8 christos if (loaderbuf == NULL)
457 1.1.1.8 christos return -1;
458 1.1 skrll
459 1.1.1.9 christos if (bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header) < 0)
460 1.1 skrll {
461 1.1 skrll free (loaderbuf);
462 1.1 skrll return -1;
463 1.1 skrll }
464 1.1 skrll
465 1.1 skrll bfd_pef_print_loader_header (abfd, &header, file);
466 1.1 skrll return 0;
467 1.1 skrll }
468 1.1 skrll
469 1.1 skrll int
470 1.1 skrll bfd_pef_scan_start_address (bfd *abfd)
471 1.1 skrll {
472 1.1 skrll bfd_pef_loader_header header;
473 1.1 skrll asection *section;
474 1.1 skrll
475 1.1 skrll asection *loadersec = NULL;
476 1.1 skrll unsigned char *loaderbuf = NULL;
477 1.1 skrll size_t loaderlen = 0;
478 1.1 skrll int ret;
479 1.1 skrll
480 1.1 skrll loadersec = bfd_get_section_by_name (abfd, "loader");
481 1.1 skrll if (loadersec == NULL)
482 1.1 skrll goto end;
483 1.1 skrll
484 1.1 skrll loaderlen = loadersec->size;
485 1.1.1.9 christos if (loaderlen < 56)
486 1.1.1.11 christos goto wrong;
487 1.1.1.9 christos if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) != 0)
488 1.1 skrll goto error;
489 1.1.1.9 christos loaderbuf = _bfd_malloc_and_read (abfd, loaderlen, loaderlen);
490 1.1.1.9 christos if (loaderbuf == NULL)
491 1.1 skrll goto error;
492 1.1.1.9 christos
493 1.1 skrll ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
494 1.1 skrll if (ret < 0)
495 1.1.1.11 christos goto wrong;
496 1.1 skrll
497 1.1 skrll if (header.main_section < 0)
498 1.1 skrll goto end;
499 1.1 skrll
500 1.1 skrll for (section = abfd->sections; section != NULL; section = section->next)
501 1.1.1.4 christos if ((long) (section->index + 1) == header.main_section)
502 1.1 skrll break;
503 1.1 skrll
504 1.1 skrll if (section == NULL)
505 1.1.1.11 christos goto wrong;
506 1.1 skrll
507 1.1 skrll abfd->start_address = section->vma + header.main_offset;
508 1.1 skrll
509 1.1 skrll end:
510 1.1.1.9 christos free (loaderbuf);
511 1.1 skrll return 0;
512 1.1 skrll
513 1.1.1.11 christos wrong:
514 1.1.1.11 christos bfd_set_error (bfd_error_wrong_format);
515 1.1 skrll error:
516 1.1.1.9 christos free (loaderbuf);
517 1.1 skrll return -1;
518 1.1 skrll }
519 1.1 skrll
520 1.1 skrll int
521 1.1.1.3 christos bfd_pef_scan (bfd *abfd,
522 1.1.1.3 christos bfd_pef_header *header,
523 1.1.1.3 christos bfd_pef_data_struct *mdata)
524 1.1 skrll {
525 1.1 skrll unsigned int i;
526 1.1 skrll enum bfd_architecture cputype;
527 1.1 skrll unsigned long cpusubtype;
528 1.1 skrll
529 1.1 skrll mdata->header = *header;
530 1.1 skrll
531 1.1 skrll bfd_pef_convert_architecture (header->architecture, &cputype, &cpusubtype);
532 1.1 skrll if (cputype == bfd_arch_unknown)
533 1.1 skrll {
534 1.1.1.6 christos _bfd_error_handler (_("bfd_pef_scan: unknown architecture 0x%lx"),
535 1.1.1.6 christos header->architecture);
536 1.1 skrll return -1;
537 1.1 skrll }
538 1.1 skrll bfd_set_arch_mach (abfd, cputype, cpusubtype);
539 1.1 skrll
540 1.1 skrll mdata->header = *header;
541 1.1 skrll
542 1.1 skrll abfd->flags = (abfd->xvec->object_flags
543 1.1 skrll | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
544 1.1 skrll
545 1.1 skrll if (header->section_count != 0)
546 1.1 skrll {
547 1.1 skrll mdata->sections = bfd_alloc (abfd, header->section_count * sizeof (bfd_pef_section));
548 1.1 skrll
549 1.1 skrll if (mdata->sections == NULL)
550 1.1 skrll return -1;
551 1.1 skrll
552 1.1 skrll for (i = 0; i < header->section_count; i++)
553 1.1 skrll {
554 1.1 skrll bfd_pef_section *cur = &mdata->sections[i];
555 1.1 skrll cur->header_offset = 40 + (i * 28);
556 1.1 skrll if (bfd_pef_scan_section (abfd, cur) < 0)
557 1.1 skrll return -1;
558 1.1 skrll }
559 1.1 skrll }
560 1.1 skrll
561 1.1 skrll if (bfd_pef_scan_start_address (abfd) < 0)
562 1.1 skrll return -1;
563 1.1 skrll
564 1.1 skrll return 0;
565 1.1 skrll }
566 1.1 skrll
567 1.1 skrll static int
568 1.1 skrll bfd_pef_read_header (bfd *abfd, bfd_pef_header *header)
569 1.1 skrll {
570 1.1 skrll unsigned char buf[40];
571 1.1 skrll
572 1.1.1.10 christos if (bfd_seek (abfd, 0, SEEK_SET) != 0
573 1.1.1.10 christos || bfd_read (buf, 40, abfd) != 40)
574 1.1 skrll return -1;
575 1.1 skrll
576 1.1 skrll header->tag1 = bfd_getb32 (buf);
577 1.1 skrll header->tag2 = bfd_getb32 (buf + 4);
578 1.1 skrll header->architecture = bfd_getb32 (buf + 8);
579 1.1 skrll header->format_version = bfd_getb32 (buf + 12);
580 1.1 skrll header->timestamp = bfd_getb32 (buf + 16);
581 1.1 skrll header->old_definition_version = bfd_getb32 (buf + 20);
582 1.1 skrll header->old_implementation_version = bfd_getb32 (buf + 24);
583 1.1 skrll header->current_version = bfd_getb32 (buf + 28);
584 1.1 skrll header->section_count = bfd_getb32 (buf + 32) + 1;
585 1.1 skrll header->instantiated_section_count = bfd_getb32 (buf + 34);
586 1.1 skrll header->reserved = bfd_getb32 (buf + 36);
587 1.1 skrll
588 1.1 skrll return 0;
589 1.1 skrll }
590 1.1 skrll
591 1.1.1.9 christos static bfd_cleanup
592 1.1 skrll bfd_pef_object_p (bfd *abfd)
593 1.1 skrll {
594 1.1 skrll bfd_pef_header header;
595 1.1.1.4 christos bfd_pef_data_struct *mdata;
596 1.1 skrll
597 1.1 skrll if (bfd_pef_read_header (abfd, &header) != 0)
598 1.1.1.11 christos return NULL;
599 1.1 skrll
600 1.1 skrll if (header.tag1 != BFD_PEF_TAG1 || header.tag2 != BFD_PEF_TAG2)
601 1.1.1.11 christos {
602 1.1.1.11 christos bfd_set_error (bfd_error_wrong_format);
603 1.1.1.11 christos return NULL;
604 1.1.1.11 christos }
605 1.1 skrll
606 1.1.1.4 christos mdata = (bfd_pef_data_struct *) bfd_zalloc (abfd, sizeof (*mdata));
607 1.1.1.4 christos if (mdata == NULL)
608 1.1.1.11 christos return NULL;
609 1.1 skrll
610 1.1.1.4 christos if (bfd_pef_scan (abfd, &header, mdata))
611 1.1.1.11 christos {
612 1.1.1.11 christos bfd_release (abfd, mdata);
613 1.1.1.11 christos return NULL;
614 1.1.1.11 christos }
615 1.1 skrll
616 1.1.1.11 christos abfd->tdata.pef_data = mdata;
617 1.1.1.9 christos return _bfd_no_cleanup;
618 1.1 skrll }
619 1.1 skrll
620 1.1 skrll static int
621 1.1 skrll bfd_pef_parse_traceback_tables (bfd *abfd,
622 1.1 skrll asection *sec,
623 1.1 skrll unsigned char *buf,
624 1.1 skrll size_t len,
625 1.1 skrll long *nsym,
626 1.1 skrll asymbol **csym)
627 1.1 skrll {
628 1.1 skrll char *name;
629 1.1 skrll
630 1.1 skrll asymbol function;
631 1.1 skrll asymbol traceback;
632 1.1 skrll
633 1.1 skrll const char *const tbprefix = "__traceback_";
634 1.1 skrll size_t tbnamelen;
635 1.1 skrll
636 1.1 skrll size_t pos = 0;
637 1.1 skrll unsigned long count = 0;
638 1.1 skrll int ret;
639 1.1 skrll
640 1.1 skrll for (;;)
641 1.1 skrll {
642 1.1 skrll /* We're reading symbols two at a time. */
643 1.1 skrll if (csym && ((csym[count] == NULL) || (csym[count + 1] == NULL)))
644 1.1 skrll break;
645 1.1 skrll
646 1.1 skrll pos += 3;
647 1.1 skrll pos -= (pos % 4);
648 1.1 skrll
649 1.1 skrll while ((pos + 4) <= len)
650 1.1 skrll {
651 1.1 skrll if (bfd_getb32 (buf + pos) == 0)
652 1.1 skrll break;
653 1.1 skrll pos += 4;
654 1.1 skrll }
655 1.1 skrll
656 1.1 skrll if ((pos + 4) > len)
657 1.1 skrll break;
658 1.1 skrll
659 1.1 skrll ret = bfd_pef_parse_traceback_table (abfd, sec, buf, len, pos + 4,
660 1.1 skrll &function, 0);
661 1.1 skrll if (ret < 0)
662 1.1 skrll {
663 1.1 skrll /* Skip over 0x0L to advance to next possible traceback table. */
664 1.1 skrll pos += 4;
665 1.1 skrll continue;
666 1.1 skrll }
667 1.1 skrll
668 1.1 skrll BFD_ASSERT (function.name != NULL);
669 1.1 skrll
670 1.1 skrll /* Don't bother to compute the name if we are just
671 1.1 skrll counting symbols. */
672 1.1 skrll if (csym)
673 1.1 skrll {
674 1.1 skrll tbnamelen = strlen (tbprefix) + strlen (function.name);
675 1.1 skrll name = bfd_alloc (abfd, tbnamelen + 1);
676 1.1 skrll if (name == NULL)
677 1.1 skrll {
678 1.1 skrll bfd_release (abfd, (void *) function.name);
679 1.1 skrll function.name = NULL;
680 1.1 skrll break;
681 1.1 skrll }
682 1.1 skrll snprintf (name, tbnamelen + 1, "%s%s", tbprefix, function.name);
683 1.1 skrll traceback.name = name;
684 1.1 skrll traceback.value = pos;
685 1.1 skrll traceback.the_bfd = abfd;
686 1.1 skrll traceback.section = sec;
687 1.1 skrll traceback.flags = 0;
688 1.1 skrll traceback.udata.i = ret;
689 1.1 skrll
690 1.1 skrll *(csym[count]) = function;
691 1.1 skrll *(csym[count + 1]) = traceback;
692 1.1 skrll }
693 1.1 skrll
694 1.1 skrll pos += ret;
695 1.1 skrll count += 2;
696 1.1 skrll }
697 1.1 skrll
698 1.1 skrll *nsym = count;
699 1.1 skrll return 0;
700 1.1 skrll }
701 1.1 skrll
702 1.1 skrll static int
703 1.1 skrll bfd_pef_parse_function_stub (bfd *abfd ATTRIBUTE_UNUSED,
704 1.1 skrll unsigned char *buf,
705 1.1 skrll size_t len,
706 1.1 skrll unsigned long *offset)
707 1.1 skrll {
708 1.1 skrll BFD_ASSERT (len == 24);
709 1.1 skrll
710 1.1 skrll if ((bfd_getb32 (buf) & 0xffff0000) != 0x81820000)
711 1.1 skrll return -1;
712 1.1 skrll if (bfd_getb32 (buf + 4) != 0x90410014)
713 1.1 skrll return -1;
714 1.1 skrll if (bfd_getb32 (buf + 8) != 0x800c0000)
715 1.1 skrll return -1;
716 1.1 skrll if (bfd_getb32 (buf + 12) != 0x804c0004)
717 1.1 skrll return -1;
718 1.1 skrll if (bfd_getb32 (buf + 16) != 0x7c0903a6)
719 1.1 skrll return -1;
720 1.1 skrll if (bfd_getb32 (buf + 20) != 0x4e800420)
721 1.1 skrll return -1;
722 1.1 skrll
723 1.1 skrll if (offset != NULL)
724 1.1 skrll *offset = (bfd_getb32 (buf) & 0x0000ffff) / 4;
725 1.1 skrll
726 1.1 skrll return 0;
727 1.1 skrll }
728 1.1 skrll
729 1.1 skrll static int
730 1.1 skrll bfd_pef_parse_function_stubs (bfd *abfd,
731 1.1 skrll asection *codesec,
732 1.1 skrll unsigned char *codebuf,
733 1.1 skrll size_t codelen,
734 1.1 skrll unsigned char *loaderbuf,
735 1.1 skrll size_t loaderlen,
736 1.1 skrll unsigned long *nsym,
737 1.1 skrll asymbol **csym)
738 1.1 skrll {
739 1.1 skrll const char *const sprefix = "__stub_";
740 1.1 skrll size_t codepos = 0;
741 1.1 skrll unsigned long count = 0;
742 1.1 skrll bfd_pef_loader_header header;
743 1.1 skrll bfd_pef_imported_library *libraries = NULL;
744 1.1 skrll bfd_pef_imported_symbol *imports = NULL;
745 1.1 skrll unsigned long i;
746 1.1 skrll int ret;
747 1.1 skrll
748 1.1 skrll if (loaderlen < 56)
749 1.1 skrll goto error;
750 1.1 skrll
751 1.1 skrll ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
752 1.1 skrll if (ret < 0)
753 1.1 skrll goto error;
754 1.1 skrll
755 1.1.1.10 christos if ((loaderlen - 56) / 24 < header.imported_library_count)
756 1.1.1.10 christos goto error;
757 1.1.1.10 christos
758 1.1.1.10 christos if ((loaderlen - 56 - header.imported_library_count * 24) / 4
759 1.1.1.10 christos < header.total_imported_symbol_count)
760 1.1.1.10 christos goto error;
761 1.1.1.10 christos
762 1.1 skrll libraries = bfd_malloc
763 1.1 skrll (header.imported_library_count * sizeof (bfd_pef_imported_library));
764 1.1 skrll imports = bfd_malloc
765 1.1 skrll (header.total_imported_symbol_count * sizeof (bfd_pef_imported_symbol));
766 1.1.1.8 christos if (libraries == NULL || imports == NULL)
767 1.1.1.8 christos goto error;
768 1.1 skrll
769 1.1 skrll for (i = 0; i < header.imported_library_count; i++)
770 1.1 skrll {
771 1.1 skrll ret = bfd_pef_parse_imported_library
772 1.1 skrll (abfd, loaderbuf + 56 + (i * 24), 24, &libraries[i]);
773 1.1 skrll if (ret < 0)
774 1.1 skrll goto error;
775 1.1 skrll }
776 1.1 skrll
777 1.1 skrll for (i = 0; i < header.total_imported_symbol_count; i++)
778 1.1 skrll {
779 1.1 skrll ret = (bfd_pef_parse_imported_symbol
780 1.1 skrll (abfd,
781 1.1 skrll loaderbuf + 56 + (header.imported_library_count * 24) + (i * 4),
782 1.1 skrll 4, &imports[i]));
783 1.1 skrll if (ret < 0)
784 1.1 skrll goto error;
785 1.1 skrll }
786 1.1 skrll
787 1.1 skrll codepos = 0;
788 1.1 skrll
789 1.1 skrll for (;;)
790 1.1 skrll {
791 1.1 skrll asymbol sym;
792 1.1 skrll const char *symname;
793 1.1 skrll char *name;
794 1.1.1.2 christos unsigned long sym_index;
795 1.1 skrll
796 1.1 skrll if (csym && (csym[count] == NULL))
797 1.1 skrll break;
798 1.1 skrll
799 1.1 skrll codepos += 3;
800 1.1 skrll codepos -= (codepos % 4);
801 1.1 skrll
802 1.1 skrll while ((codepos + 4) <= codelen)
803 1.1 skrll {
804 1.1 skrll if ((bfd_getb32 (codebuf + codepos) & 0xffff0000) == 0x81820000)
805 1.1 skrll break;
806 1.1 skrll codepos += 4;
807 1.1 skrll }
808 1.1 skrll
809 1.1.1.8 christos if ((codepos + 24) > codelen)
810 1.1 skrll break;
811 1.1 skrll
812 1.1.1.2 christos ret = bfd_pef_parse_function_stub (abfd, codebuf + codepos, 24, &sym_index);
813 1.1 skrll if (ret < 0)
814 1.1 skrll {
815 1.1 skrll codepos += 24;
816 1.1 skrll continue;
817 1.1 skrll }
818 1.1 skrll
819 1.1.1.2 christos if (sym_index >= header.total_imported_symbol_count)
820 1.1 skrll {
821 1.1 skrll codepos += 24;
822 1.1 skrll continue;
823 1.1 skrll }
824 1.1 skrll
825 1.1 skrll {
826 1.1 skrll size_t max, namelen;
827 1.1 skrll const char *s;
828 1.1 skrll
829 1.1.1.2 christos if (loaderlen < (header.loader_strings_offset + imports[sym_index].name))
830 1.1 skrll goto error;
831 1.1 skrll
832 1.1.1.2 christos max = loaderlen - (header.loader_strings_offset + imports[sym_index].name);
833 1.1 skrll symname = (char *) loaderbuf;
834 1.1.1.2 christos symname += header.loader_strings_offset + imports[sym_index].name;
835 1.1 skrll namelen = 0;
836 1.1 skrll for (s = symname; s < (symname + max); s++)
837 1.1 skrll {
838 1.1 skrll if (*s == '\0')
839 1.1 skrll break;
840 1.1 skrll if (! ISPRINT (*s))
841 1.1 skrll goto error;
842 1.1 skrll namelen++;
843 1.1 skrll }
844 1.1 skrll if (*s != '\0')
845 1.1 skrll goto error;
846 1.1 skrll
847 1.1 skrll name = bfd_alloc (abfd, strlen (sprefix) + namelen + 1);
848 1.1 skrll if (name == NULL)
849 1.1 skrll break;
850 1.1 skrll
851 1.1 skrll snprintf (name, strlen (sprefix) + namelen + 1, "%s%s",
852 1.1 skrll sprefix, symname);
853 1.1 skrll sym.name = name;
854 1.1 skrll }
855 1.1 skrll
856 1.1 skrll sym.value = codepos;
857 1.1 skrll sym.the_bfd = abfd;
858 1.1 skrll sym.section = codesec;
859 1.1 skrll sym.flags = 0;
860 1.1 skrll sym.udata.i = 0;
861 1.1 skrll
862 1.1 skrll codepos += 24;
863 1.1 skrll
864 1.1 skrll if (csym != NULL)
865 1.1 skrll *(csym[count]) = sym;
866 1.1 skrll
867 1.1 skrll count++;
868 1.1 skrll }
869 1.1 skrll
870 1.1 skrll goto end;
871 1.1 skrll
872 1.1 skrll end:
873 1.1.1.9 christos free (libraries);
874 1.1.1.9 christos free (imports);
875 1.1 skrll *nsym = count;
876 1.1 skrll return 0;
877 1.1 skrll
878 1.1 skrll error:
879 1.1.1.9 christos free (libraries);
880 1.1.1.9 christos free (imports);
881 1.1 skrll *nsym = count;
882 1.1 skrll return -1;
883 1.1 skrll }
884 1.1 skrll
885 1.1 skrll static long
886 1.1 skrll bfd_pef_parse_symbols (bfd *abfd, asymbol **csym)
887 1.1 skrll {
888 1.1 skrll unsigned long count = 0;
889 1.1 skrll
890 1.1 skrll asection *codesec = NULL;
891 1.1 skrll unsigned char *codebuf = NULL;
892 1.1 skrll size_t codelen = 0;
893 1.1 skrll
894 1.1 skrll asection *loadersec = NULL;
895 1.1 skrll unsigned char *loaderbuf = NULL;
896 1.1 skrll size_t loaderlen = 0;
897 1.1 skrll
898 1.1 skrll codesec = bfd_get_section_by_name (abfd, "code");
899 1.1 skrll if (codesec != NULL)
900 1.1 skrll {
901 1.1 skrll codelen = codesec->size;
902 1.1.1.9 christos if (bfd_seek (abfd, codesec->filepos, SEEK_SET) != 0)
903 1.1 skrll goto end;
904 1.1.1.9 christos codebuf = _bfd_malloc_and_read (abfd, codelen, codelen);
905 1.1.1.9 christos if (codebuf == NULL)
906 1.1 skrll goto end;
907 1.1 skrll }
908 1.1 skrll
909 1.1 skrll loadersec = bfd_get_section_by_name (abfd, "loader");
910 1.1 skrll if (loadersec != NULL)
911 1.1 skrll {
912 1.1 skrll loaderlen = loadersec->size;
913 1.1.1.9 christos if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) != 0)
914 1.1.1.8 christos goto end;
915 1.1.1.9 christos loaderbuf = _bfd_malloc_and_read (abfd, loaderlen, loaderlen);
916 1.1.1.9 christos if (loaderbuf == NULL)
917 1.1 skrll goto end;
918 1.1 skrll }
919 1.1 skrll
920 1.1 skrll count = 0;
921 1.1 skrll if (codesec != NULL)
922 1.1 skrll {
923 1.1 skrll long ncount = 0;
924 1.1 skrll bfd_pef_parse_traceback_tables (abfd, codesec, codebuf, codelen,
925 1.1 skrll &ncount, csym);
926 1.1 skrll count += ncount;
927 1.1 skrll }
928 1.1 skrll
929 1.1 skrll if ((codesec != NULL) && (loadersec != NULL))
930 1.1 skrll {
931 1.1 skrll unsigned long ncount = 0;
932 1.1 skrll bfd_pef_parse_function_stubs
933 1.1 skrll (abfd, codesec, codebuf, codelen, loaderbuf, loaderlen, &ncount,
934 1.1 skrll (csym != NULL) ? (csym + count) : NULL);
935 1.1 skrll count += ncount;
936 1.1 skrll }
937 1.1 skrll
938 1.1 skrll if (csym != NULL)
939 1.1 skrll csym[count] = NULL;
940 1.1 skrll
941 1.1 skrll end:
942 1.1.1.9 christos free (codebuf);
943 1.1.1.9 christos free (loaderbuf);
944 1.1 skrll return count;
945 1.1 skrll }
946 1.1 skrll
947 1.1 skrll static long
948 1.1 skrll bfd_pef_count_symbols (bfd *abfd)
949 1.1 skrll {
950 1.1 skrll return bfd_pef_parse_symbols (abfd, NULL);
951 1.1 skrll }
952 1.1 skrll
953 1.1 skrll static long
954 1.1 skrll bfd_pef_get_symtab_upper_bound (bfd *abfd)
955 1.1 skrll {
956 1.1 skrll long nsyms = bfd_pef_count_symbols (abfd);
957 1.1 skrll
958 1.1 skrll if (nsyms < 0)
959 1.1 skrll return nsyms;
960 1.1 skrll return ((nsyms + 1) * sizeof (asymbol *));
961 1.1 skrll }
962 1.1 skrll
963 1.1 skrll static long
964 1.1 skrll bfd_pef_canonicalize_symtab (bfd *abfd, asymbol **alocation)
965 1.1 skrll {
966 1.1 skrll long i;
967 1.1 skrll asymbol *syms;
968 1.1 skrll long ret;
969 1.1 skrll long nsyms = bfd_pef_count_symbols (abfd);
970 1.1 skrll
971 1.1 skrll if (nsyms < 0)
972 1.1 skrll return nsyms;
973 1.1 skrll
974 1.1 skrll syms = bfd_alloc (abfd, nsyms * sizeof (asymbol));
975 1.1 skrll if (syms == NULL)
976 1.1 skrll return -1;
977 1.1 skrll
978 1.1 skrll for (i = 0; i < nsyms; i++)
979 1.1 skrll alocation[i] = &syms[i];
980 1.1 skrll
981 1.1 skrll alocation[nsyms] = NULL;
982 1.1 skrll
983 1.1 skrll ret = bfd_pef_parse_symbols (abfd, alocation);
984 1.1 skrll if (ret != nsyms)
985 1.1 skrll return 0;
986 1.1 skrll
987 1.1 skrll return ret;
988 1.1 skrll }
989 1.1 skrll
990 1.1 skrll #define bfd_pef_make_empty_symbol _bfd_generic_make_empty_symbol
991 1.1 skrll
992 1.1 skrll static void
993 1.1 skrll bfd_pef_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
994 1.1 skrll asymbol *symbol,
995 1.1 skrll symbol_info *ret)
996 1.1 skrll {
997 1.1 skrll bfd_symbol_info (symbol, ret);
998 1.1 skrll }
999 1.1 skrll
1000 1.1 skrll static int
1001 1.1 skrll bfd_pef_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1002 1.1 skrll struct bfd_link_info *info ATTRIBUTE_UNUSED)
1003 1.1 skrll {
1004 1.1 skrll return 0;
1005 1.1 skrll }
1006 1.1 skrll
1007 1.1 skrll const bfd_target pef_vec =
1008 1.1 skrll {
1009 1.1 skrll "pef", /* Name. */
1010 1.1 skrll bfd_target_pef_flavour, /* Flavour. */
1011 1.1 skrll BFD_ENDIAN_BIG, /* Byteorder. */
1012 1.1 skrll BFD_ENDIAN_BIG, /* Header_byteorder. */
1013 1.1 skrll (HAS_RELOC | EXEC_P | /* Object flags. */
1014 1.1 skrll HAS_LINENO | HAS_DEBUG |
1015 1.1 skrll HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1016 1.1 skrll (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
1017 1.1 skrll | SEC_ROM | SEC_HAS_CONTENTS), /* Section_flags. */
1018 1.1 skrll 0, /* Symbol_leading_char. */
1019 1.1 skrll ' ', /* AR_pad_char. */
1020 1.1 skrll 16, /* AR_max_namelen. */
1021 1.1.1.3 christos 0, /* match priority. */
1022 1.1.1.9 christos TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
1023 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1024 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1025 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
1026 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1027 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1028 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
1029 1.1 skrll { /* bfd_check_format. */
1030 1.1 skrll _bfd_dummy_target,
1031 1.1 skrll bfd_pef_object_p, /* bfd_check_format. */
1032 1.1 skrll _bfd_dummy_target,
1033 1.1 skrll _bfd_dummy_target,
1034 1.1 skrll },
1035 1.1 skrll { /* bfd_set_format. */
1036 1.1.1.7 christos _bfd_bool_bfd_false_error,
1037 1.1 skrll bfd_pef_mkobject,
1038 1.1.1.7 christos _bfd_bool_bfd_false_error,
1039 1.1.1.7 christos _bfd_bool_bfd_false_error,
1040 1.1 skrll },
1041 1.1 skrll { /* bfd_write_contents. */
1042 1.1.1.7 christos _bfd_bool_bfd_false_error,
1043 1.1.1.7 christos _bfd_bool_bfd_true,
1044 1.1.1.7 christos _bfd_bool_bfd_false_error,
1045 1.1.1.7 christos _bfd_bool_bfd_false_error,
1046 1.1 skrll },
1047 1.1 skrll
1048 1.1 skrll BFD_JUMP_TABLE_GENERIC (bfd_pef),
1049 1.1 skrll BFD_JUMP_TABLE_COPY (_bfd_generic),
1050 1.1 skrll BFD_JUMP_TABLE_CORE (_bfd_nocore),
1051 1.1 skrll BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1052 1.1 skrll BFD_JUMP_TABLE_SYMBOLS (bfd_pef),
1053 1.1 skrll BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1054 1.1 skrll BFD_JUMP_TABLE_WRITE (bfd_pef),
1055 1.1 skrll BFD_JUMP_TABLE_LINK (bfd_pef),
1056 1.1 skrll BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1057 1.1 skrll
1058 1.1 skrll NULL,
1059 1.1 skrll
1060 1.1 skrll NULL
1061 1.1 skrll };
1062 1.1 skrll
1063 1.1.1.6 christos #define bfd_pef_xlib_close_and_cleanup _bfd_generic_close_and_cleanup
1064 1.1.1.6 christos #define bfd_pef_xlib_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1065 1.1.1.6 christos #define bfd_pef_xlib_new_section_hook _bfd_generic_new_section_hook
1066 1.1.1.6 christos #define bfd_pef_xlib_get_section_contents _bfd_generic_get_section_contents
1067 1.1.1.6 christos #define bfd_pef_xlib_set_section_contents _bfd_generic_set_section_contents
1068 1.1 skrll #define bfd_pef_xlib_set_section_contents_in_window _bfd_generic_set_section_contents_in_window
1069 1.1 skrll
1070 1.1 skrll static int
1071 1.1 skrll bfd_pef_xlib_read_header (bfd *abfd, bfd_pef_xlib_header *header)
1072 1.1 skrll {
1073 1.1.1.4 christos unsigned char buf[80];
1074 1.1 skrll
1075 1.1.1.10 christos if (bfd_seek (abfd, 0, SEEK_SET) != 0
1076 1.1.1.10 christos || bfd_read (buf, sizeof buf, abfd) != sizeof buf)
1077 1.1 skrll return -1;
1078 1.1 skrll
1079 1.1 skrll header->tag1 = bfd_getb32 (buf);
1080 1.1 skrll header->tag2 = bfd_getb32 (buf + 4);
1081 1.1 skrll header->current_format = bfd_getb32 (buf + 8);
1082 1.1 skrll header->container_strings_offset = bfd_getb32 (buf + 12);
1083 1.1 skrll header->export_hash_offset = bfd_getb32 (buf + 16);
1084 1.1 skrll header->export_key_offset = bfd_getb32 (buf + 20);
1085 1.1 skrll header->export_symbol_offset = bfd_getb32 (buf + 24);
1086 1.1 skrll header->export_names_offset = bfd_getb32 (buf + 28);
1087 1.1 skrll header->export_hash_table_power = bfd_getb32 (buf + 32);
1088 1.1 skrll header->exported_symbol_count = bfd_getb32 (buf + 36);
1089 1.1 skrll header->frag_name_offset = bfd_getb32 (buf + 40);
1090 1.1 skrll header->frag_name_length = bfd_getb32 (buf + 44);
1091 1.1 skrll header->dylib_path_offset = bfd_getb32 (buf + 48);
1092 1.1 skrll header->dylib_path_length = bfd_getb32 (buf + 52);
1093 1.1 skrll header->cpu_family = bfd_getb32 (buf + 56);
1094 1.1 skrll header->cpu_model = bfd_getb32 (buf + 60);
1095 1.1 skrll header->date_time_stamp = bfd_getb32 (buf + 64);
1096 1.1 skrll header->current_version = bfd_getb32 (buf + 68);
1097 1.1 skrll header->old_definition_version = bfd_getb32 (buf + 72);
1098 1.1 skrll header->old_implementation_version = bfd_getb32 (buf + 76);
1099 1.1 skrll
1100 1.1 skrll return 0;
1101 1.1 skrll }
1102 1.1 skrll
1103 1.1 skrll static int
1104 1.1 skrll bfd_pef_xlib_scan (bfd *abfd, bfd_pef_xlib_header *header)
1105 1.1 skrll {
1106 1.1 skrll bfd_pef_xlib_data_struct *mdata = NULL;
1107 1.1 skrll
1108 1.1 skrll mdata = bfd_alloc (abfd, sizeof (* mdata));
1109 1.1 skrll if (mdata == NULL)
1110 1.1 skrll return -1;
1111 1.1 skrll
1112 1.1 skrll mdata->header = *header;
1113 1.1 skrll
1114 1.1 skrll abfd->flags = (abfd->xvec->object_flags
1115 1.1 skrll | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
1116 1.1 skrll
1117 1.1 skrll abfd->tdata.pef_xlib_data = mdata;
1118 1.1 skrll
1119 1.1 skrll return 0;
1120 1.1 skrll }
1121 1.1 skrll
1122 1.1.1.9 christos static bfd_cleanup
1123 1.1 skrll bfd_pef_xlib_object_p (bfd *abfd)
1124 1.1 skrll {
1125 1.1 skrll bfd_pef_xlib_header header;
1126 1.1 skrll
1127 1.1.1.11 christos if (bfd_pef_xlib_read_header (abfd, &header) != 0
1128 1.1.1.11 christos || header.tag1 != BFD_PEF_XLIB_TAG1
1129 1.1.1.11 christos || (header.tag2 != BFD_PEF_VLIB_TAG2
1130 1.1.1.11 christos && header.tag2 != BFD_PEF_BLIB_TAG2))
1131 1.1 skrll {
1132 1.1.1.11 christos if (bfd_get_error () != bfd_error_system_call)
1133 1.1.1.11 christos bfd_set_error (bfd_error_wrong_format);
1134 1.1 skrll return NULL;
1135 1.1 skrll }
1136 1.1 skrll
1137 1.1 skrll if (bfd_pef_xlib_scan (abfd, &header) != 0)
1138 1.1.1.11 christos return NULL;
1139 1.1 skrll
1140 1.1.1.9 christos return _bfd_no_cleanup;
1141 1.1 skrll }
1142 1.1 skrll
1143 1.1 skrll const bfd_target pef_xlib_vec =
1144 1.1 skrll {
1145 1.1 skrll "pef-xlib", /* Name. */
1146 1.1 skrll bfd_target_pef_xlib_flavour, /* Flavour. */
1147 1.1 skrll BFD_ENDIAN_BIG, /* Byteorder */
1148 1.1 skrll BFD_ENDIAN_BIG, /* Header_byteorder. */
1149 1.1 skrll (HAS_RELOC | EXEC_P | /* Object flags. */
1150 1.1 skrll HAS_LINENO | HAS_DEBUG |
1151 1.1 skrll HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1152 1.1 skrll (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
1153 1.1 skrll | SEC_ROM | SEC_HAS_CONTENTS),/* Section_flags. */
1154 1.1 skrll 0, /* Symbol_leading_char. */
1155 1.1 skrll ' ', /* AR_pad_char. */
1156 1.1 skrll 16, /* AR_max_namelen. */
1157 1.1.1.3 christos 0, /* match priority. */
1158 1.1.1.9 christos TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
1159 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1160 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1161 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
1162 1.1 skrll bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1163 1.1 skrll bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1164 1.1 skrll bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
1165 1.1 skrll { /* bfd_check_format. */
1166 1.1 skrll _bfd_dummy_target,
1167 1.1 skrll bfd_pef_xlib_object_p, /* bfd_check_format. */
1168 1.1 skrll _bfd_dummy_target,
1169 1.1 skrll _bfd_dummy_target,
1170 1.1 skrll },
1171 1.1 skrll { /* bfd_set_format. */
1172 1.1.1.7 christos _bfd_bool_bfd_false_error,
1173 1.1 skrll bfd_pef_mkobject,
1174 1.1.1.7 christos _bfd_bool_bfd_false_error,
1175 1.1.1.7 christos _bfd_bool_bfd_false_error,
1176 1.1 skrll },
1177 1.1 skrll { /* bfd_write_contents. */
1178 1.1.1.7 christos _bfd_bool_bfd_false_error,
1179 1.1.1.7 christos _bfd_bool_bfd_true,
1180 1.1.1.7 christos _bfd_bool_bfd_false_error,
1181 1.1.1.7 christos _bfd_bool_bfd_false_error,
1182 1.1 skrll },
1183 1.1 skrll
1184 1.1 skrll BFD_JUMP_TABLE_GENERIC (bfd_pef_xlib),
1185 1.1 skrll BFD_JUMP_TABLE_COPY (_bfd_generic),
1186 1.1 skrll BFD_JUMP_TABLE_CORE (_bfd_nocore),
1187 1.1 skrll BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1188 1.1 skrll BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
1189 1.1 skrll BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1190 1.1 skrll BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
1191 1.1 skrll BFD_JUMP_TABLE_LINK (_bfd_nolink),
1192 1.1 skrll BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1193 1.1 skrll
1194 1.1 skrll NULL,
1195 1.1 skrll
1196 1.1 skrll NULL
1197 1.1 skrll };
1198