xref: /openbsd-src/gnu/usr.bin/binutils/bfd/pef.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
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