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