diff -r b4b157088bc8 gdb-768/src/bfd/mach-o.c --- a/gdb-768/src/bfd/mach-o.c Wed Aug 12 10:58:48 2009 +0100 +++ b/gdb-768/src/bfd/mach-o.c Wed Aug 26 15:09:04 2009 +0100 @@ -1905,14 +1905,40 @@ char *sname; const char *prefix = "LC_SEGMENT"; unsigned int snamelen; + // bfd_mach_o_segment_command structure is missing the cmd and cmdsize fields...DUH! - fG! + unsigned int cmd=0, cmdsize=0; + // this will hold our calculated value of nsects (the real one!) + unsigned int realnsects=0; +// To calculate the real number of sections we can use this information: +// cmdsize +// Common to all loadcommand structures. For this structure, set this field to +// sizeof(segment_command) plus the size of all the section data structures that follow +// (sizeof(segment_command + (sizeof(section) * segment->nsect))). + if (wide) { BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT_64); + // read cmd and cmdsize - fG! + bfd_seek (abfd, command->offset, SEEK_SET); + if (bfd_bread ((PTR) buf, 8, abfd) != 8) + { + printf("\nERROR: 8 bytes bfd_read for cmd and cmdsize failed!\n"); + return -1; + } + cmd = bfd_h_get_64 (abfd, buf); + cmdsize = bfd_h_get_64 (abfd, buf + 8); + // calculate the real number of sections + // segment_command_64 structure is 72 bytes + realnsects = (cmdsize - 72 ) / 80; + bfd_seek (abfd, command->offset + 8, SEEK_SET); if (bfd_bread ((PTR) buf, 64, abfd) != 64) - return -1; + { + printf("\nERROR: 64 bytes bfd_read failed!\n"); + return -1; + } memcpy (seg->segname, buf, 16); @@ -1929,9 +1955,28 @@ { BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT); + // read cmd and cmdsize - fG! + bfd_seek (abfd, command->offset, SEEK_SET); + // can't read data, so error ! + if (bfd_bread ((PTR) buf, 8, abfd) != 8) + { + printf("\nERROR: can't read data to retrieve cmd and cmdsize\n"); + return -1; + } + // retrieve cmd and cmdsize + cmd = bfd_h_get_32 (abfd, buf); + cmdsize = bfd_h_get_32 (abfd, buf + 4); + // calculate the real number of sections + // segment_command structure is 56 bytes + realnsects = (cmdsize - 56 ) / 68; + + // and get back to normal gdb processing bfd_seek (abfd, command->offset + 8, SEEK_SET); if (bfd_bread ((PTR) buf, 48, abfd) != 48) - return -1; + { + printf("\nERROR: can't read data to retrieve the whole header\n"); + return -1; + } memcpy (seg->segname, buf, 16); @@ -1948,12 +1993,18 @@ snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1; sname = (char *) bfd_alloc (abfd, snamelen); if (sname == NULL) + { + printf("\nERROR: bfd_alloc for sname failed!\n"); return -1; + } sprintf (sname, "%s.%s", prefix, seg->segname); bfdsec = bfd_make_section_anyway (abfd, sname); if (bfdsec == NULL) + { + printf("\nERROR: bfd_make_section_anyway failed!\n"); return -1; + } bfdsec->vma = seg->vmaddr; bfdsec->lma = seg->vmaddr; @@ -1966,14 +2017,48 @@ seg->segment = bfdsec; if (seg->nsects != 0) - { - seg->sections = - ((bfd_mach_o_section *) - bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section))); - if (seg->sections == NULL) - return -1; - - for (i = 0; i < seg->nsects; i++) + { + // check if the reported number of sections is correct + // filesize = Indicates the number of bytes occupied by this segment on disk. Each section has a size of 68 bytes (32bits) or 80 bytes (64 bits). + // if the size of the whole segment (filesize) is less than the size of all the sections reported by the header, + // then it's certain we have a problem, most probably the anti-debug trick + // the real number of sections can be calculated from the cmdsize. + // formula is: (sizeof(segment_command + (sizeof(section) * segment->nsect))) = cmdsize (at each segment header!) - retrieved from Mac OS X ABI Mach-O File Format Reference + // 64 bits + if (wide) + { + if ((unsigned long long)seg->filesize <= (unsigned long long)seg->nsects*80 || seg->nsects > realnsects) + { + printf("\n\n***WARNING***: Possible number of sections anti-debug trick detected at segment %s !\n", seg->segname); + printf("Number of sections reported from the header is %lli, the real number should be %lli\n", (unsigned long long)seg->nsects, (unsigned long long)realnsects); + // this would allow gdb to process the file but then dyld will fail so until Apple fixes the problem there's no interest doing it + // printf("Fixing to allow gdb to parse and work with this binary...\n"); + // seg->nsects = realnsects; + } + } + // 32 bits + else + { + if ((unsigned long long)seg->filesize < (unsigned long long)seg->nsects*68 || seg->nsects > realnsects) + { + printf("\n\n***WARNING***: Possible number of sections anti-debug trick detected at segment %s !\n", seg->segname); + printf("Number of sections reported from the header is %lli, the real number should be %lli\n", (unsigned long long)seg->nsects, (unsigned long long)realnsects); + // this would allow gdb to process the file but then dyld will fail so until Apple fixes the problem there's no interest doing it + // printf("Fixing to allow gdb to parse and work with this binary...\n"); + // seg->nsects = realnsects; + } + } + + // back to gdb normal code + seg->sections = ((bfd_mach_o_section *) bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section))); + // The 0xFFFFFFFF value will fail here since it's trying to allocate an huge amount of memory + if (seg->sections == NULL) + { + printf("\nERROR: bfd_alloc for seg->sections failed! Most probably because nsects is too big!\n"); + return -1; + } + + for (i = 0; i < seg->nsects; i++) { bfd_vma segoff; if (wide) @@ -1983,9 +2068,12 @@ if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i], segoff, wide) != 0) + { + printf("\nERROR: bfd_mach_o_scan_read_section failed!\n"); return -1; + } } - } + } return 0; } @@ -2008,6 +2096,7 @@ unsigned char buf[8]; bfd_seek (abfd, command->offset, SEEK_SET); + if (bfd_bread ((PTR) buf, 8, abfd) != 8) return -1; diff -r b4b157088bc8 gdb-768/src/gdb/disasm.c --- a/gdb-768/src/gdb/disasm.c Wed Aug 12 10:58:48 2009 +0100 +++ b/gdb-768/src/gdb/disasm.c Wed Aug 26 15:09:04 2009 +0100 @@ -98,8 +98,12 @@ int unmapped; int offset; int line; + struct cleanup *ui_out_chain; + struct cleanup *table_chain; + struct cleanup *tuple_chain; + for (pc = low; pc < high;) { char *filename = NULL; @@ -125,22 +129,49 @@ ui_out_field_string (uiout, "func-name", name); ui_out_text (uiout, "+"); ui_out_field_int (uiout, "offset", offset); - ui_out_text (uiout, ">:\t"); + ui_out_text (uiout, ">: "); } else - ui_out_text (uiout, ":\t"); - + ui_out_text (uiout, ": "); + if (filename != NULL) xfree (filename); if (name != NULL) xfree (name); + + ui_file_rewind (stb->stream); +// dump the disassembly raw bytes - ripped from gnu gdb latest cvs version +// fG! - 12/08/2009 +// save the initial disassembly address + CORE_ADDR old_pc = pc; + bfd_byte data; + int status; + int i; + +// this will return the disassembled instructions, but it will be buffered into the stream +// pc will hold the final address after the disassembly, so we can compute the length of the instruction +// the macro returns the number of bytes disassembled + pc += TARGET_PRINT_INSN (pc, di); + i = pc - old_pc; +// read the bytes from the initial address to the final address + for (; old_pc < pc; old_pc++) + { + status = (*di->read_memory_func) (old_pc, &data, 1, di); + if (status != 0) + (*di->memory_error_func) (status, old_pc, di); + // print the raw bytes + ui_out_message (uiout, 0, " %02x", (unsigned)data); + } + // to align the output... gdb tables don't work correctly :( + for (; i < 10 ; i++) ui_out_text(uiout, " "); + ui_out_text (uiout, " "); +// now we can finally print the buffered stream + ui_out_field_stream (uiout, "inst", stb); + ui_file_rewind (stb->stream); - ui_file_rewind (stb->stream); - pc += TARGET_PRINT_INSN (pc, di); - ui_out_field_stream (uiout, "inst", stb); - ui_file_rewind (stb->stream); - do_cleanups (ui_out_chain); - ui_out_text (uiout, "\n"); + do_cleanups (ui_out_chain); + ui_out_text (uiout, "\n"); + } return num_displayed; } @@ -630,6 +661,36 @@ int gdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream) { - struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream); - return TARGET_PRINT_INSN (memaddr, &di); + struct ui_stream *stb = ui_out_stream_new (uiout); + struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); + struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stb->stream); + // struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream); + struct disassemble_info * di2 = &di; + struct cleanup *ui_out_chain; + + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + int i; + CORE_ADDR old_pc = memaddr; + CORE_ADDR oldmemaddr = memaddr; + bfd_byte data; + int status; + ui_file_rewind (stb->stream); + memaddr = TARGET_PRINT_INSN (memaddr, &di); + oldmemaddr += memaddr; + for (; old_pc < oldmemaddr; old_pc ++) + { + status = (*di2->read_memory_func) (old_pc, &data, 1, di2); + if (status != 0) + (*di2->memory_error_func) (status, old_pc, di2); + ui_out_message (uiout, 0, " %02x", (unsigned)data); + } + i = memaddr; + for (; i<10; i++) ui_out_text(uiout, " "); + ui_out_text (uiout, " "); + ui_out_field_stream(uiout, "inst", stb); + ui_file_rewind (stb->stream); + do_cleanups (ui_out_chain); + + return memaddr; + // return TARGET_PRINT_INSN (memaddr, &di); } diff -r b4b157088bc8 gdb-768/src/gdb/printcmd.c --- a/gdb-768/src/gdb/printcmd.c Wed Aug 12 10:58:48 2009 +0100 +++ b/gdb-768/src/gdb/printcmd.c Wed Aug 26 15:09:04 2009 +0100 @@ -770,7 +770,9 @@ print_address (CORE_ADDR addr, struct ui_file *stream) { deprecated_print_address_numeric (addr, 1, stream); - print_address_symbolic (addr, stream, asm_demangle, " "); +// uncomment if you want to have the default symbolic name printing after the address in every line +// fG! 12/08/2009 +// print_address_symbolic (addr, stream, asm_demangle, " "); } /* Print address ADDR symbolically on STREAM. Parameter DEMANGLE @@ -864,7 +866,7 @@ i > 0 && count > 0; i--, count--) { - printf_filtered ("\t"); + printf_filtered (" "); /* Note that print_formatted sets next_address for the next object. */ last_examine_address = next_address; @@ -887,6 +889,9 @@ release_value (last_examine_value); print_formatted (last_examine_value, format, size, gdb_stdout); + // uncomment if you want to have the symbolic name printed in every line + // fG! 12/08/2009 + //print_address_symbolic (next_address, gdb_stdout, asm_demangle, " \t\t\t"); } printf_filtered ("\n"); gdb_flush (gdb_stdout); diff -r b4b157088bc8 gdb-768/src/gdb/symfile.c --- a/gdb-768/src/gdb/symfile.c Wed Aug 12 10:58:48 2009 +0100 +++ b/gdb-768/src/gdb/symfile.c Wed Aug 26 15:09:04 2009 +0100 @@ -3803,7 +3803,8 @@ clear_value_history (); clear_displays (); - clear_internalvars (); +// no need to clear the internal vars... damn apple forks - fG! 10/08/2009 +// clear_internalvars (); /* APPLE LOCAL breakpoints (remove reset) */ set_default_breakpoint (0, 0, 0, 0); clear_pc_function_cache ();