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