bfd/ 2008-09-03 Tristan Gingold Add MacOSX 64 bits support. * mach-o.h (bfd_mach_o_ppc_thread_flavour): Add BFD_MACH_O_PPC_THREAD_STATE_64. (bfd_mach_o_i386_thread_flavour): Add BFD_MACH_O_x86_THREAD_STATE64, BFD_MACH_O_x86_FLOAT_STATE64, BFD_MACH_O_x86_EXCEPTION_STATE64, BFD_MACH_O_x86_THREAD_STATE, BFD_MACH_O_x86_FLOAT_STATE, BFD_MACH_O_x86_EXCEPTION_STATE. (bfd_mach_o_load_command_type): Add BFD_MACH_O_LC_SEGMENT_64, BFD_MACH_O_LC_ROUTINES_64, BFD_MACH_O_LC_UUID. (BFD_MACH_O_CPU_IS64BIT): Added. (bfd_mach_o_cpu_type): Add BFD_MACH_O_CPU_TYPE_POWERPC_64, BFD_MACH_O_CPU_TYPE_X86_64. (bfd_mach_o_header): Add version field. (bfd_mach_o_section) Add reserved3 field. (bfd_mach_o_segment_command): Add initprot and maxprot fields. * mach-o.c (N_TEXT, N_DATA, N_BSS): Added. (bfd_mach_o_version): New function. (bfd_mach_o_valid): Handle 64bits cpus. (bfd_mach_o_write_header): handler 64bits headers. (bfd_mach_o_scan_write_section_32, bfd_mach_o_scan_write_section_64): New functions (from bfd_mach_o_scan_write_section) to handle both flavors. (bfd_mach_o_scan_write_segment): Parameter wide added to support both flavors. (bfd_mach_o_write_contents): Support both flavors. (bfd_mach_o_read_header): Ditto. (bfd_mach_o_scan_read_section_32, bfd_mach_o_scan_read_section_64): New functions (from bfd_mach_o_scan_read_section) to support both flavors. (bfd_mach_o_scan_read_symtab_symbol): Support both flavors. (bfd_mach_o_scan_read_symtab): Ditto. (bfd_mach_o_scan_read_segment): Parameter wide added to support both flavors. (bfd_mach_o_scan_read_segment_32, bfd_mach_o_scan_read_segment_64): New functions to call bfd_mach_o_scan_read_segment. (bfd_mach_o_flatten_sections): Support both flavors. (bfd_mach_o_scan_start_address): Ditto. (bfd_mach_o_scan): Ditto. (bfd_mach_o_lookup_section): Ditto. *** bfd/mach-o.c 30 Jul 2008 04:34:56 -0000 1.28 --- bfd/mach-o.c 3 Sep 2008 10:03:41 -0000 *************** *** 97,107 **** --- 97,122 ---- #define N_STAB 0xe0 #define N_TYPE 0x1e #define N_EXT 0x01 + #define N_UNDF 0x0 #define N_ABS 0x2 + #define N_TEXT 0x4 + #define N_DATA 0x6 + #define N_BSS 0x8 #define N_SECT 0xe #define N_INDR 0xa + static unsigned int + bfd_mach_o_version (bfd *abfd) + { + bfd_mach_o_data_struct *mdata = NULL; + + BFD_ASSERT (bfd_mach_o_valid (abfd)); + mdata = abfd->tdata.mach_o_data; + + return mdata->header.version; + } + bfd_boolean bfd_mach_o_valid (bfd *abfd) { *************** *** 264,295 **** { case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break; case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break; ! case BFD_MACH_O_CPU_TYPE_I386: *type = bfd_arch_i386; break; case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break; case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break; case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break; case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break; case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break; ! case BFD_MACH_O_CPU_TYPE_SPARC: *type = bfd_arch_sparc; break; case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break; case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break; ! case BFD_MACH_O_CPU_TYPE_POWERPC: *type = bfd_arch_powerpc; break; ! default: *type = bfd_arch_unknown; break; ! } ! ! switch (*type) ! { ! case bfd_arch_i386: *subtype = bfd_mach_i386_i386; break; ! case bfd_arch_sparc: *subtype = bfd_mach_sparc; break; default: ! *subtype = bfd_arch_unknown; } } static int bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header) { ! unsigned char buf[28]; bfd_h_put_32 (abfd, header->magic, buf + 0); bfd_h_put_32 (abfd, header->cputype, buf + 4); --- 279,324 ---- { case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break; case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break; ! case BFD_MACH_O_CPU_TYPE_I386: ! *type = bfd_arch_i386; ! *subtype = bfd_mach_i386_i386; ! break; ! case BFD_MACH_O_CPU_TYPE_X86_64: ! *type = bfd_arch_i386; ! *subtype = bfd_mach_x86_64; ! break; case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break; case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break; case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break; case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break; case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break; ! case BFD_MACH_O_CPU_TYPE_SPARC: ! *type = bfd_arch_sparc; ! *subtype = bfd_mach_sparc; ! break; case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break; case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break; ! case BFD_MACH_O_CPU_TYPE_POWERPC: ! *type = bfd_arch_powerpc; ! *subtype = bfd_mach_ppc; ! break; ! case BFD_MACH_O_CPU_TYPE_POWERPC_64: ! *type = bfd_arch_powerpc; ! *subtype = bfd_mach_ppc64; ! break; default: ! *type = bfd_arch_unknown; ! break; } } static int bfd_mach_o_write_header (bfd *abfd, bfd_mach_o_header *header) { ! unsigned char buf[32]; ! unsigned int size; ! ! size = (header->version == 2) ? 32 : 28; bfd_h_put_32 (abfd, header->magic, buf + 0); bfd_h_put_32 (abfd, header->cputype, buf + 4); *************** *** 299,314 **** bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20); bfd_h_put_32 (abfd, header->flags, buf + 24); bfd_seek (abfd, 0, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, 28, abfd) != 28) return -1; return 0; } static int ! bfd_mach_o_scan_write_thread (bfd *abfd, ! bfd_mach_o_load_command *command) { bfd_mach_o_thread_command *cmd = &command->command.thread; unsigned int i; --- 328,345 ---- bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20); bfd_h_put_32 (abfd, header->flags, buf + 24); + if (header->version == 2) + bfd_h_put_32 (abfd, header->reserved, buf + 28); + bfd_seek (abfd, 0, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, size, abfd) != size) return -1; return 0; } static int ! bfd_mach_o_scan_write_thread (bfd *abfd, bfd_mach_o_load_command *command) { bfd_mach_o_thread_command *cmd = &command->command.thread; unsigned int i; *************** *** 340,348 **** } static int ! bfd_mach_o_scan_write_section (bfd *abfd, ! bfd_mach_o_section *section, ! bfd_vma offset) { unsigned char buf[68]; --- 371,379 ---- } static int ! bfd_mach_o_scan_write_section_32 (bfd *abfd, ! bfd_mach_o_section *section, ! bfd_vma offset) { unsigned char buf[68]; *************** *** 355,362 **** bfd_h_put_32 (abfd, section->reloff, buf + 48); bfd_h_put_32 (abfd, section->nreloc, buf + 52); bfd_h_put_32 (abfd, section->flags, buf + 56); ! /* bfd_h_put_32 (abfd, section->reserved1, buf + 60); */ ! /* bfd_h_put_32 (abfd, section->reserved2, buf + 64); */ bfd_seek (abfd, offset, SEEK_SET); if (bfd_bwrite ((PTR) buf, 68, abfd) != 68) --- 386,393 ---- bfd_h_put_32 (abfd, section->reloff, buf + 48); bfd_h_put_32 (abfd, section->nreloc, buf + 52); bfd_h_put_32 (abfd, section->flags, buf + 56); ! bfd_h_put_32 (abfd, section->reserved1, buf + 60); ! bfd_h_put_32 (abfd, section->reserved2, buf + 64); bfd_seek (abfd, offset, SEEK_SET); if (bfd_bwrite ((PTR) buf, 68, abfd) != 68) *************** *** 366,392 **** } static int ! bfd_mach_o_scan_write_segment (bfd *abfd, bfd_mach_o_load_command *command) { ! unsigned char buf[48]; bfd_mach_o_segment_command *seg = &command->command.segment; unsigned long i; ! BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT); ! memcpy (buf, seg->segname, 16); ! bfd_h_put_32 (abfd, seg->vmaddr, buf + 16); ! bfd_h_put_32 (abfd, seg->vmsize, buf + 20); ! bfd_h_put_32 (abfd, seg->fileoff, buf + 24); ! bfd_h_put_32 (abfd, seg->filesize, buf + 28); ! bfd_h_put_32 (abfd, 0 /* seg->maxprot */, buf + 32); ! bfd_h_put_32 (abfd, 0 /* seg->initprot */, buf + 36); ! bfd_h_put_32 (abfd, seg->nsects, buf + 40); ! bfd_h_put_32 (abfd, seg->flags, buf + 44); ! bfd_seek (abfd, command->offset + 8, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, 48, abfd) != 48) ! return -1; { char buf[1024]; --- 397,487 ---- } static int ! bfd_mach_o_scan_write_section_64 (bfd *abfd, ! bfd_mach_o_section *section, ! bfd_vma offset) { ! unsigned char buf[80]; ! ! memcpy (buf, section->sectname, 16); ! memcpy (buf + 16, section->segname, 16); ! bfd_h_put_64 (abfd, section->addr, buf + 32); ! bfd_h_put_64 (abfd, section->size, buf + 40); ! bfd_h_put_32 (abfd, section->offset, buf + 48); ! bfd_h_put_32 (abfd, section->align, buf + 52); ! bfd_h_put_32 (abfd, section->reloff, buf + 56); ! bfd_h_put_32 (abfd, section->nreloc, buf + 60); ! bfd_h_put_32 (abfd, section->flags, buf + 64); ! bfd_h_put_32 (abfd, section->reserved1, buf + 68); ! bfd_h_put_32 (abfd, section->reserved2, buf + 72); ! bfd_h_put_32 (abfd, section->reserved3, buf + 76); ! ! bfd_seek (abfd, offset, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, 80, abfd) != 80) ! return -1; ! ! return 0; ! } ! ! static int ! bfd_mach_o_scan_write_section (bfd *abfd, ! bfd_mach_o_section *section, ! bfd_vma offset, ! unsigned int wide) ! { ! if (wide) ! return bfd_mach_o_scan_write_section_64 (abfd, section, offset); ! else ! return bfd_mach_o_scan_write_section_32 (abfd, section, offset); ! } ! ! static int ! bfd_mach_o_scan_write_segment (bfd *abfd, ! bfd_mach_o_load_command *command, ! unsigned int wide) ! { ! unsigned char buf[64]; bfd_mach_o_segment_command *seg = &command->command.segment; unsigned long i; ! if (wide) ! { ! BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64); ! ! memcpy (buf, seg->segname, 16); ! ! bfd_h_put_64 (abfd, seg->vmaddr, buf + 16); ! bfd_h_put_64 (abfd, seg->vmsize, buf + 24); ! bfd_h_put_64 (abfd, seg->fileoff, buf + 32); ! bfd_h_put_64 (abfd, seg->filesize, buf + 40); ! bfd_h_put_32 (abfd, seg->maxprot, buf + 48); ! bfd_h_put_32 (abfd, seg->initprot, buf + 52); ! bfd_h_put_32 (abfd, seg->nsects, buf + 56); ! bfd_h_put_32 (abfd, seg->flags, buf + 60); ! bfd_seek (abfd, command->offset + 8, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, 64, abfd) != 64) ! return -1; ! } ! else ! { ! BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT); ! ! memcpy (buf, seg->segname, 16); ! ! bfd_h_put_32 (abfd, seg->vmaddr, buf + 16); ! bfd_h_put_32 (abfd, seg->vmsize, buf + 20); ! bfd_h_put_32 (abfd, seg->fileoff, buf + 24); ! bfd_h_put_32 (abfd, seg->filesize, buf + 28); ! bfd_h_put_32 (abfd, seg->maxprot, buf + 32); ! bfd_h_put_32 (abfd, seg->initprot, buf + 36); ! bfd_h_put_32 (abfd, seg->nsects, buf + 40); ! bfd_h_put_32 (abfd, seg->flags, buf + 44); ! bfd_seek (abfd, command->offset + 8, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, 48, abfd) != 48) ! return -1; ! } { char buf[1024]; *************** *** 395,423 **** while (nbytes > 0) { ! bfd_vma thisread = nbytes; ! if (thisread > 1024) ! thisread = 1024; bfd_seek (abfd, curoff, SEEK_SET); ! if (bfd_bread ((PTR) buf, thisread, abfd) != thisread) return -1; bfd_seek (abfd, curoff, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, thisread, abfd) != thisread) return -1; ! nbytes -= thisread; ! curoff += thisread; } } for (i = 0; i < seg->nsects; i++) { ! bfd_vma segoff = command->offset + 48 + 8 + (i * 68); ! if (bfd_mach_o_scan_write_section (abfd, &seg->sections[i], segoff) != 0) return -1; } --- 490,523 ---- while (nbytes > 0) { ! bfd_vma thiswrite = nbytes; ! if (thiswrite > 1024) ! thiswrite = 1024; bfd_seek (abfd, curoff, SEEK_SET); ! if (bfd_bread ((PTR) buf, thiswrite, abfd) != thiswrite) return -1; bfd_seek (abfd, curoff, SEEK_SET); ! if (bfd_bwrite ((PTR) buf, thiswrite, abfd) != thiswrite) return -1; ! nbytes -= thiswrite; ! curoff += thiswrite; } } for (i = 0; i < seg->nsects; i++) { ! bfd_vma segoff; ! if (wide) ! segoff = command->offset + 64 + 8 + (i * 80); ! else ! segoff = command->offset + 48 + 8 + (i * 68); ! if (bfd_mach_o_scan_write_section ! (abfd, &seg->sections[i], segoff, wide) != 0) return -1; } *************** *** 425,432 **** } static int ! bfd_mach_o_scan_write_symtab_symbols (bfd *abfd, ! bfd_mach_o_load_command *command) { bfd_mach_o_symtab_command *sym = &command->command.symtab; asymbol *s = NULL; --- 525,543 ---- } static int ! bfd_mach_o_scan_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command) ! { ! return bfd_mach_o_scan_write_segment (abfd, command, 0); ! } ! ! static int ! bfd_mach_o_scan_write_segment_64 (bfd *abfd, bfd_mach_o_load_command *command) ! { ! return bfd_mach_o_scan_write_segment (abfd, command, 1); ! } ! ! static int ! bfd_mach_o_scan_write_symtab_symbols (bfd *abfd, bfd_mach_o_load_command *command) { bfd_mach_o_symtab_command *sym = &command->command.symtab; asymbol *s = NULL; *************** *** 524,530 **** switch (cur->type) { case BFD_MACH_O_LC_SEGMENT: ! if (bfd_mach_o_scan_write_segment (abfd, cur) != 0) return FALSE; break; case BFD_MACH_O_LC_SYMTAB: --- 635,645 ---- switch (cur->type) { case BFD_MACH_O_LC_SEGMENT: ! if (bfd_mach_o_scan_write_segment_32 (abfd, cur) != 0) ! return FALSE; ! break; ! case BFD_MACH_O_LC_SEGMENT_64: ! if (bfd_mach_o_scan_write_segment_64 (abfd, cur) != 0) return FALSE; break; case BFD_MACH_O_LC_SYMTAB: *************** *** 589,612 **** static int bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header) { ! unsigned char buf[28]; bfd_vma (*get32) (const void *) = NULL; bfd_seek (abfd, 0, SEEK_SET); ! if (bfd_bread ((PTR) buf, 28, abfd) != 28) return -1; if (bfd_getb32 (buf) == 0xfeedface) { header->byteorder = BFD_ENDIAN_BIG; header->magic = 0xfeedface; get32 = bfd_getb32; } else if (bfd_getl32 (buf) == 0xfeedface) { header->byteorder = BFD_ENDIAN_LITTLE; header->magic = 0xfeedface; get32 = bfd_getl32; } else --- 704,745 ---- static int bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header) { ! unsigned char buf[32]; ! unsigned int size; bfd_vma (*get32) (const void *) = NULL; bfd_seek (abfd, 0, SEEK_SET); ! /* Just read the magic number. */ ! if (bfd_bread ((PTR) buf, 4, abfd) != 4) return -1; if (bfd_getb32 (buf) == 0xfeedface) { header->byteorder = BFD_ENDIAN_BIG; header->magic = 0xfeedface; + header->version = 1; get32 = bfd_getb32; } else if (bfd_getl32 (buf) == 0xfeedface) { header->byteorder = BFD_ENDIAN_LITTLE; header->magic = 0xfeedface; + header->version = 1; + get32 = bfd_getl32; + } + else if (bfd_getb32 (buf) == 0xfeedfacf) + { + header->byteorder = BFD_ENDIAN_BIG; + header->magic = 0xfeedfacf; + header->version = 2; + get32 = bfd_getb32; + } + else if (bfd_getl32 (buf) == 0xfeedfacf) + { + header->byteorder = BFD_ENDIAN_LITTLE; + header->magic = 0xfeedfacf; + header->version = 2; get32 = bfd_getl32; } else *************** *** 615,620 **** --- 748,760 ---- return -1; } + /* Once the size of the header is known, read the full header. */ + size = (header->version == 2) ? 32 : 28; + + bfd_seek (abfd, 0, SEEK_SET); + if (bfd_bread ((PTR) buf, size, abfd) != size) + return -1; + header->cputype = (*get32) (buf + 4); header->cpusubtype = (*get32) (buf + 8); header->filetype = (*get32) (buf + 12); *************** *** 622,627 **** --- 762,770 ---- header->sizeofcmds = (*get32) (buf + 20); header->flags = (*get32) (buf + 24); + if (header->version == 2) + header->reserved = (*get32) (buf + 28); + return 0; } *************** *** 655,668 **** bfdsec->size = section->size; bfdsec->filepos = section->offset; bfdsec->alignment_power = section->align; return bfdsec; } static int ! bfd_mach_o_scan_read_section (bfd *abfd, ! bfd_mach_o_section *section, ! bfd_vma offset) { unsigned char buf[68]; --- 798,812 ---- bfdsec->size = section->size; bfdsec->filepos = section->offset; bfdsec->alignment_power = section->align; + bfdsec->segment_mark = 0; return bfdsec; } static int ! bfd_mach_o_scan_read_section_32 (bfd *abfd, ! bfd_mach_o_section *section, ! bfd_vma offset) { unsigned char buf[68]; *************** *** 683,688 **** --- 827,866 ---- section->flags = bfd_h_get_32 (abfd, buf + 56); section->reserved1 = bfd_h_get_32 (abfd, buf + 60); section->reserved2 = bfd_h_get_32 (abfd, buf + 64); + section->reserved3 = 0; + section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section); + + if (section->bfdsection == NULL) + return -1; + + return 0; + } + + static int + bfd_mach_o_scan_read_section_64 (bfd *abfd, + bfd_mach_o_section *section, + bfd_vma offset) + { + unsigned char buf[80]; + + bfd_seek (abfd, offset, SEEK_SET); + if (bfd_bread ((PTR) buf, 80, abfd) != 80) + return -1; + + memcpy (section->sectname, buf, 16); + section->sectname[16] = '\0'; + memcpy (section->segname, buf + 16, 16); + section->segname[16] = '\0'; + section->addr = bfd_h_get_64 (abfd, buf + 32); + section->size = bfd_h_get_64 (abfd, buf + 40); + section->offset = bfd_h_get_32 (abfd, buf + 48); + section->align = bfd_h_get_32 (abfd, buf + 52); + section->reloff = bfd_h_get_32 (abfd, buf + 56); + section->nreloc = bfd_h_get_32 (abfd, buf + 60); + section->flags = bfd_h_get_32 (abfd, buf + 64); + section->reserved1 = bfd_h_get_32 (abfd, buf + 68); + section->reserved2 = bfd_h_get_32 (abfd, buf + 72); + section->reserved3 = bfd_h_get_32 (abfd, buf + 76); section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section); if (section->bfdsection == NULL) *************** *** 691,696 **** --- 869,886 ---- return 0; } + static int + bfd_mach_o_scan_read_section (bfd *abfd, + bfd_mach_o_section *section, + bfd_vma offset, + unsigned int wide) + { + if (wide) + return bfd_mach_o_scan_read_section_64 (abfd, section, offset); + else + return bfd_mach_o_scan_read_section_32 (abfd, section, offset); + } + int bfd_mach_o_scan_read_symtab_symbol (bfd *abfd, bfd_mach_o_symtab_command *sym, *************** *** 698,719 **** unsigned long i) { bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data; ! bfd_vma symoff = sym->symoff + (i * 12); ! unsigned char buf[12]; unsigned char type = -1; unsigned char section = -1; short desc = -1; ! unsigned long value = -1; unsigned long stroff = -1; unsigned int symtype = -1; BFD_ASSERT (sym->strtab != NULL); bfd_seek (abfd, symoff, SEEK_SET); ! if (bfd_bread ((PTR) buf, 12, abfd) != 12) { fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n", ! 12, (unsigned long) symoff); return -1; } --- 888,911 ---- unsigned long i) { bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data; ! unsigned int wide = (mdata->header.version == 2); ! unsigned int symwidth = wide ? 16 : 12; ! bfd_vma symoff = sym->symoff + (i * symwidth); ! unsigned char buf[16]; unsigned char type = -1; unsigned char section = -1; short desc = -1; ! symvalue value = -1; unsigned long stroff = -1; unsigned int symtype = -1; BFD_ASSERT (sym->strtab != NULL); bfd_seek (abfd, symoff, SEEK_SET); ! if (bfd_bread ((PTR) buf, symwidth, abfd) != symwidth) { fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n", ! symwidth, (unsigned long) symoff); return -1; } *************** *** 722,728 **** symtype = (type & 0x0e); section = bfd_h_get_8 (abfd, buf + 5) - 1; desc = bfd_h_get_16 (abfd, buf + 6); ! value = bfd_h_get_32 (abfd, buf + 8); if (stroff >= sym->strsize) { --- 914,923 ---- symtype = (type & 0x0e); section = bfd_h_get_8 (abfd, buf + 5) - 1; desc = bfd_h_get_16 (abfd, buf + 6); ! if (wide) ! value = bfd_h_get_64 (abfd, buf + 8); ! else ! value = bfd_h_get_32 (abfd, buf + 8); if (stroff >= sym->strsize) { *************** *** 770,777 **** case BFD_MACH_O_N_SECT: if ((section > 0) && (section <= mdata->nsects)) { ! s->section = mdata->sections[section - 1]->bfdsection; ! s->value = s->value - mdata->sections[section - 1]->addr; } else { --- 965,972 ---- case BFD_MACH_O_N_SECT: if ((section > 0) && (section <= mdata->nsects)) { ! s->section = mdata->sections[section]->bfdsection; ! s->value = s->value - mdata->sections[section]->addr; } else { *************** *** 1114,1122 **** --- 1309,1319 ---- switch (mdata->header.cputype) { case BFD_MACH_O_CPU_TYPE_POWERPC: + case BFD_MACH_O_CPU_TYPE_POWERPC_64: flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour); break; case BFD_MACH_O_CPU_TYPE_I386: + case BFD_MACH_O_CPU_TYPE_X86_64: flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour); break; default: *************** *** 1193,1198 **** --- 1390,1396 ---- asection *bfdsec; char *sname; const char *prefix = "LC_SYMTAB.stabs"; + int nlist_size = (bfd_mach_o_version (abfd) > 1) ? 16 : 12; BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB); *************** *** 1218,1224 **** bfdsec->vma = 0; bfdsec->lma = 0; ! bfdsec->size = seg->nsyms * 12; bfdsec->filepos = seg->symoff; bfdsec->alignment_power = 0; --- 1416,1422 ---- bfdsec->vma = 0; bfdsec->lma = 0; ! bfdsec->size = seg->nsyms * nlist_size; bfdsec->filepos = seg->symoff; bfdsec->alignment_power = 0; *************** *** 1246,1277 **** } static int ! bfd_mach_o_scan_read_segment (bfd *abfd, bfd_mach_o_load_command *command) { ! unsigned char buf[48]; bfd_mach_o_segment_command *seg = &command->command.segment; unsigned long i; asection *bfdsec; char *sname; const char *prefix = "LC_SEGMENT"; unsigned int snamelen; - flagword flags; ! BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT); ! bfd_seek (abfd, command->offset + 8, SEEK_SET); ! if (bfd_bread ((PTR) buf, 48, abfd) != 48) ! return -1; ! memcpy (seg->segname, buf, 16); ! seg->vmaddr = bfd_h_get_32 (abfd, buf + 16); ! seg->vmsize = bfd_h_get_32 (abfd, buf + 20); ! seg->fileoff = bfd_h_get_32 (abfd, buf + 24); ! seg->filesize = bfd_h_get_32 (abfd, buf + 28); ! /* seg->maxprot = bfd_h_get_32 (abfd, buf + 32); */ ! /* seg->initprot = bfd_h_get_32 (abfd, buf + 36); */ ! seg->nsects = bfd_h_get_32 (abfd, buf + 40); ! seg->flags = bfd_h_get_32 (abfd, buf + 44); snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1; sname = bfd_alloc (abfd, snamelen); --- 1444,1499 ---- } static int ! bfd_mach_o_scan_read_segment (bfd *abfd, ! bfd_mach_o_load_command *command, ! unsigned int wide) { ! unsigned char buf[64]; bfd_mach_o_segment_command *seg = &command->command.segment; unsigned long i; asection *bfdsec; char *sname; const char *prefix = "LC_SEGMENT"; unsigned int snamelen; ! if (wide) ! { ! BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64); ! bfd_seek (abfd, command->offset + 8, SEEK_SET); ! if (bfd_bread ((PTR) buf, 64, abfd) != 64) ! return -1; ! ! memcpy (seg->segname, buf, 16); ! seg->vmaddr = bfd_h_get_64 (abfd, buf + 16); ! seg->vmsize = bfd_h_get_64 (abfd, buf + 24); ! seg->fileoff = bfd_h_get_64 (abfd, buf + 32); ! seg->filesize = bfd_h_get_64 (abfd, buf + 40); ! seg->maxprot = bfd_h_get_32 (abfd, buf + 48); ! seg->initprot = bfd_h_get_32 (abfd, buf + 52); ! seg->nsects = bfd_h_get_32 (abfd, buf + 56); ! seg->flags = bfd_h_get_32 (abfd, buf + 60); ! } ! else ! { ! BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT); ! ! bfd_seek (abfd, command->offset + 8, SEEK_SET); ! if (bfd_bread ((PTR) buf, 48, abfd) != 48) ! return -1; ! ! memcpy (seg->segname, buf, 16); ! ! seg->vmaddr = bfd_h_get_32 (abfd, buf + 16); ! seg->vmsize = bfd_h_get_32 (abfd, buf + 20); ! seg->fileoff = bfd_h_get_32 (abfd, buf + 24); ! seg->filesize = bfd_h_get_32 (abfd, buf + 28); ! seg->maxprot = bfd_h_get_32 (abfd, buf + 32); ! seg->initprot = bfd_h_get_32 (abfd, buf + 36); ! seg->nsects = bfd_h_get_32 (abfd, buf + 40); ! seg->flags = bfd_h_get_32 (abfd, buf + 44); ! } snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1; sname = bfd_alloc (abfd, snamelen); *************** *** 1279,1286 **** return -1; sprintf (sname, "%s.%s", prefix, seg->segname); ! flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE; ! bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags); if (bfdsec == NULL) return -1; --- 1501,1507 ---- return -1; sprintf (sname, "%s.%s", prefix, seg->segname); ! bfdsec = bfd_make_section_anyway (abfd, sname); if (bfdsec == NULL) return -1; *************** *** 1289,1294 **** --- 1510,1517 ---- bfdsec->size = seg->filesize; bfdsec->filepos = seg->fileoff; bfdsec->alignment_power = 0x0; + bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE; + bfdsec->segment_mark = 1; seg->segment = bfdsec; *************** *** 1300,1309 **** for (i = 0; i < seg->nsects; i++) { ! bfd_vma segoff = command->offset + 48 + 8 + (i * 68); ! if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i], ! segoff) != 0) return -1; } } --- 1523,1536 ---- for (i = 0; i < seg->nsects; i++) { ! bfd_vma segoff; ! if (wide) ! segoff = command->offset + 64 + 8 + (i * 80); ! else ! segoff = command->offset + 48 + 8 + (i * 68); ! if (bfd_mach_o_scan_read_section ! (abfd, &seg->sections[i], segoff, wide) != 0) return -1; } } *************** *** 1312,1317 **** --- 1539,1556 ---- } static int + bfd_mach_o_scan_read_segment_32 (bfd *abfd, bfd_mach_o_load_command *command) + { + return bfd_mach_o_scan_read_segment (abfd, command, 0); + } + + static int + bfd_mach_o_scan_read_segment_64 (bfd *abfd, bfd_mach_o_load_command *command) + { + return bfd_mach_o_scan_read_segment (abfd, command, 1); + } + + static int bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command) { unsigned char buf[8]; *************** *** 1328,1334 **** switch (command->type) { case BFD_MACH_O_LC_SEGMENT: ! if (bfd_mach_o_scan_read_segment (abfd, command) != 0) return -1; break; case BFD_MACH_O_LC_SYMTAB: --- 1567,1577 ---- switch (command->type) { case BFD_MACH_O_LC_SEGMENT: ! if (bfd_mach_o_scan_read_segment_32 (abfd, command) != 0) ! return -1; ! break; ! case BFD_MACH_O_LC_SEGMENT_64: ! if (bfd_mach_o_scan_read_segment_64 (abfd, command) != 0) return -1; break; case BFD_MACH_O_LC_SYMTAB: *************** *** 1395,1401 **** for (i = 0; i < mdata->header.ncmds; i++) { ! if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT) { bfd_mach_o_segment_command *seg; --- 1638,1645 ---- for (i = 0; i < mdata->header.ncmds; i++) { ! if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT ! || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64) { bfd_mach_o_segment_command *seg; *************** *** 1410,1416 **** for (i = 0; i < mdata->header.ncmds; i++) { ! if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT) { bfd_mach_o_segment_command *seg; --- 1654,1661 ---- for (i = 0; i < mdata->header.ncmds; i++) { ! if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT ! || mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT_64) { bfd_mach_o_segment_command *seg; *************** *** 1472,1477 **** --- 1717,1746 ---- abfd->start_address = bfd_h_get_32 (abfd, buf); } + else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64) + && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE_64)) + { + unsigned char buf[8]; + + bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET); + + if (bfd_bread (buf, 8, abfd) != 8) + return -1; + + abfd->start_address = bfd_h_get_64 (abfd, buf); + } + else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_X86_64) + && (cmd->flavours[i].flavour == BFD_MACH_O_x86_THREAD_STATE64)) + { + unsigned char buf[8]; + + bfd_seek (abfd, cmd->flavours[i].offset + (16 * 8), SEEK_SET); + + if (bfd_bread (buf, 8, abfd) != 8) + return -1; + + abfd->start_address = bfd_h_get_64 (abfd, buf); + } } return 0; *************** *** 1485,1490 **** --- 1754,1762 ---- unsigned int i; enum bfd_architecture cputype; unsigned long cpusubtype; + unsigned int hdrsize; + + hdrsize = (header->version == 2) ? 32 : 28; mdata->header = *header; mdata->symbols = NULL; *************** *** 1515,1521 **** bfd_mach_o_load_command *cur = &mdata->commands[i]; if (i == 0) ! cur->offset = 28; else { bfd_mach_o_load_command *prev = &mdata->commands[i - 1]; --- 1787,1793 ---- bfd_mach_o_load_command *cur = &mdata->commands[i]; if (i == 0) ! cur->offset = hdrsize; else { bfd_mach_o_load_command *prev = &mdata->commands[i - 1]; *************** *** 1804,1810 **** struct bfd_mach_o_load_command *cmd = &md->commands[i]; struct bfd_mach_o_segment_command *seg = NULL; ! if (cmd->type != BFD_MACH_O_LC_SEGMENT) continue; seg = &cmd->command.segment; --- 2076,2083 ---- struct bfd_mach_o_load_command *cmd = &md->commands[i]; struct bfd_mach_o_segment_command *seg = NULL; ! if (cmd->type != BFD_MACH_O_LC_SEGMENT ! || cmd->type != BFD_MACH_O_LC_SEGMENT_64) continue; seg = &cmd->command.segment; *** bfd/mach-o.h 3 Jul 2007 14:26:42 -0000 1.9 --- bfd/mach-o.h 3 Sep 2008 10:03:42 -0000 *************** *** 1,5 **** /* Mach-O support for BFD. ! Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. --- 1,5 ---- /* Mach-O support for BFD. ! Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. *************** *** 39,45 **** BFD_MACH_O_PPC_THREAD_STATE = 1, BFD_MACH_O_PPC_FLOAT_STATE = 2, BFD_MACH_O_PPC_EXCEPTION_STATE = 3, ! BFD_MACH_O_PPC_VECTOR_STATE = 4 } bfd_mach_o_ppc_thread_flavour; --- 39,46 ---- BFD_MACH_O_PPC_THREAD_STATE = 1, BFD_MACH_O_PPC_FLOAT_STATE = 2, BFD_MACH_O_PPC_EXCEPTION_STATE = 3, ! BFD_MACH_O_PPC_VECTOR_STATE = 4, ! BFD_MACH_O_PPC_THREAD_STATE_64 = 5 } bfd_mach_o_ppc_thread_flavour; *************** *** 51,62 **** BFD_MACH_O_i386_V86_ASSIST_STATE = 4, BFD_MACH_O_i386_REGS_SEGS_STATE = 5, BFD_MACH_O_i386_THREAD_SYSCALL_STATE = 6, - BFD_MACH_O_i386_THREAD_STATE_NONE = 7, BFD_MACH_O_i386_SAVED_STATE = 8, BFD_MACH_O_i386_THREAD_STATE = -1, BFD_MACH_O_i386_THREAD_FPSTATE = -2, BFD_MACH_O_i386_THREAD_EXCEPTSTATE = -3, BFD_MACH_O_i386_THREAD_CTHREADSTATE = -4, } bfd_mach_o_i386_thread_flavour; --- 52,69 ---- BFD_MACH_O_i386_V86_ASSIST_STATE = 4, BFD_MACH_O_i386_REGS_SEGS_STATE = 5, BFD_MACH_O_i386_THREAD_SYSCALL_STATE = 6, BFD_MACH_O_i386_SAVED_STATE = 8, BFD_MACH_O_i386_THREAD_STATE = -1, BFD_MACH_O_i386_THREAD_FPSTATE = -2, BFD_MACH_O_i386_THREAD_EXCEPTSTATE = -3, BFD_MACH_O_i386_THREAD_CTHREADSTATE = -4, + BFD_MACH_O_x86_THREAD_STATE64 = 4, + BFD_MACH_O_x86_FLOAT_STATE64 = 5, + BFD_MACH_O_x86_EXCEPTION_STATE64 = 6, + BFD_MACH_O_x86_THREAD_STATE = 7, + BFD_MACH_O_x86_FLOAT_STATE = 8, + BFD_MACH_O_x86_EXCEPTION_STATE = 9, + BFD_MACH_O_i386_THREAD_STATE_NONE = 10, } bfd_mach_o_i386_thread_flavour; *************** *** 89,98 **** BFD_MACH_O_LC_PREBIND_CKSUM = 0x17, /* Prebind checksum. */ /* Load a dynamically linked shared library that is allowed to be missing (weak). */ ! BFD_MACH_O_LC_LOAD_WEAK_DYLIB = 0x18 } bfd_mach_o_load_command_type; typedef enum bfd_mach_o_cpu_type { BFD_MACH_O_CPU_TYPE_VAX = 1, --- 96,112 ---- BFD_MACH_O_LC_PREBIND_CKSUM = 0x17, /* Prebind checksum. */ /* Load a dynamically linked shared library that is allowed to be missing (weak). */ ! BFD_MACH_O_LC_LOAD_WEAK_DYLIB = 0x18, ! BFD_MACH_O_LC_SEGMENT_64 = 0x19, /* 64-bit segment of this file to be ! mapped. */ ! BFD_MACH_O_LC_ROUTINES_64 = 0x1a, /* Address of the dyld init routine ! in a dylib. */ ! BFD_MACH_O_LC_UUID = 0x1b /* 128-bit UUID of the executable. */ } bfd_mach_o_load_command_type; + #define BFD_MACH_O_CPU_IS64BIT 0x1000000 + typedef enum bfd_mach_o_cpu_type { BFD_MACH_O_CPU_TYPE_VAX = 1, *************** *** 106,112 **** BFD_MACH_O_CPU_TYPE_SPARC = 14, BFD_MACH_O_CPU_TYPE_I860 = 15, BFD_MACH_O_CPU_TYPE_ALPHA = 16, ! BFD_MACH_O_CPU_TYPE_POWERPC = 18 } bfd_mach_o_cpu_type; --- 120,128 ---- BFD_MACH_O_CPU_TYPE_SPARC = 14, BFD_MACH_O_CPU_TYPE_I860 = 15, BFD_MACH_O_CPU_TYPE_ALPHA = 16, ! BFD_MACH_O_CPU_TYPE_POWERPC = 18, ! BFD_MACH_O_CPU_TYPE_POWERPC_64 = (BFD_MACH_O_CPU_TYPE_POWERPC | BFD_MACH_O_CPU_IS64BIT), ! BFD_MACH_O_CPU_TYPE_X86_64 = (BFD_MACH_O_CPU_TYPE_I386 | BFD_MACH_O_CPU_IS64BIT) } bfd_mach_o_cpu_type; *************** *** 183,188 **** --- 199,207 ---- unsigned long ncmds; unsigned long sizeofcmds; unsigned long flags; + unsigned int reserved; + /* Version 1: 32 bits, version 2: 64 bits. */ + unsigned int version; enum bfd_endian byteorder; } bfd_mach_o_header; *************** *** 201,206 **** --- 220,226 ---- unsigned long flags; unsigned long reserved1; unsigned long reserved2; + unsigned long reserved3; } bfd_mach_o_section; *************** *** 211,216 **** --- 231,238 ---- bfd_vma vmsize; bfd_vma fileoff; unsigned long filesize; + unsigned long maxprot; + unsigned long initprot; unsigned long nsects; unsigned long flags; bfd_mach_o_section *sections;