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