/* * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * This file intention is to beable to print the structures in an object file * and handle problems with reguard to alignment and bytesex. The goal is to * print as much as possible even when things are truncated or trashed. Both * a verbose (symbolic) and non-verbose modes are supported to aid in seeing * the values even if they are not correct. As much as possible strict checks * on values of fields for correctness should be done (such as proper alignment) * and notations on errors should be printed. */ #define __cr cr #define __ctr ctr #define __dar dar #define __dsisr dsisr #define __exception exception #define __fpregs fpregs #define __fpscr fpscr #define __fpscr_pad fpscr_pad #define __lr lr #define __mq mq #define __pad0 pad0 #define __pad1 pad1 #define __r0 r0 #define __r1 r1 #define __r10 r10 #define __r11 r11 #define __r12 r12 #define __r13 r13 #define __r14 r14 #define __r15 r15 #define __r16 r16 #define __r17 r17 #define __r18 r18 #define __r19 r19 #define __r2 r2 #define __r20 r20 #define __r21 r21 #define __r22 r22 #define __r23 r23 #define __r24 r24 #define __r25 r25 #define __r26 r26 #define __r27 r27 #define __r28 r28 #define __r29 r29 #define __r3 r3 #define __r30 r30 #define __r31 r31 #define __r4 r4 #define __r5 r5 #define __r6 r6 #define __r7 r7 #define __r8 r8 #define __r9 r9 #define __srr0 srr0 #define __srr1 srr1 #define __vrsave vrsave #define __xer xer #define __darwin_i386_exception_state i386_exception_state #define __darwin_i386_float_state i386_float_state #define __darwin_i386_thread_state i386_thread_state #define __busy busy #define __c0 c0 #define __c1 c1 #define __c2 c2 #define __c3 c3 #define __cs cs #define __darwin_fp_control fp_control #define __darwin_fp_status fp_status #define __darwin_mmst_reg mmst_reg #define __darwin_xmm_reg xmm_reg #define __denorm denorm #define __ds ds #define __eax eax #define __ebp ebp #define __ebx ebx #define __ecx ecx #define __edi edi #define __edx edx #define __eflags eflags #define __eip eip #define __err err #define __errsumm errsumm #define __es es #define __esi esi #define __esp esp #define __faultvaddr faultvaddr #define __fpu_cs fpu_cs #define __fpu_dp fpu_dp #define __fpu_ds fpu_ds #define __fpu_fcw fpu_fcw #define __fpu_fop fpu_fop #define __fpu_fsw fpu_fsw #define __fpu_ftw fpu_ftw #define __fpu_ip fpu_ip #define __fpu_mxcsr fpu_mxcsr #define __fpu_mxcsrmask fpu_mxcsrmask #define __fpu_reserved fpu_reserved #define __fpu_reserved1 fpu_reserved1 #define __fpu_rsrv1 fpu_rsrv1 #define __fpu_rsrv2 fpu_rsrv2 #define __fpu_rsrv3 fpu_rsrv3 #define __fpu_rsrv4 fpu_rsrv4 #define __fpu_stmm0 fpu_stmm0 #define __fpu_stmm1 fpu_stmm1 #define __fpu_stmm2 fpu_stmm2 #define __fpu_stmm3 fpu_stmm3 #define __fpu_stmm4 fpu_stmm4 #define __fpu_stmm5 fpu_stmm5 #define __fpu_stmm6 fpu_stmm6 #define __fpu_stmm7 fpu_stmm7 #define __fpu_xmm0 fpu_xmm0 #define __fpu_xmm1 fpu_xmm1 #define __fpu_xmm2 fpu_xmm2 #define __fpu_xmm3 fpu_xmm3 #define __fpu_xmm4 fpu_xmm4 #define __fpu_xmm5 fpu_xmm5 #define __fpu_xmm6 fpu_xmm6 #define __fpu_xmm7 fpu_xmm7 #define __fpu_xmm8 fpu_xmm8 #define __fpu_xmm9 fpu_xmm9 #define __fpu_xmm10 fpu_xmm10 #define __fpu_xmm11 fpu_xmm11 #define __fpu_xmm12 fpu_xmm12 #define __fpu_xmm13 fpu_xmm13 #define __fpu_xmm14 fpu_xmm14 #define __fpu_xmm15 fpu_xmm15 #define __fs fs #define __gs gs #define __invalid invalid #define __mmst_reg mmst_reg #define __mmst_rsrv mmst_rsrv #define __ovrfl ovrfl #define __pc pc #define __precis precis #define __rc rc #define __ss ss #define __stkflt stkflt #define __tos tos #define __trapno trapno #define __undfl undfl #define __xmm_reg xmm_reg #define __zdiv zdiv #define __rax rax #define __rbx rbx #define __rcx rcx #define __rdx rdx #define __rdi rdi #define __rsi rsi #define __rbp rbp #define __rsp rsp #define __r8 r8 #define __r9 r9 #define __r10 r10 #define __r11 r11 #define __r12 r12 #define __r13 r13 #define __r14 r14 #define __r15 r15 #define __rip rip #define __rflags rflags #define __dr0 dr0 #define __dr1 dr1 #define __dr2 dr2 #define __dr3 dr3 #define __dr4 dr4 #define __dr5 dr5 #define __dr6 dr6 #define __dr7 dr7 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stuff/symbol.h" #include "stuff/ofile.h" #include "stuff/allocate.h" #include "stuff/errors.h" #include "stuff/guess_short_name.h" #include "ofile_print.h" /* */ /* The maximum section alignment allowed to be specified, as a power of two */ #define MAXSECTALIGN 15 /* 2**15 or 0x8000 */ static void print_arch( struct fat_arch *fat_arch); static void print_cputype( cpu_type_t cputype, cpu_subtype_t cpusubtype); #if i386_THREAD_STATE == 1 #ifdef i386_EXCEPTION_STATE_COUNT static void print_mmst_reg( struct mmst_reg *r); static void print_xmm_reg( struct xmm_reg *r); #endif /* defined(i386_EXCEPTION_STATE_COUNT) */ #endif /* i386_THREAD_STATE == 1 */ static void print_unknown_state( char *begin, char *end, unsigned int count, enum bool swapped); struct reloc_section_info { char segname[16]; char sectname[16]; uint32_t nreloc; uint32_t reloff; }; static void print_relocs( unsigned reloff, unsigned nreloc, struct reloc_section_info *sect_rel, unsigned long nsects, enum bool swapped, cpu_type_t cputype, char *object_addr, unsigned long object_size, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, enum bool verbose); static void print_r_type( cpu_type_t cputype, unsigned long r_type, enum bool predicted); static void print_cstring_char( char c); static void print_literal4( unsigned long l, float f); static void print_literal8( unsigned long l0, unsigned long l1, double d); static void print_literal16( unsigned long l0, unsigned long l1, unsigned long l2, unsigned long l3); static int rel_bsearch( unsigned long *address, struct relocation_info *rel); /* * Print the fat header and the fat_archs. The caller is responsible for making * sure the structures are properly aligned and that the fat_archs is of the * size fat_header->nfat_arch * sizeof(struct fat_arch). */ void print_fat_headers( struct fat_header *fat_header, struct fat_arch *fat_archs, unsigned long size, enum bool verbose) { unsigned long i, j; uint64_t big_size; if(verbose){ if(fat_header->magic == FAT_MAGIC) printf("fat_magic FAT_MAGIC\n"); else printf("fat_magic 0x%x\n", (unsigned int)(fat_header->magic)); } else printf("fat_magic 0x%x\n", (unsigned int)(fat_header->magic)); printf("nfat_arch %u", fat_header->nfat_arch); big_size = fat_header->nfat_arch; big_size *= sizeof(struct fat_arch); big_size += sizeof(struct fat_header); if(fat_header->nfat_arch == 0) printf(" (malformed, contains zero architecture types)\n"); else if(big_size > size) printf(" (malformed, architectures past end of file)\n"); else printf("\n"); for(i = 0; i < fat_header->nfat_arch; i++){ big_size = i; big_size *= sizeof(struct fat_arch); big_size += sizeof(struct fat_header); if(big_size > size) break; printf("architecture "); for(j = 0; i != 0 && j <= i - 1; j++){ if(fat_archs[i].cputype != 0 && fat_archs[i].cpusubtype != 0 && fat_archs[i].cputype == fat_archs[j].cputype && (fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) == (fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){ printf("(illegal duplicate architecture) "); break; } } if(verbose){ print_arch(fat_archs + i); print_cputype(fat_archs[i].cputype, fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); } else{ printf("%ld\n", i); printf(" cputype %d\n", fat_archs[i].cputype); printf(" cpusubtype %d\n", fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK); } if(verbose && (fat_archs[i].cpusubtype & CPU_SUBTYPE_MASK) == CPU_SUBTYPE_LIB64) printf(" capabilities CPU_SUBTYPE_LIB64\n"); else printf(" capabilities 0x%x\n", (unsigned int) ((fat_archs[i].cpusubtype & CPU_SUBTYPE_MASK) >>24)); printf(" offset %u", fat_archs[i].offset); if(fat_archs[i].offset > size) printf(" (past end of file)"); if(fat_archs[i].offset % (1 << fat_archs[i].align) != 0) printf(" (not aligned on it's alignment (2^%u))\n", fat_archs[i].align); else printf("\n"); printf(" size %u", fat_archs[i].size); if(fat_archs[i].offset + fat_archs[i].size > size) printf(" (past end of file)\n"); else printf("\n"); printf(" align 2^%u (%d)", fat_archs[i].align, 1 << fat_archs[i].align); if(fat_archs[i].align > MAXSECTALIGN) printf("( too large, maximum 2^%d)\n", MAXSECTALIGN); else printf("\n"); } } /* * print_arch() helps print_fat_headers by printing the * architecture name for the cputype and cpusubtype. */ static void print_arch( struct fat_arch *fat_arch) { switch(fat_arch->cputype){ case CPU_TYPE_MC680x0: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC680x0_ALL: printf("m68k\n"); break; case CPU_SUBTYPE_MC68030_ONLY: printf("m68030\n"); break; case CPU_SUBTYPE_MC68040: printf("m68040\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_MC88000: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC88000_ALL: case CPU_SUBTYPE_MC88110: printf("m88k\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_I386: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I386_ALL: /* case CPU_SUBTYPE_386: same as above */ printf("i386\n"); break; case CPU_SUBTYPE_486: printf("i486\n"); break; case CPU_SUBTYPE_486SX: printf("i486SX\n"); break; case CPU_SUBTYPE_PENT: /* same as 586 */ printf("pentium\n"); break; case CPU_SUBTYPE_PENTPRO: printf("pentpro\n"); break; case CPU_SUBTYPE_PENTII_M3: printf("pentIIm3\n"); break; case CPU_SUBTYPE_PENTII_M5: printf("pentIIm5\n"); break; default: printf("intel x86 family %d model %d\n", CPU_SUBTYPE_INTEL_FAMILY(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK), CPU_SUBTYPE_INTEL_MODEL(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK)); break; } break; case CPU_TYPE_X86_64: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_X86_64_ALL: printf("x86_64\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_I860: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I860_ALL: case CPU_SUBTYPE_I860_860: printf("i860\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_POWERPC: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf("ppc\n"); break; case CPU_SUBTYPE_POWERPC_601: printf("ppc601\n"); break; case CPU_SUBTYPE_POWERPC_602: printf("ppc602\n"); break; case CPU_SUBTYPE_POWERPC_603: printf("ppc603\n"); break; case CPU_SUBTYPE_POWERPC_603e: printf("ppc603e\n"); break; case CPU_SUBTYPE_POWERPC_603ev: printf("ppc603ev\n"); break; case CPU_SUBTYPE_POWERPC_604: printf("ppc604\n"); break; case CPU_SUBTYPE_POWERPC_604e: printf("ppc604e\n"); break; case CPU_SUBTYPE_POWERPC_620: printf("ppc620\n"); break; case CPU_SUBTYPE_POWERPC_750: printf("ppc750\n"); break; case CPU_SUBTYPE_POWERPC_7400: printf("ppc7400\n"); break; case CPU_SUBTYPE_POWERPC_7450: printf("ppc7450\n"); break; case CPU_SUBTYPE_POWERPC_970: printf("ppc970\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_POWERPC64: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf("ppc64\n"); break; case CPU_SUBTYPE_POWERPC_970: printf("ppc970-64\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_VEO: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_VEO_1: printf("veo1\n"); break; case CPU_SUBTYPE_VEO_2: printf("veo2\n"); break; case CPU_SUBTYPE_VEO_3: printf("veo3\n"); break; case CPU_SUBTYPE_VEO_4: printf("veo4\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_HPPA: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_HPPA_ALL: case CPU_SUBTYPE_HPPA_7100LC: printf("hppa\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_SPARC: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_SPARC_ALL: printf("sparc\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_ANY: switch(fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MULTIPLE: printf("any\n"); break; case CPU_SUBTYPE_LITTLE_ENDIAN: printf("little\n"); break; case CPU_SUBTYPE_BIG_ENDIAN: printf("big\n"); break; default: goto print_arch_unknown; } break; print_arch_unknown: default: printf("cputype (%d) cpusubtype (%d)\n", fat_arch->cputype, fat_arch->cpusubtype & ~CPU_SUBTYPE_MASK); break; } } /* * print_cputype() helps print_fat_headers by printing the cputype and * cpusubtype (symbolicly for the one's it knows about). */ static void print_cputype( cpu_type_t cputype, cpu_subtype_t cpusubtype) { switch(cputype){ case CPU_TYPE_MC680x0: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC680x0_ALL: printf(" cputype CPU_TYPE_MC680x0\n" " cpusubtype CPU_SUBTYPE_MC680x0_ALL\n"); break; case CPU_SUBTYPE_MC68030_ONLY: printf(" cputype CPU_TYPE_MC680x0\n" " cpusubtype CPU_SUBTYPE_MC68030_ONLY\n"); break; case CPU_SUBTYPE_MC68040: printf(" cputype CPU_TYPE_MC680x0\n" " cpusubtype CPU_SUBTYPE_MC68040\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_MC88000: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC88000_ALL: printf(" cputype CPU_TYPE_MC88000\n" " cpusubtype CPU_SUBTYPE_MC88000_ALL\n"); break; case CPU_SUBTYPE_MC88110: printf(" cputype CPU_TYPE_MC88000\n" " cpusubtype CPU_SUBTYPE_MC88110\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_I386: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I386_ALL: /* case CPU_SUBTYPE_386: same as above */ printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_I386_ALL\n"); break; case CPU_SUBTYPE_486: printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_486\n"); break; case CPU_SUBTYPE_486SX: printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_486SX\n"); break; case CPU_SUBTYPE_PENT: /* same as 586 */ printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_PENT\n"); break; case CPU_SUBTYPE_PENTPRO: printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_PENTPRO\n"); break; case CPU_SUBTYPE_PENTII_M3: printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_PENTII_M3\n"); break; case CPU_SUBTYPE_PENTII_M5: printf(" cputype CPU_TYPE_I386\n" " cpusubtype CPU_SUBTYPE_PENTII_M5\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_X86_64: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_X86_64_ALL: printf(" cputype CPU_TYPE_X86_64\n" " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_I860: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I860_ALL: printf(" cputype CPU_TYPE_I860\n" " cpusubtype CPU_SUBTYPE_I860_ALL\n"); break; case CPU_SUBTYPE_I860_860: printf(" cputype CPU_TYPE_I860\n" " cpusubtype CPU_SUBTYPE_I860_860\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_POWERPC: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_ALL\n"); break; case CPU_SUBTYPE_POWERPC_601: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_601\n"); break; case CPU_SUBTYPE_POWERPC_602: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_602\n"); break; case CPU_SUBTYPE_POWERPC_603: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_603\n"); break; case CPU_SUBTYPE_POWERPC_603e: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_603e\n"); break; case CPU_SUBTYPE_POWERPC_603ev: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_603ev\n"); break; case CPU_SUBTYPE_POWERPC_604: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_604\n"); break; case CPU_SUBTYPE_POWERPC_604e: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_604e\n"); break; case CPU_SUBTYPE_POWERPC_620: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_620\n"); break; case CPU_SUBTYPE_POWERPC_750: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_750\n"); break; case CPU_SUBTYPE_POWERPC_7400: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_7400\n"); break; case CPU_SUBTYPE_POWERPC_7450: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_7450\n"); break; case CPU_SUBTYPE_POWERPC_970: printf(" cputype CPU_TYPE_POWERPC\n" " cpusubtype CPU_SUBTYPE_POWERPC_970\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_POWERPC64: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf(" cputype CPU_TYPE_POWERPC64\n" " cpusubtype CPU_SUBTYPE_POWERPC64_ALL\n"); break; case CPU_SUBTYPE_POWERPC_970: printf(" cputype CPU_TYPE_POWERPC64\n" " cpusubtype CPU_SUBTYPE_POWERPC_970\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_VEO: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_VEO_1: printf(" cputype CPU_TYPE_VEO\n" " cpusubtype CPU_SUBTYPE_VEO_1\n"); break; case CPU_SUBTYPE_VEO_2: printf(" cputype CPU_TYPE_VEO\n" " cpusubtype CPU_SUBTYPE_VEO_2\n"); break; case CPU_SUBTYPE_VEO_3: printf(" cputype CPU_TYPE_VEO\n" " cpusubtype CPU_SUBTYPE_VEO_3\n"); break; case CPU_SUBTYPE_VEO_4: printf(" cputype CPU_TYPE_VEO\n" " cpusubtype CPU_SUBTYPE_VEO_4\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_HPPA: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_HPPA_ALL: printf(" cputype CPU_TYPE_HPPA\n" " cpusubtype CPU_SUBTYPE_HPPA_ALL\n"); break; case CPU_SUBTYPE_HPPA_7100LC: printf(" cputype CPU_TYPE_HPPA\n" " cpusubtype CPU_SUBTYPE_HPPA_7100LC\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_SPARC: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_SPARC_ALL: printf(" cputype CPU_TYPE_SPARC\n" " cpusubtype CPU_SUBTYPE_SPARC_ALL\n"); break; default: goto print_arch_unknown; } break; case CPU_TYPE_ANY: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MULTIPLE: printf(" cputype CPU_TYPE_ANY\n" " cpusubtype CPU_SUBTYPE_MULTIPLE\n"); break; case CPU_SUBTYPE_LITTLE_ENDIAN: printf(" cputype CPU_TYPE_ANY\n" " cpusubtype CPU_SUBTYPE_LITTLE_ENDIAN\n"); break; case CPU_SUBTYPE_BIG_ENDIAN: printf(" cputype CPU_TYPE_ANY\n" " cpusubtype CPU_SUBTYPE_BIG_ENDIAN\n"); break; default: goto print_arch_unknown; } break; print_arch_unknown: default: printf(" cputype (%d)\n" " cpusubtype (%d)\n", cputype, cpusubtype & ~CPU_SUBTYPE_MASK); break; } } /* * Print the archive header. The format is constant width character fields * blank padded. So the trailing blanks are stripped and full field widths * are handled correctly. */ void print_ar_hdr( struct ar_hdr *ar_hdr, char *member_name, unsigned long member_name_size, enum bool verbose) { long i; unsigned long j, mode, date; char *p, *endp; char date_buf[sizeof(ar_hdr->ar_date) + 1]; char uid_buf[sizeof(ar_hdr->ar_uid) + 1]; char gid_buf[sizeof(ar_hdr->ar_gid) + 1]; char mode_buf[sizeof(ar_hdr->ar_mode) + 1]; char size_buf[sizeof(ar_hdr->ar_size) + 1]; memcpy(date_buf, ar_hdr->ar_date, sizeof(ar_hdr->ar_date)); for(i = sizeof(ar_hdr->ar_date) - 1; i >= 0 && date_buf[i] == ' '; i--) date_buf[i] = '\0'; date_buf[sizeof(ar_hdr->ar_date)] = '\0'; memcpy(uid_buf, ar_hdr->ar_uid, sizeof(ar_hdr->ar_uid)); for(i = sizeof(ar_hdr->ar_uid) - 1; i >= 0 && uid_buf[i] == ' '; i--) uid_buf[i] = '\0'; uid_buf[sizeof(ar_hdr->ar_uid)] = '\0'; memcpy(gid_buf, ar_hdr->ar_gid, sizeof(ar_hdr->ar_gid)); for(i = sizeof(ar_hdr->ar_gid) - 1; i >= 0 && gid_buf[i] == ' '; i--) gid_buf[i] = '\0'; gid_buf[sizeof(ar_hdr->ar_gid)] = '\0'; memcpy(mode_buf, ar_hdr->ar_mode, sizeof(ar_hdr->ar_mode)); for(i = sizeof(ar_hdr->ar_mode) - 1; i >= 0 && mode_buf[i] == ' '; i--) mode_buf[i] = '\0'; mode_buf[sizeof(ar_hdr->ar_mode)] = '\0'; memcpy(size_buf, ar_hdr->ar_size, sizeof(ar_hdr->ar_size)); for(i = sizeof(ar_hdr->ar_size) - 1; i >= 0 && size_buf[i] == ' '; i--) size_buf[i] = '\0'; size_buf[sizeof(ar_hdr->ar_size)] = '\0'; if(verbose == TRUE){ mode = strtoul(mode_buf, &endp, 8); if(*endp != '\0') printf("(mode: \"%s\" contains non-octal chars) ", mode_buf); switch(mode & S_IFMT){ case S_IFDIR: printf("d"); break; case S_IFCHR: printf("c"); break; case S_IFBLK: printf("b"); break; case S_IFREG: printf("-"); break; case S_IFLNK: printf("l"); break; case S_IFSOCK: printf("s"); break; default: printf("?"); break; } /* owner permissions */ if(mode & S_IREAD) printf("r"); else printf("-"); if(mode & S_IWRITE) printf("w"); else printf("-"); if(mode & S_ISUID) printf("s"); else if(mode & S_IEXEC) printf("x"); else printf("-"); /* group permissions */ if(mode & (S_IREAD >> 3)) printf("r"); else printf("-"); if(mode & (S_IWRITE >> 3)) printf("w"); else printf("-"); if(mode & S_ISGID) printf("s"); else if(mode & (S_IEXEC >> 3)) printf("x"); else printf("-"); /* other permissions */ if(mode & (S_IREAD >> 6)) printf("r"); else printf("-"); if(mode & (S_IWRITE >> 6)) printf("w"); else printf("-"); if(mode & S_ISVTX) printf("t"); else if(mode & (S_IEXEC >> 6)) printf("x"); else printf("-"); } else /* printf("0%03o ", mode & 0777); */ printf("0%s ", mode_buf); printf("%3s/%-3s %5s ", uid_buf, gid_buf, size_buf); /* * Since cime(3) returns a 26 character string of the form: * "Sun Sep 16 01:03:52 1973\n\0" * and the new line is not wanted a '\0' is placed there. */ if(verbose){ date = strtoul(date_buf, &endp, 10); if(*endp != '\0') printf("(date: \"%s\" contains non-decimal chars) ", date_buf); p = ctime((const long *)&date); p[24] = '\0'; printf("%s ", p); } else printf("%s ", date_buf); if(verbose){ printf("%.*s", (int)member_name_size, member_name); } else{ j = size_ar_name(ar_hdr); printf("%.*s", (int)j, ar_hdr->ar_name); } if(memcmp(ar_hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1) == 0) printf("\n"); else printf(" (ar_fmag not ARFMAG)\n"); } /* * print_library_toc prints the table of contents of the a library. It is * converted to the host byte sex if toc_byte_sex is not the host byte sex. * The problem with determing the byte sex of the table of contents is left * to the caller. The determination is based on the byte sex of the object * files contained in the library (this can still present a problem since the * object files could be of differing byte sex in an erroneous library). There * is no problem of a library containing no objects with respect to the byte * sex of the table of contents since the table of contents would be made up * of two binary unsigned long zeros which are the same in either byte sex. */ void print_library_toc( struct ar_hdr *toc_ar_hdr, char *toc_name, unsigned long toc_name_size, char *toc_addr, unsigned long toc_size, enum byte_sex toc_byte_sex, char *library_name, char *library_addr, unsigned long library_size, char *arch_name, enum bool verbose) { enum byte_sex host_byte_sex; unsigned long ran_size, nranlibs, str_size, i, toc_offset, member_name_size; struct ranlib *ranlibs; char *strings, *member_name; struct ar_hdr *ar_hdr; int n; char buf[20]; host_byte_sex = get_host_byte_sex(); toc_offset = 0; strings = NULL; if(toc_offset + sizeof(unsigned long) > toc_size){ error_with_arch(arch_name, "truncated table of contents in: " "%s(%.*s) (size of ranlib structs extends past the end of the " "table of contents member)", library_name, (int)toc_name_size, toc_name); return; } memcpy((char *)&ran_size, toc_addr + toc_offset, sizeof(unsigned long)); if(toc_byte_sex != host_byte_sex) ran_size = SWAP_LONG(ran_size); toc_offset += sizeof(unsigned long); if(toc_offset + ran_size > toc_size){ error_with_arch(arch_name, "truncated table of contents in: " "%s(%.*s) (ranlib structures extends past the end of the " "table of contents member)", library_name, (int)toc_name_size, toc_name); return; } ranlibs = allocate(ran_size); memcpy((char *)ranlibs, toc_addr + toc_offset, ran_size); nranlibs = ran_size / sizeof(struct ranlib); if(toc_byte_sex != host_byte_sex) swap_ranlib(ranlibs, nranlibs, host_byte_sex); toc_offset += ran_size; if(verbose){ if(toc_offset + sizeof(unsigned long) > toc_size){ error_with_arch(arch_name, "truncated table of contents in: " "%s(%.*s) (size of ranlib strings extends past the end of " "the table of contents member)", library_name, (int)toc_name_size, toc_name); free(ranlibs); return; } memcpy((char *)&str_size, toc_addr + toc_offset, sizeof(unsigned long)); if(toc_byte_sex != host_byte_sex) str_size = SWAP_LONG(str_size); toc_offset += sizeof(unsigned long); if(toc_offset + str_size > toc_size){ error_with_arch(arch_name, "truncated table of contents in: " "%s(%.*s) (ranlib strings extends past the end of the " "table of contents member)", library_name, (int)toc_name_size, toc_name); free(ranlibs); return; } strings = toc_addr + toc_offset; } printf("Table of contents from: %s(%.*s)", library_name, (int)toc_name_size, toc_name); if(arch_name != NULL) printf(" (for architecture %s)\n", arch_name); else printf("\n"); printf("size of ranlib structures: %lu (number %lu)\n", ran_size, nranlibs); if(verbose){ printf("size of strings: %lu", str_size); if(str_size % sizeof(long) != 0) printf(" (not multiple of sizeof(long))\n"); else printf("\n"); } if(verbose) printf("object symbol name\n"); else printf("object offset string index\n"); for(i = 0; i < nranlibs; i++){ if(verbose){ if(ranlibs[i].ran_off + sizeof(struct ar_hdr) <= library_size){ ar_hdr = (struct ar_hdr *) (library_addr + ranlibs[i].ran_off); if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){ member_name = ar_hdr->ar_name + sizeof(struct ar_hdr); member_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1, NULL, 10); while(member_name_size > 0 && member_name[member_name_size - 1] == '\0') member_name_size--; printf("%-.*s ", (int)member_name_size, member_name); if(member_name_size < 16) printf("%-.*s", (int)(16 - member_name_size), " "); } else{ printf("%-.16s ", ar_hdr->ar_name); } } else{ n = sprintf(buf, "?(%ld) ", (long int)ranlibs[i].ran_off); printf("%s%.*s", buf, 17 - n, " "); } if(ranlibs[i].ran_un.ran_strx < str_size) printf("%s\n", strings + ranlibs[i].ran_un.ran_strx); else printf("?(%ld)\n", (long int)ranlibs[i].ran_un.ran_strx); } else{ printf("%-14ld %ld\n", (long int)ranlibs[i].ran_off, (long int)ranlibs[i].ran_un.ran_strx); } } free(ranlibs); } /* * Print the mach header. It is assumed that the parameters are in the host * byte sex. In this way it is up to the caller to determine he has a * mach_header and what byte sex it is and get it aligned in the host byte sex * for the parameters to this routine. */ void print_mach_header( uint32_t magic, cpu_type_t cputype, cpu_subtype_t cpusubtype, uint32_t filetype, uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, enum bool verbose) { unsigned long f; printf("Mach header\n"); printf(" magic cputype cpusubtype caps filetype ncmds " "sizeofcmds flags\n"); if(verbose){ if(magic == MH_MAGIC) printf("%11s", "MH_MAGIC"); else if(magic == MH_MAGIC_64) printf("%11s", "MH_MAGIC_64"); else printf(" 0x%08x", (unsigned int)magic); switch(cputype){ case CPU_TYPE_POWERPC64: printf(" PPC64"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf(" ALL"); break; case CPU_SUBTYPE_POWERPC_970: printf(" ppc970"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_X86_64: printf(" X86_64"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_X86_64_ALL: printf(" ALL"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_VAX: printf(" VAX"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_VAX780: printf(" VAX780"); break; case CPU_SUBTYPE_VAX785: printf(" VAX785"); break; case CPU_SUBTYPE_VAX750: printf(" VAX750"); break; case CPU_SUBTYPE_VAX730: printf(" VAX730"); break; case CPU_SUBTYPE_UVAXI: printf(" UVAXI"); break; case CPU_SUBTYPE_UVAXII: printf(" UVAXII"); break; case CPU_SUBTYPE_VAX8200: printf(" VAX8200"); break; case CPU_SUBTYPE_VAX8500: printf(" VAX8500"); break; case CPU_SUBTYPE_VAX8600: printf(" VAX8600"); break; case CPU_SUBTYPE_VAX8650: printf(" VAX8650"); break; case CPU_SUBTYPE_VAX8800: printf(" VAX8800"); break; case CPU_SUBTYPE_UVAXIII: printf(" UVAXIII"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_ROMP: printf(" ROMP"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_RT_PC: printf(" RT_PC"); break; case CPU_SUBTYPE_RT_APC: printf(" RT_APC"); break; case CPU_SUBTYPE_RT_135: printf(" RT_135"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_NS32032: printf(" NS32032"); goto NS32; case CPU_TYPE_NS32332: printf(" NS32332"); NS32: switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MMAX_DPC: printf(" MMAX_DPC"); break; case CPU_SUBTYPE_SQT: printf(" SQT"); break; case CPU_SUBTYPE_MMAX_APC_FPU: printf(" MMAX_APC_FPC"); break; case CPU_SUBTYPE_MMAX_APC_FPA: printf(" MMAX_APC_FPA"); break; case CPU_SUBTYPE_MMAX_XPC: printf(" MMAX_XPC"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_MC680x0: printf(" MC680x0"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC680x0_ALL: printf(" ALL"); break; case CPU_SUBTYPE_MC68030_ONLY: printf(" MC68030"); break; case CPU_SUBTYPE_MC68040: printf(" MC68040"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_MC88000: printf(" MC88000"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_MC88000_ALL: printf(" ALL"); break; case CPU_SUBTYPE_MC88100: printf(" MC88100"); break; case CPU_SUBTYPE_MC88110: printf(" MC88110"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_I860: printf(" I860"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I860_ALL: printf(" ALL"); break; case CPU_SUBTYPE_I860_860: printf(" 860"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_I386: printf(" I386"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_I386_ALL: /* case CPU_SUBTYPE_386: same as above */ printf(" ALL"); break; case CPU_SUBTYPE_486: printf(" 486"); break; case CPU_SUBTYPE_486SX: printf(" 486SX"); break; case CPU_SUBTYPE_PENT: /* same as 586 */ printf(" PENT"); break; case CPU_SUBTYPE_PENTPRO: printf(" PENTPRO"); break; case CPU_SUBTYPE_PENTII_M3: printf(" PENTII_M3"); break; case CPU_SUBTYPE_PENTII_M5: printf(" PENTII_M5"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_POWERPC: printf(" PPC"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_POWERPC_ALL: printf(" ALL"); break; case CPU_SUBTYPE_POWERPC_601: printf(" ppc601"); break; case CPU_SUBTYPE_POWERPC_602: printf(" ppc602"); break; case CPU_SUBTYPE_POWERPC_603: printf(" ppc603"); break; case CPU_SUBTYPE_POWERPC_603e: printf(" ppc603e"); break; case CPU_SUBTYPE_POWERPC_603ev: printf(" ppc603ev"); break; case CPU_SUBTYPE_POWERPC_604: printf(" ppc604"); break; case CPU_SUBTYPE_POWERPC_604e: printf(" ppc604e"); break; case CPU_SUBTYPE_POWERPC_620: printf(" ppc620"); break; case CPU_SUBTYPE_POWERPC_750: printf(" ppc750"); break; case CPU_SUBTYPE_POWERPC_7400: printf(" ppc7400"); break; case CPU_SUBTYPE_POWERPC_7450: printf(" ppc7450"); break; case CPU_SUBTYPE_POWERPC_970: printf(" ppc970"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_VEO: printf(" VEO"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_VEO_1: printf(" veo1"); break; case CPU_SUBTYPE_VEO_2: printf(" veo2"); break; case CPU_SUBTYPE_VEO_3: printf(" veo3"); break; case CPU_SUBTYPE_VEO_4: printf(" veo4"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_HPPA: printf(" HPPA"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_HPPA_ALL: printf(" ALL"); break; case CPU_SUBTYPE_HPPA_7100LC: printf(" HPPA_7100LC"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_SPARC: printf(" SPARC"); switch(cpusubtype & ~CPU_SUBTYPE_MASK){ case CPU_SUBTYPE_SPARC_ALL: printf(" ALL"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; case CPU_TYPE_ARM: printf(" ARM"); switch(cpusubtype){ case CPU_SUBTYPE_ARM_ALL: printf(" ALL"); break; case CPU_SUBTYPE_ARM_V4T: printf(" V4T"); break; case CPU_SUBTYPE_ARM_V5TEJ: printf(" V5TEJ"); break; case CPU_SUBTYPE_ARM_XSCALE: printf(" XSCALE"); break; case CPU_SUBTYPE_ARM_V6: printf(" V6"); break; default: printf(" %10d", cpusubtype & ~CPU_SUBTYPE_MASK); break; } break; default: printf(" %7d %10d", cputype, cpusubtype & ~CPU_SUBTYPE_MASK); break; } if((cpusubtype & CPU_SUBTYPE_MASK) == CPU_SUBTYPE_LIB64){ printf(" LIB64 "); } else{ printf(" 0x%02x ", (unsigned int) ((cpusubtype & ~CPU_SUBTYPE_MASK) >> 24)); } switch(filetype){ case MH_OBJECT: printf(" OBJECT"); break; case MH_EXECUTE: printf(" EXECUTE"); break; case MH_FVMLIB: printf(" FVMLIB"); break; case MH_CORE: printf(" CORE"); break; case MH_PRELOAD: printf(" PRELOAD"); break; case MH_DYLIB: printf(" DYLIB"); break; case MH_DYLIB_STUB: printf(" DYLIB_STUB"); break; case MH_DYLINKER: printf(" DYLINKER"); break; case MH_BUNDLE: printf(" BUNDLE"); break; case MH_DSYM: printf(" DSYM"); default: printf(" %10u", filetype); break; } printf(" %5u %10u", ncmds, sizeofcmds); f = flags; if(f & MH_NOUNDEFS){ printf(" NOUNDEFS"); f &= ~MH_NOUNDEFS; } if(f & MH_INCRLINK){ printf(" INCRLINK"); f &= ~MH_INCRLINK; } if(f & MH_DYLDLINK){ printf(" DYLDLINK"); f &= ~MH_DYLDLINK; } if(f & MH_BINDATLOAD){ printf(" BINDATLOAD"); f &= ~MH_BINDATLOAD; } if(f & MH_PREBOUND){ printf(" PREBOUND"); f &= ~MH_PREBOUND; } if(f & MH_SPLIT_SEGS){ printf(" SPLIT_SEGS"); f &= ~MH_SPLIT_SEGS; } if(f & MH_LAZY_INIT){ printf(" LAZY_INIT"); f &= ~MH_LAZY_INIT; } if(f & MH_TWOLEVEL){ printf(" TWOLEVEL"); f &= ~MH_TWOLEVEL; } if(f & MH_FORCE_FLAT){ printf(" FORCE_FLAT"); f &= ~MH_FORCE_FLAT; } if(f & MH_NOMULTIDEFS){ printf(" NOMULTIDEFS"); f &= ~MH_NOMULTIDEFS; } if(f & MH_NOFIXPREBINDING){ printf(" NOFIXPREBINDING"); f &= ~MH_NOFIXPREBINDING; } if(f & MH_PREBINDABLE){ printf(" PREBINDABLE"); f &= ~MH_PREBINDABLE; } if(f & MH_ALLMODSBOUND){ printf(" ALLMODSBOUND"); f &= ~MH_ALLMODSBOUND; } if(f & MH_SUBSECTIONS_VIA_SYMBOLS){ printf(" SUBSECTIONS_VIA_SYMBOLS"); f &= ~MH_SUBSECTIONS_VIA_SYMBOLS; } if(f & MH_CANONICAL){ printf(" CANONICAL"); f &= ~MH_CANONICAL; } if(f & MH_WEAK_DEFINES){ printf(" WEAK_DEFINES"); f &= ~MH_WEAK_DEFINES; } if(f & MH_BINDS_TO_WEAK){ printf(" BINDS_TO_WEAK"); f &= ~MH_BINDS_TO_WEAK; } if(f & MH_ALLOW_STACK_EXECUTION){ printf(" ALLOW_STACK_EXECUTION"); f &= ~MH_ALLOW_STACK_EXECUTION; } if(f & MH_PIE){ printf(" PIE"); f &= ~MH_PIE; } if(f & MH_NO_REEXPORTED_DYLIBS){ printf(" NO_REEXPORTED_DYLIBS"); f &= ~MH_NO_REEXPORTED_DYLIBS; } if(f != 0 || flags == 0) printf(" 0x%08x", (unsigned int)f); printf("\n"); } else{ printf(" 0x%08x %7d %10d 0x%02x %10u %5u %10u 0x%08x\n", (unsigned int)magic, cputype, cpusubtype & ~CPU_SUBTYPE_MASK, (unsigned int)((cpusubtype & CPU_SUBTYPE_MASK) >> 24), filetype, ncmds, sizeofcmds, (unsigned int)flags); } } /* * Print the load commands. The load commands pointed to by load_commands can * have any alignment, are in the specified byte_sex, and must be at least * sizeofcmds in length. */ void print_loadcmds( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, cpu_type_t cputype, uint32_t filetype, enum byte_sex load_commands_byte_sex, unsigned long object_size, enum bool verbose, enum bool very_verbose) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, j, k, left, size, *unknown, nsyms; char *p, *begin, *end; struct load_command *lc, l; struct segment_command sg; struct section s; struct segment_command_64 sg64; struct section_64 s64; struct symtab_command st; struct dysymtab_command dyst; struct symseg_command ss; struct fvmlib_command fl; struct dylib_command dl; struct prebound_dylib_command pbdylib; struct sub_framework_command sub; struct sub_umbrella_command usub; struct sub_library_command lsub; struct sub_client_command csub; struct fvmfile_command ff; struct dylinker_command dyld; struct routines_command rc; struct routines_command_64 rc64; struct twolevel_hints_command hints; struct prebind_cksum_command cs; struct uuid_command uuid; struct linkedit_data_command ld; struct rpath_command rpath; struct encryption_info_command encrypt; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; nsyms = ULONG_MAX; lc = load_commands; for(i = 0 ; i < ncmds; i++){ printf("Load command %lu\n", i); memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&l, host_byte_sex); if(l.cmdsize % sizeof(long) != 0) printf("load command %lu size not a multiple of sizeof(long)\n", i); if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %lu extends past end of load commands\n", i); left = sizeofcmds - ((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: memset((char *)&sg, '\0', sizeof(struct segment_command)); size = left < sizeof(struct segment_command) ? left : sizeof(struct segment_command); memcpy((char *)&sg, (char *)lc, size); if(swapped) swap_segment_command(&sg, host_byte_sex); print_segment_command(sg.cmd, sg.cmdsize, sg.segname, sg.vmaddr, sg.vmsize, sg.fileoff, sg.filesize, sg.maxprot, sg.initprot, sg.nsects, sg.flags, object_size, verbose); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds){ printf("section structure command extends past end of " "load commands\n"); } left = sizeofcmds - (p - (char *)load_commands); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); memcpy((char *)&s, p, size); if(swapped) swap_section(&s, 1, host_byte_sex); print_section(s.sectname, s.segname, s.addr, s.size, s.offset, s.align, s.reloff, s.nreloc, s.flags, s.reserved1, s.reserved2, sg.cmd, sg.segname, filetype, object_size, verbose); if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds) return; p += size; } break; case LC_SEGMENT_64: memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); size = left < sizeof(struct segment_command_64) ? left : sizeof(struct segment_command_64); memcpy((char *)&sg64, (char *)lc, size); if(swapped) swap_segment_command_64(&sg64, host_byte_sex); print_segment_command(sg64.cmd, sg64.cmdsize, sg64.segname, sg64.vmaddr, sg64.vmsize, sg64.fileoff, sg64.filesize, sg64.maxprot, sg64.initprot, sg64.nsects, sg64.flags, object_size, verbose); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ if(p + sizeof(struct section_64) > (char *)load_commands + sizeofcmds){ printf("section structure command extends past end of " "load commands\n"); } left = sizeofcmds - (p - (char *)load_commands); memset((char *)&s64, '\0', sizeof(struct section_64)); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); memcpy((char *)&s64, p, size); if(swapped) swap_section_64(&s64, 1, host_byte_sex); print_section(s64.sectname, s64.segname, s64.addr, s64.size, s64.offset, s64.align, s64.reloff, s64.nreloc, s64.flags, s64.reserved1, s64.reserved2, sg64.cmd, sg64.segname, filetype, object_size, verbose); if(p + sizeof(struct section_64) > (char *)load_commands + sizeofcmds) return; p += size; } break; case LC_SYMTAB: memset((char *)&st, '\0', sizeof(struct symtab_command)); size = left < sizeof(struct symtab_command) ? left : sizeof(struct symtab_command); memcpy((char *)&st, (char *)lc, size); if(swapped) swap_symtab_command(&st, host_byte_sex); nsyms = st.nsyms; print_symtab_command(&st, cputype, object_size); break; case LC_DYSYMTAB: memset((char *)&dyst, '\0', sizeof(struct dysymtab_command)); size = left < sizeof(struct dysymtab_command) ? left : sizeof(struct dysymtab_command); memcpy((char *)&dyst, (char *)lc, size); if(swapped) swap_dysymtab_command(&dyst, host_byte_sex); print_dysymtab_command(&dyst, nsyms, object_size, cputype); break; case LC_SYMSEG: memset((char *)&ss, '\0', sizeof(struct symseg_command)); size = left < sizeof(struct symseg_command) ? left : sizeof(struct symseg_command); memcpy((char *)&ss, (char *)lc, size); if(swapped) swap_symseg_command(&ss, host_byte_sex); print_symseg_command(&ss, object_size); break; case LC_IDFVMLIB: case LC_LOADFVMLIB: memset((char *)&fl, '\0', sizeof(struct fvmlib_command)); size = left < sizeof(struct fvmlib_command) ? left : sizeof(struct fvmlib_command); memcpy((char *)&fl, (char *)lc, size); if(swapped) swap_fvmlib_command(&fl, host_byte_sex); print_fvmlib_command(&fl, lc); break; case LC_ID_DYLIB: case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: case LC_REEXPORT_DYLIB: memset((char *)&dl, '\0', sizeof(struct dylib_command)); size = left < sizeof(struct dylib_command) ? left : sizeof(struct dylib_command); memcpy((char *)&dl, (char *)lc, size); if(swapped) swap_dylib_command(&dl, host_byte_sex); print_dylib_command(&dl, lc); break; case LC_SUB_FRAMEWORK: memset((char *)&sub, '\0',sizeof(struct sub_framework_command)); size = left < sizeof(struct sub_framework_command) ? left : sizeof(struct sub_framework_command); memcpy((char *)&sub, (char *)lc, size); if(swapped) swap_sub_framework_command(&sub, host_byte_sex); print_sub_framework_command(&sub, lc); break; case LC_SUB_UMBRELLA: memset((char *)&usub, '\0',sizeof(struct sub_umbrella_command)); size = left < sizeof(struct sub_umbrella_command) ? left : sizeof(struct sub_umbrella_command); memcpy((char *)&usub, (char *)lc, size); if(swapped) swap_sub_umbrella_command(&usub, host_byte_sex); print_sub_umbrella_command(&usub, lc); break; case LC_SUB_LIBRARY: memset((char *)&lsub, '\0',sizeof(struct sub_library_command)); size = left < sizeof(struct sub_library_command) ? left : sizeof(struct sub_library_command); memcpy((char *)&lsub, (char *)lc, size); if(swapped) swap_sub_library_command(&lsub, host_byte_sex); print_sub_library_command(&lsub, lc); break; case LC_SUB_CLIENT: memset((char *)&csub, '\0',sizeof(struct sub_client_command)); size = left < sizeof(struct sub_client_command) ? left : sizeof(struct sub_client_command); memcpy((char *)&csub, (char *)lc, size); if(swapped) swap_sub_client_command(&csub, host_byte_sex); print_sub_client_command(&csub, lc); break; case LC_PREBOUND_DYLIB: memset((char *)&pbdylib, '\0', sizeof(struct prebound_dylib_command)); size = left < sizeof(struct prebound_dylib_command) ? left : sizeof(struct prebound_dylib_command); memcpy((char *)&pbdylib, (char *)lc, size); if(swapped) swap_prebound_dylib_command(&pbdylib, host_byte_sex); print_prebound_dylib_command(&pbdylib, lc, very_verbose); break; case LC_ID_DYLINKER: case LC_LOAD_DYLINKER: memset((char *)&dyld, '\0', sizeof(struct dylinker_command)); size = left < sizeof(struct dylinker_command) ? left : sizeof(struct dylinker_command); memcpy((char *)&dyld, (char *)lc, size); if(swapped) swap_dylinker_command(&dyld, host_byte_sex); print_dylinker_command(&dyld, lc); break; case LC_FVMFILE: memset((char *)&ff, '\0', sizeof(struct fvmfile_command)); size = left < sizeof(struct fvmfile_command) ? left : sizeof(struct fvmfile_command); memcpy((char *)&ff, (char *)lc, size); if(swapped) swap_fvmfile_command(&ff, host_byte_sex); print_fvmfile_command(&ff, lc); break; case LC_UNIXTHREAD: case LC_THREAD: if(l.cmd == LC_UNIXTHREAD) printf(" cmd LC_UNIXTHREAD\n"); else printf(" cmd LC_THREAD\n"); printf(" cmdsize %u\n", l.cmdsize); if(left <= sizeof(struct thread_command)) break; begin = (char *)lc + sizeof(struct thread_command); if(left >= l.cmdsize) end = (char *)lc + l.cmdsize; else end = (char *)lc + left; print_thread_states(begin, end, cputype, load_commands_byte_sex); break; case LC_IDENT: printf(" cmd LC_IDENT\n"); printf(" cmdsize %u", l.cmdsize); if(l.cmdsize < sizeof(struct ident_command)) printf(" Incorrect size\n"); else printf("\n"); begin = (char *)lc + sizeof(struct ident_command); left -= sizeof(struct ident_command); if(left >= l.cmdsize) end = (char *)lc + l.cmdsize; else end = (char *)lc + left; p = ((char *)lc) + sizeof(struct ident_command); while(begin < end){ if(*begin == '\0'){ begin++; continue; } for(j = 0; begin + j < end && begin[j] != '\0'; j++) ; printf(" ident string %.*s\n", (int)j, begin); begin += j; } break; case LC_ROUTINES: memset((char *)&rc, '\0', sizeof(struct routines_command)); size = left < sizeof(struct routines_command) ? left : sizeof(struct routines_command); memcpy((char *)&rc, (char *)lc, size); if(swapped) swap_routines_command(&rc, host_byte_sex); print_routines_command(&rc); break; case LC_ROUTINES_64: memset((char *)&rc64, '\0', sizeof(struct routines_command_64)); size = left < sizeof(struct routines_command_64) ? left : sizeof(struct routines_command_64); memcpy((char *)&rc64, (char *)lc, size); if(swapped) swap_routines_command_64(&rc64, host_byte_sex); print_routines_command_64(&rc64); break; case LC_TWOLEVEL_HINTS: memset((char *)&hints, '\0', sizeof(struct twolevel_hints_command)); size = left < sizeof(struct twolevel_hints_command) ? left : sizeof(struct twolevel_hints_command); memcpy((char *)&hints, (char *)lc, size); if(swapped) swap_twolevel_hints_command(&hints, host_byte_sex); print_twolevel_hints_command(&hints, object_size); break; case LC_PREBIND_CKSUM: memset((char *)&cs, '\0', sizeof(struct prebind_cksum_command)); size = left < sizeof(struct prebind_cksum_command) ? left : sizeof(struct prebind_cksum_command); memcpy((char *)&cs, (char *)lc, size); if(swapped) swap_prebind_cksum_command(&cs, host_byte_sex); print_prebind_cksum_command(&cs); break; case LC_UUID: memset((char *)&uuid, '\0', sizeof(struct uuid_command)); size = left < sizeof(struct uuid_command) ? left : sizeof(struct uuid_command); memcpy((char *)&uuid, (char *)lc, size); if(swapped) swap_uuid_command(&uuid, host_byte_sex); print_uuid_command(&uuid); break; case LC_CODE_SIGNATURE: case LC_SEGMENT_SPLIT_INFO: memset((char *)&ld, '\0', sizeof(struct linkedit_data_command)); size = left < sizeof(struct linkedit_data_command) ? left : sizeof(struct linkedit_data_command); memcpy((char *)&ld, (char *)lc, size); if(swapped) swap_linkedit_data_command(&ld, host_byte_sex); print_linkedit_data_command(&ld, object_size); break; case LC_RPATH: memset((char *)&rpath, '\0', sizeof(struct rpath_command)); size = left < sizeof(struct rpath_command) ? left : sizeof(struct rpath_command); memcpy((char *)&rpath, (char *)lc, size); if(swapped) swap_rpath_command(&rpath, host_byte_sex); print_rpath_command(&rpath, lc); break; case LC_ENCRYPTION_INFO: memset((char *)&encrypt, '\0', sizeof(struct encryption_info_command)); size = left < sizeof(struct encryption_info_command) ? left : sizeof(struct encryption_info_command); memcpy((char *)&encrypt, (char *)lc, size); if(swapped) swap_encryption_command(&encrypt, host_byte_sex); print_encryption_info_command(&encrypt, object_size); break; default: printf(" cmd ?(0x%08x) Unknown load command\n", (unsigned int)l.cmd); printf(" cmdsize %u\n", l.cmdsize); if(left < sizeof(struct load_command)) return; left -= sizeof(struct load_command); size = left < l.cmdsize - sizeof(struct load_command) ? left : l.cmdsize - sizeof(struct load_command); unknown = allocate(size); memcpy((char *)unknown, ((char *)lc) + sizeof(struct load_command), size); if(swapped) for(j = 0; j < size / sizeof(unsigned long); j++) unknown[j] = SWAP_LONG(unknown[j]); for(j = 0; j < size / sizeof(unsigned long); j += k){ for(k = 0; k < 8 && j + k < size / sizeof(unsigned long); k++) printf("%08x ", (unsigned int)unknown[j + k]); printf("\n"); } break; } if(l.cmdsize == 0){ printf("load command %lu size zero (can't advance to other " "load commands)\n", i); return; } lc = (struct load_command *)((char *)lc + l.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) return; } if((char *)load_commands + sizeofcmds != (char *)lc) printf("Inconsistent sizeofcmds\n"); } void print_libraries( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, enum bool just_id, enum bool verbose) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, left, size; struct load_command *lc, l; struct fvmlib_command fl; struct dylib_command dl; char *p; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; lc = load_commands; for(i = 0 ; i < ncmds; i++){ memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&l, host_byte_sex); if(l.cmdsize % sizeof(long) != 0) printf("load command %lu size not a multiple of sizeof(long)\n", i); if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %lu extends past end of load commands\n", i); left = sizeofcmds - ((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_IDFVMLIB: case LC_LOADFVMLIB: if(just_id == TRUE) break; memset((char *)&fl, '\0', sizeof(struct fvmlib_command)); size = left < sizeof(struct fvmlib_command) ? left : sizeof(struct fvmlib_command); memcpy((char *)&fl, (char *)lc, size); if(swapped) swap_fvmlib_command(&fl, host_byte_sex); if(fl.fvmlib.name.offset < fl.cmdsize){ p = (char *)lc + fl.fvmlib.name.offset; printf("\t%s (minor version %u)\n", p, fl.fvmlib.minor_version); } else{ printf("\tBad offset (%u) for name of %s command %lu\n", fl.fvmlib.name.offset, l.cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" : "LC_LOADFVMLIB" , i); } break; case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: case LC_REEXPORT_DYLIB: if(just_id == TRUE) break; case LC_ID_DYLIB: memset((char *)&dl, '\0', sizeof(struct dylib_command)); size = left < sizeof(struct dylib_command) ? left : sizeof(struct dylib_command); memcpy((char *)&dl, (char *)lc, size); if(swapped) swap_dylib_command(&dl, host_byte_sex); if(dl.dylib.name.offset < dl.cmdsize){ p = (char *)lc + dl.dylib.name.offset; if(just_id == TRUE) printf("%s\n", p); else printf("\t%s (compatibility version %u.%u.%u, " "current version %u.%u.%u)\n", p, dl.dylib.compatibility_version >> 16, (dl.dylib.compatibility_version >> 8) & 0xff, dl.dylib.compatibility_version & 0xff, dl.dylib.current_version >> 16, (dl.dylib.current_version >> 8) & 0xff, dl.dylib.current_version & 0xff); if(verbose){ printf("\ttime stamp %u ", dl.dylib.timestamp); printf("%s",ctime((const long *)&(dl.dylib.timestamp))); } } else{ printf("\tBad offset (%u) for name of ", dl.dylib.name.offset); if(l.cmd == LC_ID_DYLIB) printf("LC_ID_DYLIB "); else if(l.cmd == LC_LOAD_DYLIB) printf("LC_LOAD_DYLIB "); else if(l.cmd == LC_LOAD_WEAK_DYLIB) printf("LC_LOAD_WEAK_DYLIB "); else if(l.cmd == LC_REEXPORT_DYLIB) printf("LC_LOAD_WEAK_DYLIB "); else printf("LC_??? "); printf("command %lu\n", i); } break; } if(l.cmdsize == 0){ printf("load command %lu size zero (can't advance to other " "load commands)\n", i); return; } lc = (struct load_command *)((char *)lc + l.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) return; } if((char *)load_commands + sizeofcmds != (char *)lc) printf("Inconsistent sizeofcmds\n"); } /* * print an LC_SEGMENT command. The fields of the segment_command must * be in the host byte sex. */ void print_segment_command( uint32_t cmd, uint32_t cmdsize, char *segname, uint64_t vmaddr, uint64_t vmsize, uint64_t fileoff, uint64_t filesize, vm_prot_t maxprot, vm_prot_t initprot, uint32_t nsects, uint32_t flags, unsigned long object_size, enum bool verbose) { uint32_t expected_cmdsize; if(cmd == LC_SEGMENT){ printf(" cmd LC_SEGMENT\n"); expected_cmdsize = sizeof(struct segment_command) + nsects * sizeof(struct section); } else{ printf(" cmd LC_SEGMENT_64\n"); expected_cmdsize = sizeof(struct segment_command_64) + nsects * sizeof(struct section_64); } printf(" cmdsize %u", cmdsize); if(cmdsize != expected_cmdsize) printf(" Inconsistent size\n"); else printf("\n"); printf(" segname %.16s\n", segname); if(cmd == LC_SEGMENT_64){ printf(" vmaddr 0x%016llx\n", vmaddr); printf(" vmsize 0x%016llx\n", vmsize); } else{ printf(" vmaddr 0x%08x\n", (uint32_t)vmaddr); printf(" vmsize 0x%08x\n", (uint32_t)vmsize); } printf(" fileoff %llu", fileoff); if(fileoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" filesize %llu", filesize); if(fileoff + filesize > object_size) printf(" (past end of file)\n"); else printf("\n"); if(verbose){ if((maxprot & ~(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)) != 0) printf(" maxprot ?(0x%08x)\n", (unsigned int)maxprot); else{ if(maxprot & VM_PROT_READ) printf(" maxprot r"); else printf(" maxprot -"); if(maxprot & VM_PROT_WRITE) printf("w"); else printf("-"); if(maxprot & VM_PROT_EXECUTE) printf("x\n"); else printf("-\n"); } if((initprot & ~(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)) != 0) printf(" initprot ?(0x%08x)\n", (unsigned int)initprot); else{ if(initprot & VM_PROT_READ) printf(" initprot r"); else printf(" initprot -"); if(initprot & VM_PROT_WRITE) printf("w"); else printf("-"); if(initprot & VM_PROT_EXECUTE) printf("x\n"); else printf("-\n"); } } else{ printf(" maxprot 0x%08x\n", (unsigned int)maxprot); printf(" initprot 0x%08x\n", (unsigned int)initprot); } printf(" nsects %u\n", nsects); if(verbose){ printf(" flags"); if(flags == 0) printf(" (none)\n"); else{ if(flags & SG_HIGHVM){ printf(" HIGHVM"); flags &= ~SG_HIGHVM; } if(flags & SG_FVMLIB){ printf(" FVMLIB"); flags &= ~SG_FVMLIB; } if(flags & SG_NORELOC){ printf(" NORELOC"); flags &= ~SG_NORELOC; } if(flags & SG_PROTECTED_VERSION_1){ printf(" PROTECTED_VERSION_1"); flags &= ~SG_PROTECTED_VERSION_1; } if(flags) printf(" 0x%x (unknown flags)\n", (unsigned int)flags); else printf("\n"); } } else{ printf(" flags 0x%x\n", (unsigned int)flags); } } /* * print a section structure. All parameters must be in the host byte sex. */ void print_section( char *sectname, char *segname, uint64_t addr, uint64_t size, uint32_t offset, uint32_t align, uint32_t reloff, uint32_t nreloc, uint32_t flags, uint32_t reserved1, uint32_t reserved2, uint32_t cmd, char *sg_segname, uint32_t filetype, unsigned long object_size, enum bool verbose) { unsigned long section_type, section_attributes; printf("Section\n"); printf(" sectname %.16s\n", sectname); printf(" segname %.16s", segname); if(filetype != MH_OBJECT && strcmp(sg_segname, segname) != 0) printf(" (does not match segment)\n"); else printf("\n"); if(cmd == LC_SEGMENT_64){ printf(" addr 0x%016llx\n", addr); printf(" size 0x%016llx", size); } else{ printf(" addr 0x%08x\n", (uint32_t)addr); printf(" size 0x%08x", (uint32_t)size); } if((flags & S_ZEROFILL) != 0 && offset + size > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" offset %u", offset); if(offset > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" align 2^%u (%d)\n", align, 1 << align); printf(" reloff %u", reloff); if(reloff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nreloc %u", nreloc); if(reloff + nreloc * sizeof(struct relocation_info) > object_size) printf(" (past end of file)\n"); else printf("\n"); section_type = flags & SECTION_TYPE; if(verbose){ printf(" type"); if(section_type == S_REGULAR) printf(" S_REGULAR\n"); else if(section_type == S_ZEROFILL) printf(" S_ZEROFILL\n"); else if(section_type == S_CSTRING_LITERALS) printf(" S_CSTRING_LITERALS\n"); else if(section_type == S_4BYTE_LITERALS) printf(" S_4BYTE_LITERALS\n"); else if(section_type == S_8BYTE_LITERALS) printf(" S_8BYTE_LITERALS\n"); else if(section_type == S_LITERAL_POINTERS) printf(" S_LITERAL_POINTERS\n"); else if(section_type == S_NON_LAZY_SYMBOL_POINTERS) printf(" S_NON_LAZY_SYMBOL_POINTERS\n"); else if(section_type == S_LAZY_SYMBOL_POINTERS) printf(" S_LAZY_SYMBOL_POINTERS\n"); else if(section_type == S_SYMBOL_STUBS) printf(" S_SYMBOL_STUBS\n"); else if(section_type == S_MOD_INIT_FUNC_POINTERS) printf(" S_MOD_INIT_FUNC_POINTERS\n"); else if(section_type == S_MOD_TERM_FUNC_POINTERS) printf(" S_MOD_TERM_FUNC_POINTERS\n"); else if(section_type == S_COALESCED) printf(" S_COALESCED\n"); else if(section_type == S_INTERPOSING) printf(" S_INTERPOSING\n"); else printf(" 0x%08x\n", (unsigned int)section_type); printf("attributes"); section_attributes = flags & SECTION_ATTRIBUTES; if(section_attributes & S_ATTR_PURE_INSTRUCTIONS) printf(" PURE_INSTRUCTIONS"); if(section_attributes & S_ATTR_NO_TOC) printf(" NO_TOC"); if(section_attributes & S_ATTR_STRIP_STATIC_SYMS) printf(" STRIP_STATIC_SYMS"); if(section_attributes & S_ATTR_NO_DEAD_STRIP) printf(" NO_DEAD_STRIP"); if(section_attributes & S_ATTR_LIVE_SUPPORT) printf(" LIVE_SUPPORT"); if(section_attributes & S_ATTR_SELF_MODIFYING_CODE) printf(" SELF_MODIFYING_CODE"); if(section_attributes & S_ATTR_DEBUG) printf(" DEBUG"); if(section_attributes & S_ATTR_SOME_INSTRUCTIONS) printf(" SOME_INSTRUCTIONS"); if(section_attributes & S_ATTR_EXT_RELOC) printf(" EXT_RELOC"); if(section_attributes & S_ATTR_LOC_RELOC) printf(" LOC_RELOC"); if(section_attributes == 0) printf(" (none)"); printf("\n"); } else printf(" flags 0x%08x\n", (unsigned int)flags); printf(" reserved1 %u", reserved1); if(section_type == S_SYMBOL_STUBS || section_type == S_LAZY_SYMBOL_POINTERS || section_type == S_NON_LAZY_SYMBOL_POINTERS) printf(" (index into indirect symbol table)\n"); else printf("\n"); printf(" reserved2 %u", reserved2); if(section_type == S_SYMBOL_STUBS) printf(" (size of stubs)\n"); else printf("\n"); } /* * print an LC_SYMTAB command. The symtab_command structure specified must * be aligned correctly and in the host byte sex. */ void print_symtab_command( struct symtab_command *st, cpu_type_t cputype, unsigned long object_size) { printf(" cmd LC_SYMTAB\n"); printf(" cmdsize %u", st->cmdsize); if(st->cmdsize != sizeof(struct symtab_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" symoff %u", st->symoff); if(st->symoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nsyms %u", st->nsyms); if(cputype & CPU_ARCH_ABI64){ if(st->symoff + st->nsyms * sizeof(struct nlist_64) > object_size) printf(" (past end of file)\n"); else printf("\n"); } else{ if(st->symoff + st->nsyms * sizeof(struct nlist) > object_size) printf(" (past end of file)\n"); else printf("\n"); } printf(" stroff %u", st->stroff); if(st->stroff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" strsize %u", st->strsize); if(st->stroff + st->strsize > object_size) printf(" (past end of file)\n"); else printf("\n"); } /* * print an LC_DYSYMTAB command. The dysymtab_command structure specified must * be aligned correctly and in the host byte sex. */ void print_dysymtab_command( struct dysymtab_command *dyst, unsigned long nsyms, unsigned long object_size, cpu_type_t cputype) { uint32_t modtabend; printf(" cmd LC_DYSYMTAB\n"); printf(" cmdsize %u", dyst->cmdsize); if(dyst->cmdsize != sizeof(struct dysymtab_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" ilocalsym %u", dyst->ilocalsym); if(dyst->ilocalsym > nsyms) printf(" (greater than the number of symbols)\n"); else printf("\n"); printf(" nlocalsym %u", dyst->nlocalsym); if(dyst->ilocalsym + dyst->nlocalsym > nsyms) printf(" (past the end of the symbol table)\n"); else printf("\n"); printf(" iextdefsym %u", dyst->iextdefsym); if(dyst->iextdefsym > nsyms) printf(" (greater than the number of symbols)\n"); else printf("\n"); printf(" nextdefsym %u", dyst->nextdefsym); if(dyst->iextdefsym + dyst->nextdefsym > nsyms) printf(" (past the end of the symbol table)\n"); else printf("\n"); printf(" iundefsym %u", dyst->iundefsym); if(dyst->iundefsym > nsyms) printf(" (greater than the number of symbols)\n"); else printf("\n"); printf(" nundefsym %u", dyst->nundefsym); if(dyst->iundefsym + dyst->nundefsym > nsyms) printf(" (past the end of the symbol table)\n"); else printf("\n"); printf(" tocoff %u", dyst->tocoff); if(dyst->tocoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" ntoc %u", dyst->ntoc); if(dyst->tocoff + dyst->ntoc * sizeof(struct dylib_table_of_contents) > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" modtaboff %u", dyst->modtaboff); if(dyst->modtaboff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nmodtab %u", dyst->nmodtab); if(cputype & CPU_ARCH_ABI64) modtabend = dyst->modtaboff + dyst->nmodtab * sizeof(struct dylib_module_64); else modtabend = dyst->modtaboff + dyst->nmodtab * sizeof(struct dylib_module); if(modtabend > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" extrefsymoff %u", dyst->extrefsymoff); if(dyst->extrefsymoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nextrefsyms %u", dyst->nextrefsyms); if(dyst->extrefsymoff + dyst->nextrefsyms * sizeof(struct dylib_reference) > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" indirectsymoff %u", dyst->indirectsymoff); if(dyst->indirectsymoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nindirectsyms %u", dyst->nindirectsyms); if(dyst->indirectsymoff + dyst->nindirectsyms * sizeof(unsigned long) > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" extreloff %u", dyst->extreloff); if(dyst->extreloff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nextrel %u", dyst->nextrel); if(dyst->extreloff + dyst->nextrel * sizeof(struct relocation_info) > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" locreloff %u", dyst->locreloff); if(dyst->locreloff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nlocrel %u", dyst->nlocrel); if(dyst->locreloff + dyst->nlocrel * sizeof(struct relocation_info) > object_size) printf(" (past end of file)\n"); else printf("\n"); } /* * print an LC_SYMSEG command. The symseg_command structure specified must * be aligned correctly and in the host byte sex. */ void print_symseg_command( struct symseg_command *ss, unsigned long object_size) { printf(" cmd LC_SYMSEG (obsolete)\n"); printf(" cmdsize %u", ss->cmdsize); if(ss->cmdsize != sizeof(struct symseg_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" offset %u", ss->offset); if(ss->offset > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" size %u", ss->size); if(ss->offset + ss->size > object_size) printf(" (past end of file)\n"); else printf("\n"); } /* * print an LC_IDFVMLIB or LC_LOADFVMLIB command. The fvmlib_command structure * specified must be aligned correctly and in the host byte sex. */ void print_fvmlib_command( struct fvmlib_command *fl, struct load_command *lc) { char *p; if(fl->cmd == LC_IDFVMLIB) printf(" cmd LC_IDFVMLIB\n"); else printf(" cmd LC_LOADFVMLIB\n"); printf(" cmdsize %u", fl->cmdsize); if(fl->cmdsize < sizeof(struct fvmlib_command)) printf(" Incorrect size\n"); else printf("\n"); if(fl->fvmlib.name.offset < fl->cmdsize){ p = (char *)lc + fl->fvmlib.name.offset; printf(" name %s (offset %u)\n", p, fl->fvmlib.name.offset); } else{ printf(" name ?(bad offset %u)\n", fl->fvmlib.name.offset); } printf(" minor version %u\n", fl->fvmlib.minor_version); printf(" header addr 0x%08x\n", (unsigned int)fl->fvmlib.header_addr); } /* * print an LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB or LC_REEXPORT_DYLIB * command. The dylib_command structure specified must be aligned correctly and * in the host byte sex. */ void print_dylib_command( struct dylib_command *dl, struct load_command *lc) { char *p; if(dl->cmd == LC_ID_DYLIB) printf(" cmd LC_ID_DYLIB\n"); else if(dl->cmd == LC_LOAD_DYLIB) printf(" cmd LC_LOAD_DYLIB\n"); else if(dl->cmd == LC_LOAD_WEAK_DYLIB) printf(" cmd LC_LOAD_WEAK_DYLIB\n"); else if(dl->cmd == LC_REEXPORT_DYLIB) printf(" cmd LC_REEXPORT_DYLIB\n"); else printf(" cmd %u (unknown)\n", dl->cmd); printf(" cmdsize %u", dl->cmdsize); if(dl->cmdsize < sizeof(struct dylib_command)) printf(" Incorrect size\n"); else printf("\n"); if(dl->dylib.name.offset < dl->cmdsize){ p = (char *)lc + dl->dylib.name.offset; printf(" name %s (offset %u)\n", p, dl->dylib.name.offset); } else{ printf(" name ?(bad offset %u)\n", dl->dylib.name.offset); } printf(" time stamp %u ", dl->dylib.timestamp); printf("%s", ctime((const long *)&(dl->dylib.timestamp))); printf(" current version %u.%u.%u\n", dl->dylib.current_version >> 16, (dl->dylib.current_version >> 8) & 0xff, dl->dylib.current_version & 0xff); printf("compatibility version %u.%u.%u\n", dl->dylib.compatibility_version >> 16, (dl->dylib.compatibility_version >> 8) & 0xff, dl->dylib.compatibility_version & 0xff); } /* * print an LC_SUB_FRAMEWORK command. The sub_framework_command * structure specified must be aligned correctly and in the host byte sex. */ void print_sub_framework_command( struct sub_framework_command *sub, struct load_command *lc) { char *p; printf(" cmd LC_SUB_FRAMEWORK\n"); printf(" cmdsize %u", sub->cmdsize); if(sub->cmdsize < sizeof(struct sub_framework_command)) printf(" Incorrect size\n"); else printf("\n"); if(sub->umbrella.offset < sub->cmdsize){ p = (char *)lc + sub->umbrella.offset; printf(" umbrella %s (offset %u)\n", p, sub->umbrella.offset); } else{ printf(" umbrella ?(bad offset %u)\n", sub->umbrella.offset); } } /* * print an LC_SUB_UMBRELLA command. The sub_umbrella_command * structure specified must be aligned correctly and in the host byte sex. */ void print_sub_umbrella_command( struct sub_umbrella_command *usub, struct load_command *lc) { char *p; printf(" cmd LC_SUB_UMBRELLA\n"); printf(" cmdsize %u", usub->cmdsize); if(usub->cmdsize < sizeof(struct sub_umbrella_command)) printf(" Incorrect size\n"); else printf("\n"); if(usub->sub_umbrella.offset < usub->cmdsize){ p = (char *)lc + usub->sub_umbrella.offset; printf(" sub_umbrella %s (offset %u)\n", p, usub->sub_umbrella.offset); } else{ printf(" sub_umbrella ?(bad offset %u)\n", usub->sub_umbrella.offset); } } /* * print an LC_SUB_LIBRARY command. The sub_library_command * structure specified must be aligned correctly and in the host byte sex. */ void print_sub_library_command( struct sub_library_command *lsub, struct load_command *lc) { char *p; printf(" cmd LC_SUB_LIBRARY\n"); printf(" cmdsize %u", lsub->cmdsize); if(lsub->cmdsize < sizeof(struct sub_library_command)) printf(" Incorrect size\n"); else printf("\n"); if(lsub->sub_library.offset < lsub->cmdsize){ p = (char *)lc + lsub->sub_library.offset; printf(" sub_library %s (offset %u)\n", p, lsub->sub_library.offset); } else{ printf(" sub_library ?(bad offset %u)\n", lsub->sub_library.offset); } } /* * print an LC_SUB_CLIENT command. The sub_client_command * structure specified must be aligned correctly and in the host byte sex. */ void print_sub_client_command( struct sub_client_command *csub, struct load_command *lc) { char *p; printf(" cmd LC_SUB_CLIENT\n"); printf(" cmdsize %u", csub->cmdsize); if(csub->cmdsize < sizeof(struct sub_client_command)) printf(" Incorrect size\n"); else printf("\n"); if(csub->client.offset < csub->cmdsize){ p = (char *)lc + csub->client.offset; printf(" client %s (offset %u)\n", p, csub->client.offset); } else{ printf(" client ?(bad offset %u)\n", csub->client.offset); } } /* * print an LC_PREBOUND_DYLIB command. The prebound_dylib_command structure * specified must be aligned correctly and in the host byte sex. */ void print_prebound_dylib_command( struct prebound_dylib_command *pbdylib, struct load_command *lc, enum bool verbose) { char *p; unsigned long i; printf(" cmd LC_PREBOUND_DYLIB\n"); printf(" cmdsize %u", pbdylib->cmdsize); if(pbdylib->cmdsize < sizeof(struct prebound_dylib_command)) printf(" Incorrect size\n"); else printf("\n"); if(pbdylib->name.offset < pbdylib->cmdsize){ p = (char *)lc + pbdylib->name.offset; printf(" name %s (offset %u)\n", p, pbdylib->name.offset); } else{ printf(" name ?(bad offset %u)\n", pbdylib->name.offset); } printf(" nmodules %u\n", pbdylib->nmodules); if(pbdylib->linked_modules.offset < pbdylib->cmdsize){ p = (char *)lc + pbdylib->linked_modules.offset; if(verbose == TRUE){ printf(" linked_modules (offset %u)\n", pbdylib->linked_modules.offset); for(i = 0; i < pbdylib->nmodules; i++){ if(((p[i/8] >> (i%8)) & 1) == 1) printf("%lu\n", i); } } else{ printf(" linked_modules "); for(i = 0; i < pbdylib->nmodules && i < 8; i++){ if(((*p >> i) & 1) == 0) printf("0"); else printf("1"); } if(i <= pbdylib->nmodules) printf("..."); printf(" (offset %u)\n", pbdylib->linked_modules.offset); } } else{ printf(" linked_modules ?(bad offset %u)\n", pbdylib->linked_modules.offset); } } /* * print an LC_ID_DYLINKER or LC_LOAD_DYLINKER command. The dylinker_command * structure specified must be aligned correctly and in the host byte sex. */ void print_dylinker_command( struct dylinker_command *dyld, struct load_command *lc) { char *p; if(dyld->cmd == LC_ID_DYLINKER) printf(" cmd LC_ID_DYLINKER\n"); else printf(" cmd LC_LOAD_DYLINKER\n"); printf(" cmdsize %u", dyld->cmdsize); if(dyld->cmdsize < sizeof(struct dylinker_command)) printf(" Incorrect size\n"); else printf("\n"); if(dyld->name.offset < dyld->cmdsize){ p = (char *)lc + dyld->name.offset; printf(" name %s (offset %u)\n", p, dyld->name.offset); } else{ printf(" name ?(bad offset %u)\n", dyld->name.offset); } } /* * print an LC_FVMFILE command. The fvmfile_command structure specified must * be aligned correctly and in the host byte sex. */ void print_fvmfile_command( struct fvmfile_command *ff, struct load_command *lc) { char *p; printf(" cmd LC_FVMFILE\n"); printf(" cmdsize %u", ff->cmdsize); if(ff->cmdsize < sizeof(struct fvmfile_command)) printf(" Incorrect size\n"); else printf("\n"); if(ff->name.offset < ff->cmdsize){ p = (char *)lc + ff->name.offset; printf(" name %s (offset %u)\n", p, ff->name.offset); } else{ printf(" name ?(bad offset %u)\n", ff->name.offset); } printf(" header addr 0x%08x\n", (unsigned int)ff->header_addr); } /* * print an LC_ROUTINES command. The routines_command structure specified must * be aligned correctly and in the host byte sex. */ void print_routines_command( struct routines_command *rc) { printf(" cmd LC_ROUTINES\n"); printf(" cmdsize %u", rc->cmdsize); if(rc->cmdsize != sizeof(struct routines_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" init_address 0x%08x\n", rc->init_address); printf(" init_module %u\n", rc->init_module); printf(" reserved1 %u\n", rc->reserved1); printf(" reserved2 %u\n", rc->reserved2); printf(" reserved3 %u\n", rc->reserved3); printf(" reserved4 %u\n", rc->reserved4); printf(" reserved5 %u\n", rc->reserved5); printf(" reserved6 %u\n", rc->reserved6); } /* * print an LC_ROUTINES_64 command. The routines_command_64 structure specified * must be aligned correctly and in the host byte sex. */ void print_routines_command_64( struct routines_command_64 *rc64) { printf(" cmd LC_ROUTINES_64\n"); printf(" cmdsize %u", rc64->cmdsize); if(rc64->cmdsize != sizeof(struct routines_command_64)) printf(" Incorrect size\n"); else printf("\n"); printf(" init_address 0x%016llx\n", rc64->init_address); printf(" init_module %llu\n", rc64->init_module); printf(" reserved1 %llu\n", rc64->reserved1); printf(" reserved2 %llu\n", rc64->reserved2); printf(" reserved3 %llu\n", rc64->reserved3); printf(" reserved4 %llu\n", rc64->reserved4); printf(" reserved5 %llu\n", rc64->reserved5); printf(" reserved6 %llu\n", rc64->reserved6); } /* * print an LC_TWOLEVEL_HINTS command. The twolevel_hints_command structure * specified must be aligned correctly and in the host byte sex. */ void print_twolevel_hints_command( struct twolevel_hints_command *hints, unsigned long object_size) { printf(" cmd LC_TWOLEVEL_HINTS\n"); printf(" cmdsize %u", hints->cmdsize); if(hints->cmdsize != sizeof(struct twolevel_hints_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" offset %u", hints->offset); if(hints->offset > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" nhints %u", hints->nhints); if(hints->offset + hints->nhints * sizeof(struct twolevel_hint) > object_size) printf(" (past end of file)\n"); else printf("\n"); } /* * print an LC_PREBIND_CKSUM command. The prebind_cksum_command structure * specified must be aligned correctly and in the host byte sex. */ void print_prebind_cksum_command( struct prebind_cksum_command *cksum) { printf(" cmd LC_PREBIND_CKSUM\n"); printf(" cmdsize %u", cksum->cmdsize); if(cksum->cmdsize != sizeof(struct prebind_cksum_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" cksum 0x%08x\n", (unsigned int)cksum->cksum); } /* * print an LC_UUID command. The uuid_command structure * specified must be aligned correctly and in the host byte sex. */ void print_uuid_command( struct uuid_command *uuid) { printf(" cmd LC_UUID\n"); printf(" cmdsize %u", uuid->cmdsize); if(uuid->cmdsize != sizeof(struct uuid_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" uuid 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x" "\n", (unsigned int)uuid->uuid[0], (unsigned int)uuid->uuid[1], (unsigned int)uuid->uuid[2], (unsigned int)uuid->uuid[3], (unsigned int)uuid->uuid[4], (unsigned int)uuid->uuid[5], (unsigned int)uuid->uuid[6], (unsigned int)uuid->uuid[7]); printf(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x" "\n", (unsigned int)uuid->uuid[8], (unsigned int)uuid->uuid[9], (unsigned int)uuid->uuid[10], (unsigned int)uuid->uuid[11], (unsigned int)uuid->uuid[12], (unsigned int)uuid->uuid[13], (unsigned int)uuid->uuid[14], (unsigned int)uuid->uuid[15]); } /* * print a linkedit_data_command. The linkedit_data_command structure * specified must be aligned correctly and in the host byte sex. */ void print_linkedit_data_command( struct linkedit_data_command *ld, unsigned long object_size) { if(ld->cmd == LC_CODE_SIGNATURE) printf(" cmd LC_CODE_SIGNATURE\n"); else if(ld->cmd == LC_SEGMENT_SPLIT_INFO) printf(" cmd LC_SEGMENT_SPLIT_INFO\n"); else printf(" cmd %u (?)\n", ld->cmd); printf(" cmdsize %u", ld->cmdsize); if(ld->cmdsize != sizeof(struct linkedit_data_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" dataoff %u", ld->dataoff); if(ld->dataoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" datasize %u", ld->datasize); if(ld->dataoff + ld->datasize > object_size) printf(" (past end of file)\n"); else printf("\n"); } /* * print an LC_RPATH command. The rpath_command structure specified must be * aligned correctly and in the host byte sex. */ void print_rpath_command( struct rpath_command *rpath, struct load_command *lc) { char *p; printf(" cmd LC_RPATH\n"); printf(" cmdsize %u", rpath->cmdsize); if(rpath->cmdsize < sizeof(struct rpath_command)) printf(" Incorrect size\n"); else printf("\n"); if(rpath->path.offset < rpath->cmdsize){ p = (char *)lc + rpath->path.offset; printf(" path %s (offset %u)\n", p, rpath->path.offset); } else{ printf(" path ?(bad offset %u)\n", rpath->path.offset); } } /* * print an LC_ENCRYPTION_INFO command. The encryption_info_command structure * specified must be aligned correctly and in the host byte sex. */ void print_encryption_info_command( struct encryption_info_command *ec, unsigned long object_size) { printf(" cmd LC_ENCRYPTION_INFO\n"); printf(" cmdsize %u", ec->cmdsize); if(ec->cmdsize < sizeof(struct encryption_info_command)) printf(" Incorrect size\n"); else printf("\n"); printf(" cryptoff %u", ec->cryptoff); if(ec->cryptoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" cryptsize %u", ec->cryptsize); if(ec->cryptsize + ec->cryptoff > object_size) printf(" (past end of file)\n"); else printf("\n"); printf(" cryptid %u\n", ec->cryptid); } /* * print the thread states from an LC_THREAD or LC_UNIXTHREAD command. The * thread state triples (flavor, count, state) are in memory between begin and * and end values specified, and in the specified byte sex. The mach_header * structure specified must be aligned correctly and in the host byte sex. */ void print_thread_states( char *begin, char *end, cpu_type_t cputype, enum byte_sex thread_states_byte_sex) { unsigned long i, j, k, flavor, count, left; enum byte_sex host_byte_sex; enum bool swapped; i = 0; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != thread_states_byte_sex; if(cputype == CPU_TYPE_MC680x0){ struct m68k_thread_state_regs cpu; struct m68k_thread_state_68882 fpu; struct m68k_thread_state_user_reg user_reg; while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case M68K_THREAD_STATE_REGS: printf(" flavor M68K_THREAD_STATE_REGS\n"); if(count == M68K_THREAD_STATE_REGS_COUNT) printf(" count M68K_THREAD_STATE_" "REGS_COUNT\n"); else printf(" count %lu (not M68K_THREAD_STATE_" "REGS_COUNT)\n", count); left = end - begin; if(left >= sizeof(struct m68k_thread_state_regs)){ memcpy((char *)&cpu, begin, sizeof(struct m68k_thread_state_regs)); begin += sizeof(struct m68k_thread_state_regs); } else{ memset((char *)&cpu, '\0', sizeof(struct m68k_thread_state_regs)); memcpy((char *)&cpu, begin, left); begin += left; } if(swapped) swap_m68k_thread_state_regs(&cpu, host_byte_sex); printf(" dregs "); for(j = 0 ; j < 8 ; j++) printf(" %08x", (unsigned int)cpu.dreg[j]); printf("\n"); printf(" aregs "); for(j = 0 ; j < 8 ; j++) printf(" %08x", (unsigned int)cpu.areg[j]); printf("\n"); printf(" pad 0x%04x sr 0x%04x pc 0x%08x\n", (unsigned int)(cpu.pad0 & 0x0000ffff), (unsigned int)(cpu.sr & 0x0000ffff), (unsigned int)cpu.pc); break; case M68K_THREAD_STATE_68882: printf(" flavor M68K_THREAD_STATE_68882\n"); if(count == M68K_THREAD_STATE_68882_COUNT) printf(" count M68K_THREAD_STATE_" "68882_COUNT\n"); else printf(" count %lu (not M68K_THREAD_STATE_" "68882_COUNT\n", count); left = end - begin; if(left >= sizeof(struct m68k_thread_state_68882)){ memcpy((char *)&fpu, begin, sizeof(struct m68k_thread_state_68882)); begin += sizeof(struct m68k_thread_state_68882); } else{ memset((char *)&fpu, '\0', sizeof(struct m68k_thread_state_68882)); memcpy((char *)&fpu, begin, left); begin += left; } if(swapped) swap_m68k_thread_state_68882(&fpu, host_byte_sex); for(j = 0 ; j < 8 ; j++) printf(" fp reg %lu %08x %08x %08x\n", j, (unsigned int)fpu.regs[j].fp[0], (unsigned int)fpu.regs[j].fp[1], (unsigned int)fpu.regs[j].fp[2]); printf(" cr 0x%08x sr 0x%08x state 0x%08x\n", (unsigned int)fpu.cr, (unsigned int)fpu.sr, (unsigned int)fpu.state); break; case M68K_THREAD_STATE_USER_REG: printf(" flavor M68K_THREAD_STATE_USER_REG\n"); if(count == M68K_THREAD_STATE_USER_REG_COUNT) printf(" count M68K_THREAD_STATE_" "USER_REG_COUNT\n"); else printf(" count %lu (not M68K_THREAD_STATE_" "USER_REG_COUNT", count); left = end - begin; if(left >= sizeof(struct m68k_thread_state_user_reg)){ memcpy((char *)&user_reg, begin, sizeof(struct m68k_thread_state_user_reg)); begin += sizeof(struct m68k_thread_state_user_reg); } else{ memset((char *)&user_reg, '\0', sizeof(struct m68k_thread_state_user_reg)); memcpy((char *)&user_reg, begin, left); begin += left; } if(swapped) swap_m68k_thread_state_user_reg(&user_reg, host_byte_sex); printf(" user_reg 0x%08x\n", (unsigned int)user_reg.user_reg); break; default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else if(cputype == CPU_TYPE_HPPA){ while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case HPPA_INTEGER_THREAD_STATE: { struct hp_pa_integer_thread_state frame; printf(" flavor HPPA_INTEGER_THREAD_STATE\n"); if(count == HPPA_INTEGER_THREAD_STATE_COUNT) printf(" count HPPA_INTEGER_THREAD_STATE_COUNT\n"); else printf(" count %lu (not HPPA_INTEGER_THREAD_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(struct hp_pa_integer_thread_state)){ memcpy((char *)&frame, begin, sizeof(struct hp_pa_integer_thread_state)); begin += sizeof(struct hp_pa_integer_thread_state); } else{ memset((char *)&frame, '\0', sizeof(struct hp_pa_integer_thread_state)); memcpy((char *)&frame, begin, left); begin += left; } if(swapped) swap_hppa_integer_thread_state(&frame, host_byte_sex); printf( "r1 0x%08lx r2 0x%08lx r3 0x%08lx r4 0x%08lx\n" "r5 0x%08lx r6 0x%08lx r7 0x%08lx r8 0x%08lx\n" "r9 0x%08lx r10 0x%08lx r11 0x%08lx r12 0x%08lx\n" "r13 0x%08lx r14 0x%08lx r15 0x%08lx r16 0x%08lx\n" "r17 0x%08lx r18 0x%08lx r19 0x%08lx r20 0x%08lx\n" "r21 0x%08lx r22 0x%08lx r23 0x%08lx r24 0x%08lx\n" "r25 0x%08lx r26 0x%08lx r27 0x%08lx r28 0x%08lx\n" "r29 0x%08lx r30 0x%08lx r31 0x%08lx\n" "sr0 0x%08lx sr1 0x%08lx sr2 0x%08lx sar 0x%08lx\n", frame.ts_gr1, frame.ts_gr2, frame.ts_gr3, frame.ts_gr4, frame.ts_gr5, frame.ts_gr6, frame.ts_gr7, frame.ts_gr8, frame.ts_gr9, frame.ts_gr10, frame.ts_gr11, frame.ts_gr12, frame.ts_gr13, frame.ts_gr14, frame.ts_gr15, frame.ts_gr16, frame.ts_gr17, frame.ts_gr18, frame.ts_gr19, frame.ts_gr20, frame.ts_gr21, frame.ts_gr22, frame.ts_gr23, frame.ts_gr24, frame.ts_gr25, frame.ts_gr26, frame.ts_gr27, frame.ts_gr28, frame.ts_gr29, frame.ts_gr30, frame.ts_gr31, frame.ts_sr0, frame.ts_sr1, frame.ts_sr2, frame.ts_sar); } break; case HPPA_FRAME_THREAD_STATE: { struct hp_pa_frame_thread_state frame; printf(" flavor HPPA_FRAME_THREAD_STATE\n"); if(count == HPPA_FRAME_THREAD_STATE_COUNT) printf(" count HPPA_FRAME_THREAD_STATE_COUNT\n"); else printf(" count %lu (not HPPA_FRAME_THREAD_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(struct hp_pa_frame_thread_state)){ memcpy((char *)&frame, begin, sizeof(struct hp_pa_frame_thread_state)); begin += sizeof(struct hp_pa_frame_thread_state); } else{ memset((char *)&frame, '\0', sizeof(struct hp_pa_frame_thread_state)); memcpy((char *)&frame, begin, left); begin += left; } if(swapped) swap_hppa_frame_thread_state(&frame, host_byte_sex); printf("pcsq_front 0x%08lx pcsq_back 0x%08lx\n" "pcoq_front 0x%08lx pcoq_back 0x%08lx\n" " psw 0x%08lx\n", frame.ts_pcsq_front, frame.ts_pcsq_back, frame.ts_pcoq_front, frame.ts_pcoq_back, frame.ts_psw); break; } case HPPA_FP_THREAD_STATE: { struct hp_pa_fp_thread_state frame; printf(" flavor HPPA_FP_THREAD_STATE\n"); if(count == HPPA_FP_THREAD_STATE_COUNT) printf(" count HPPA_FP_THREAD_STATE_COUNT\n"); else printf(" count %lu (not HPPA_FP_THREAD_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(struct hp_pa_fp_thread_state)){ memcpy((char *)&frame, begin, sizeof(struct hp_pa_fp_thread_state)); begin += sizeof(struct hp_pa_fp_thread_state); } else{ memset((char *)&frame, '\0', sizeof(struct hp_pa_fp_thread_state)); memcpy((char *)&frame, begin, left); begin += left; } if(swapped) swap_hppa_fp_thread_state(&frame, host_byte_sex); printf("fp0 %f fp1 %f\nfp2 %f fp3 %f\n" "fp4 %f fp5 %f\nfp6 %f fp7 %f\n" "fp8 %f fp9 %f\nfp10 %f fp11 %f\n" "fp12 %f fp13 %f\nfp14 %f fp15 %f\n" "fp16 %f fp17 %f\nfp18 %f fp19 %f\n" "fp20 %f fp21 %f\nfp22 %f fp23 %f\n" "fp24 %f fp25 %f\nfp26 %f fp27 %f\n" "fp28 %f fp29 %f\nfp30 %f fp31 %f\n", frame.ts_fp0, frame.ts_fp1, frame.ts_fp2, frame.ts_fp3, frame.ts_fp4, frame.ts_fp5, frame.ts_fp6, frame.ts_fp7, frame.ts_fp8, frame.ts_fp9, frame.ts_fp10, frame.ts_fp11, frame.ts_fp12, frame.ts_fp13, frame.ts_fp14, frame.ts_fp15, frame.ts_fp16, frame.ts_fp17, frame.ts_fp18, frame.ts_fp19, frame.ts_fp20, frame.ts_fp21, frame.ts_fp22, frame.ts_fp23, frame.ts_fp24, frame.ts_fp25, frame.ts_fp26, frame.ts_fp27, frame.ts_fp28, frame.ts_fp29, frame.ts_fp30, frame.ts_fp31); break; } default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else if(cputype == CPU_TYPE_SPARC){ while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case SPARC_THREAD_STATE_REGS: { struct sparc_thread_state_regs cpu; printf(" flavor SPARC_THREAD_STATE_REGS\n"); if (count == SPARC_THREAD_STATE_REGS_COUNT) printf(" count SPARC_THREAD_STATE_REGS_COUNT\n"); else printf(" count %lu (not SPARC_THREAD_STATE_REGS_COUNT)\n", count); left = begin - end; if (left >= sizeof(struct sparc_thread_state_regs)) { memcpy((char *) &cpu, begin, sizeof(struct sparc_thread_state_regs)); begin += sizeof(struct sparc_thread_state_regs); } else { memset((char *) &cpu, '\0', sizeof(struct sparc_thread_state_regs)); begin += left; } if (swapped) swap_sparc_thread_state_regs(&cpu, host_byte_sex); printf( "psr 0x%08x pc 0x%08x npc 0x%08x y 0x%08x\n" "g0 0x%08x g1 0x%08x g2 0x%08x g3 0x%08x\n" "g4 0x%08x g5 0x%08x g6 0x%08x g7 0x%08x\n" "o0 0x%08x o1 0x%08x o2 0x%08x o3 0x%08x\n" "o4 0x%08x o5 0x%08x o6 0x%08x o7 0x%08x\n", cpu.regs.r_psr, cpu.regs.r_pc, cpu.regs.r_npc, cpu.regs.r_y, 0, cpu.regs.r_g1, cpu.regs.r_g2, cpu.regs.r_g3, cpu.regs.r_g4, cpu.regs.r_g5, cpu.regs.r_g6, cpu.regs.r_g7, cpu.regs.r_o0, cpu.regs.r_o1, cpu.regs.r_o2, cpu.regs.r_o3, cpu.regs.r_o4, cpu.regs.r_o5, cpu.regs.r_o6, cpu.regs.r_o7); break; } case SPARC_THREAD_STATE_FPU: { struct sparc_thread_state_fpu fpu; printf(" flavor SPARC_THREAD_STATE_FPU\n"); if (count == SPARC_THREAD_STATE_FPU_COUNT) printf(" count SPARC_THREAD_STATE_FPU_COUNT\n"); else printf(" count %lu (not SPARC_THREAD_STATE_FPU_COUNT)\n", count); left = begin - end; if (left >= sizeof(struct sparc_thread_state_fpu)) { memcpy((char *) &fpu, begin, sizeof(struct sparc_thread_state_fpu)); begin += sizeof(struct sparc_thread_state_fpu); } else { memset((char *) &fpu, '\0', sizeof(struct sparc_thread_state_fpu)); begin += left; } if (swapped) swap_sparc_thread_state_fpu(&fpu, host_byte_sex); printf( "f0 0x%08x f1 0x%08x f2 0x%08x f3 0x%08x\n" "f4 0x%08x f5 0x%08x f6 0x%08x f7 0x%08x\n" "f8 0x%08x f9 0x%08x f10 0x%08x f11 0x%08x\n" "f12 0x%08x f13 0x%08x f14 0x%08x f15 0x%08x\n" "f16 0x%08x f17 0x%08x f18 0x%08x f19 0x%08x\n" "f20 0x%08x f21 0x%08x f22 0x%08x f23 0x%08x\n" "f24 0x%08x f25 0x%08x f26 0x%08x f27 0x%08x\n" "f28 0x%08x f29 0x%08x f30 0x%08x f31 0x%08x\n" "fsr 0x%08x\n", fpu.fpu.fpu_fr.Fpu_regs[0], fpu.fpu.fpu_fr.Fpu_regs[1], fpu.fpu.fpu_fr.Fpu_regs[2], fpu.fpu.fpu_fr.Fpu_regs[3], fpu.fpu.fpu_fr.Fpu_regs[4], fpu.fpu.fpu_fr.Fpu_regs[5], fpu.fpu.fpu_fr.Fpu_regs[6], fpu.fpu.fpu_fr.Fpu_regs[7], fpu.fpu.fpu_fr.Fpu_regs[8], fpu.fpu.fpu_fr.Fpu_regs[9], fpu.fpu.fpu_fr.Fpu_regs[10], fpu.fpu.fpu_fr.Fpu_regs[11], fpu.fpu.fpu_fr.Fpu_regs[12], fpu.fpu.fpu_fr.Fpu_regs[13], fpu.fpu.fpu_fr.Fpu_regs[14], fpu.fpu.fpu_fr.Fpu_regs[15], fpu.fpu.fpu_fr.Fpu_regs[16], fpu.fpu.fpu_fr.Fpu_regs[17], fpu.fpu.fpu_fr.Fpu_regs[18], fpu.fpu.fpu_fr.Fpu_regs[19], fpu.fpu.fpu_fr.Fpu_regs[20], fpu.fpu.fpu_fr.Fpu_regs[21], fpu.fpu.fpu_fr.Fpu_regs[22], fpu.fpu.fpu_fr.Fpu_regs[23], fpu.fpu.fpu_fr.Fpu_regs[24], fpu.fpu.fpu_fr.Fpu_regs[25], fpu.fpu.fpu_fr.Fpu_regs[26], fpu.fpu.fpu_fr.Fpu_regs[27], fpu.fpu.fpu_fr.Fpu_regs[28], fpu.fpu.fpu_fr.Fpu_regs[29], fpu.fpu.fpu_fr.Fpu_regs[30], fpu.fpu.fpu_fr.Fpu_regs[31], fpu.fpu.Fpu_fsr); break; } default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else if(cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO){ ppc_thread_state_t cpu; ppc_thread_state64_t cpu64; ppc_float_state_t fpu; ppc_exception_state_t except; while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case PPC_THREAD_STATE: printf(" flavor PPC_THREAD_STATE\n"); if(count == PPC_THREAD_STATE_COUNT) printf(" count PPC_THREAD_STATE_COUNT\n"); else printf(" count %lu (not PPC_THREAD_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(ppc_thread_state_t)){ memcpy((char *)&cpu, begin, sizeof(ppc_thread_state_t)); begin += sizeof(ppc_thread_state_t); } else{ memset((char *)&cpu, '\0', sizeof(ppc_thread_state_t)); memcpy((char *)&cpu, begin, left); begin += left; } if(swapped) swap_ppc_thread_state_t(&cpu, host_byte_sex); printf(" r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x " "r4 0x%08x\n" " r5 0x%08x r6 0x%08x r7 0x%08x r8 0x%08x " "r9 0x%08x\n" " r10 0x%08x r11 0x%08x r12 0x%08x r13 0x%08x " "r14 0x%08x\n" " r15 0x%08x r16 0x%08x r17 0x%08x r18 0x%08x " "r19 0x%08x\n" " r20 0x%08x r21 0x%08x r22 0x%08x r23 0x%08x " "r24 0x%08x\n" " r25 0x%08x r26 0x%08x r27 0x%08x r28 0x%08x " "r29 0x%08x\n" " r30 0x%08x r31 0x%08x cr 0x%08x xer 0x%08x " "lr 0x%08x\n" " ctr 0x%08x mq 0x%08x vrsave 0x%08x srr0 0x%08x" " srr1 0x%08x\n", cpu.r0, cpu.r1, cpu.r2, cpu.r3, cpu.r4, cpu.r5, cpu.r6, cpu.r7, cpu.r8, cpu.r9, cpu.r10, cpu.r11, cpu.r12, cpu.r13, cpu.r14, cpu.r15, cpu.r16, cpu.r17, cpu.r18, cpu.r19, cpu.r20, cpu.r21, cpu.r22, cpu.r23, cpu.r24, cpu.r25, cpu.r26, cpu.r27, cpu.r28, cpu.r29, cpu.r30, cpu.r31, cpu.cr, cpu.xer, cpu.lr, cpu.ctr, cpu.mq, cpu.vrsave, cpu.srr0, cpu.srr1); break; case PPC_FLOAT_STATE: printf(" flavor PPC_FLOAT_STATE\n"); if(count == PPC_FLOAT_STATE_COUNT) printf(" count PPC_FLOAT_STATE_COUNT\n"); else printf(" count %lu (not PPC_FLOAT_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(ppc_float_state_t)){ memcpy((char *)&fpu, begin, sizeof(ppc_float_state_t)); begin += sizeof(ppc_float_state_t); } else{ memset((char *)&fpu, '\0', sizeof(ppc_float_state_t)); memcpy((char *)&fpu, begin, left); begin += left; } if(swapped) swap_ppc_float_state_t(&fpu, host_byte_sex); printf(" f0 %f f1 %f\n f2 %f f3 %f\n" " f4 %f f5 %f\n f6 %f f7 %f\n" " f8 %f f9 %f\n f10 %f f11 %f\n" " f12 %f f13 %f\n f14 %f f15 %f\n" " f16 %f f17 %f\n f18 %f f19 %f\n" " f20 %f f21 %f\n f22 %f f23 %f\n" " f24 %f f25 %f\n f26 %f f27 %f\n" " f28 %f f29 %f\n f30 %f f31 %f\n", fpu.fpregs[0], fpu.fpregs[1], fpu.fpregs[2], fpu.fpregs[3], fpu.fpregs[4], fpu.fpregs[5], fpu.fpregs[6], fpu.fpregs[7], fpu.fpregs[8], fpu.fpregs[9], fpu.fpregs[10], fpu.fpregs[11], fpu.fpregs[12], fpu.fpregs[13], fpu.fpregs[14], fpu.fpregs[15], fpu.fpregs[16], fpu.fpregs[17], fpu.fpregs[18], fpu.fpregs[19], fpu.fpregs[20], fpu.fpregs[21], fpu.fpregs[22], fpu.fpregs[23], fpu.fpregs[24], fpu.fpregs[25], fpu.fpregs[26], fpu.fpregs[27], fpu.fpregs[28], fpu.fpregs[29], fpu.fpregs[30], fpu.fpregs[31]); printf(" fpscr_pad 0x%x fpscr 0x%x\n", fpu.fpscr_pad, fpu.fpscr); break; case PPC_EXCEPTION_STATE: printf(" flavor PPC_EXCEPTION_STATE\n"); if(count == PPC_EXCEPTION_STATE_COUNT) printf(" count PPC_EXCEPTION_STATE_COUNT\n"); else printf(" count %lu (not PPC_EXCEPTION_STATE_COUNT" ")\n", count); left = end - begin; if(left >= sizeof(ppc_exception_state_t)){ memcpy((char *)&except, begin, sizeof(ppc_exception_state_t)); begin += sizeof(ppc_exception_state_t); } else{ memset((char *)&except, '\0', sizeof(ppc_exception_state_t)); memcpy((char *)&except, begin, left); begin += left; } if(swapped) swap_ppc_exception_state_t(&except, host_byte_sex); printf(" dar 0x%x dsisr 0x%x exception 0x%x pad0 " "0x%x\n", (unsigned int)except.dar, (unsigned int)except.dsisr, (unsigned int)except.exception, (unsigned int)except.pad0); printf(" pad1[0] 0x%x pad1[1] 0x%x pad1[2] " "0x%x pad1[3] 0x%x\n", (unsigned int)except.pad1[0], (unsigned int)except.pad1[0], (unsigned int)except.pad1[0], (unsigned int)except.pad1[0]); break; case PPC_THREAD_STATE64: printf(" flavor PPC_THREAD_STATE64\n"); if(count == PPC_THREAD_STATE64_COUNT) printf(" count PPC_THREAD_STATE64_COUNT\n"); else printf(" count %lu (not PPC_THREAD_STATE64_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(ppc_thread_state64_t)){ memcpy((char *)&cpu64, begin, sizeof(ppc_thread_state64_t)); begin += sizeof(ppc_thread_state64_t); } else{ memset((char *)&cpu64, '\0', sizeof(ppc_thread_state64_t)); memcpy((char *)&cpu64, begin, left); begin += left; } if(swapped) swap_ppc_thread_state64_t(&cpu64, host_byte_sex); printf(" r0 0x%016llx r1 0x%016llx r2 0x%016llx\n" " r3 0x%016llx r4 0x%016llx r5 0x%016llx\n" " r6 0x%016llx r7 0x%016llx r8 0x%016llx\n" " r9 0x%016llx r10 0x%016llx r11 0x%016llx\n" " r12 0x%016llx r13 0x%016llx r14 0x%016llx\n" " r15 0x%016llx r16 0x%016llx r17 0x%016llx\n" " r18 0x%016llx r19 0x%016llx r20 0x%016llx\n" " r21 0x%016llx r22 0x%016llx r23 0x%016llx\n" " r24 0x%016llx r25 0x%016llx r26 0x%016llx\n" " r27 0x%016llx r28 0x%016llx r29 0x%016llx\n" " r30 0x%016llx r31 0x%016llx cr 0x%08x\n" " xer 0x%016llx lr 0x%016llx ctr 0x%016llx\n" "vrsave 0x%08x srr0 0x%016llx srr1 " "0x%016llx\n", cpu64.r0, cpu64.r1, cpu64.r2, cpu64.r3, cpu64.r4, cpu64.r5, cpu64.r6, cpu64.r7, cpu64.r8, cpu64.r9, cpu64.r10, cpu64.r11, cpu64.r12, cpu64.r13,cpu64.r14, cpu64.r15, cpu64.r16, cpu64.r17, cpu64.r18,cpu64.r19, cpu64.r20, cpu64.r21, cpu64.r22, cpu64.r23,cpu64.r24, cpu64.r25, cpu64.r26, cpu64.r27, cpu64.r28,cpu64.r29, cpu64.r30, cpu64.r31, cpu64.cr, cpu64.xer, cpu64.lr, cpu64.ctr, cpu64.vrsave, cpu64.srr0, cpu64.srr1); break; default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else if(cputype == CPU_TYPE_MC88000){ m88k_thread_state_grf_t cpu; m88k_thread_state_xrf_t fpu; m88k_thread_state_user_t user; m88110_thread_state_impl_t spu; while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case M88K_THREAD_STATE_GRF: printf(" flavor M88K_THREAD_STATE_GRF\n"); if(count == M88K_THREAD_STATE_GRF_COUNT) printf(" count M88K_THREAD_STATE_GRF_COUNT\n"); else printf(" count %lu (not M88K_THREAD_STATE_GRF_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(m88k_thread_state_grf_t)){ memcpy((char *)&cpu, begin, sizeof(m88k_thread_state_grf_t)); begin += sizeof(m88k_thread_state_grf_t); } else{ memset((char *)&cpu, '\0', sizeof(m88k_thread_state_grf_t)); memcpy((char *)&cpu, begin, left); begin += left; } if(swapped) swap_m88k_thread_state_grf_t(&cpu, host_byte_sex); printf(" r1 0x%08x r2 0x%08x r3 0x%08x r4 0x%08x " "r5 0x%08x\n" " r6 0x%08x r7 0x%08x r8 0x%08x r9 0x%08x " "r10 0x%08x\n" " r11 0x%08x r12 0x%08x r13 0x%08x r14 0x%08x " "r15 0x%08x\n" " r16 0x%08x r17 0x%08x r18 0x%08x r19 0x%08x " "r20 0x%08x\n" " r21 0x%08x r22 0x%08x r23 0x%08x r24 0x%08x " "r25 0x%08x\n" " r26 0x%08x r27 0x%08x r28 0x%08x r29 0x%08x " "r30 0x%08x\n" " r31 0x%08x xip 0x%08x xip_in_bd 0x%08x nip " "0x%08x\n", cpu.r1, cpu.r2, cpu.r3, cpu.r4, cpu.r5, cpu.r6, cpu.r7, cpu.r8, cpu.r9, cpu.r10, cpu.r11, cpu.r12, cpu.r13, cpu.r14, cpu.r15, cpu.r16, cpu.r17, cpu.r18, cpu.r19, cpu.r20, cpu.r21, cpu.r22, cpu.r23, cpu.r24, cpu.r25, cpu.r26, cpu.r27, cpu.r28, cpu.r29, cpu.r30, cpu.r31, cpu.xip, cpu.xip_in_bd, cpu.nip); break; case M88K_THREAD_STATE_XRF: printf(" flavor M88K_THREAD_STATE_XRF\n"); if(count == M88K_THREAD_STATE_XRF_COUNT) printf(" count M88K_THREAD_STATE_XRF_COUNT\n"); else printf(" count %lu (not M88K_THREAD_STATE_XRF_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(m88k_thread_state_xrf_t)){ memcpy((char *)&fpu, begin, sizeof(m88k_thread_state_xrf_t)); begin += sizeof(m88k_thread_state_xrf_t); } else{ memset((char *)&fpu, '\0', sizeof(m88k_thread_state_xrf_t)); memcpy((char *)&fpu, begin, left); begin += left; } if(swapped) swap_m88k_thread_state_xrf_t(&fpu, host_byte_sex); printf(" x1 0x%08x 0x%08x 0x%08x 0x%08x\n" " x2 0x%08x 0x%08x 0x%08x 0x%08x\n" " x3 0x%08x 0x%08x 0x%08x 0x%08x\n" " x4 0x%08x 0x%08x 0x%08x 0x%08x\n" " x5 0x%08x 0x%08x 0x%08x 0x%08x\n" " x6 0x%08x 0x%08x 0x%08x 0x%08x\n" " x7 0x%08x 0x%08x 0x%08x 0x%08x\n" " x8 0x%08x 0x%08x 0x%08x 0x%08x\n" " x9 0x%08x 0x%08x 0x%08x 0x%08x\n" " x10 0x%08x 0x%08x 0x%08x 0x%08x\n" " x11 0x%08x 0x%08x 0x%08x 0x%08x\n" " x12 0x%08x 0x%08x 0x%08x 0x%08x\n" " x13 0x%08x 0x%08x 0x%08x 0x%08x\n" " x14 0x%08x 0x%08x 0x%08x 0x%08x\n" " x15 0x%08x 0x%08x 0x%08x 0x%08x\n" " x16 0x%08x 0x%08x 0x%08x 0x%08x\n" " x17 0x%08x 0x%08x 0x%08x 0x%08x\n" " x18 0x%08x 0x%08x 0x%08x 0x%08x\n" " x19 0x%08x 0x%08x 0x%08x 0x%08x\n" " x20 0x%08x 0x%08x 0x%08x 0x%08x\n" " x21 0x%08x 0x%08x 0x%08x 0x%08x\n" " x22 0x%08x 0x%08x 0x%08x 0x%08x\n" " x23 0x%08x 0x%08x 0x%08x 0x%08x\n" " x24 0x%08x 0x%08x 0x%08x 0x%08x\n" " x25 0x%08x 0x%08x 0x%08x 0x%08x\n" " x26 0x%08x 0x%08x 0x%08x 0x%08x\n" " x27 0x%08x 0x%08x 0x%08x 0x%08x\n" " x28 0x%08x 0x%08x 0x%08x 0x%08x\n" " x29 0x%08x 0x%08x 0x%08x 0x%08x\n" " x30 0x%08x 0x%08x 0x%08x 0x%08x\n" " x31 0x%08x 0x%08x 0x%08x 0x%08x\n", fpu.x1.x[0],fpu.x1.x[1],fpu.x1.x[2],fpu.x1.x[3], fpu.x2.x[0],fpu.x2.x[1],fpu.x2.x[2],fpu.x2.x[3], fpu.x3.x[0],fpu.x3.x[1],fpu.x3.x[2],fpu.x3.x[3], fpu.x4.x[0],fpu.x4.x[1],fpu.x4.x[2],fpu.x4.x[3], fpu.x5.x[0],fpu.x5.x[1],fpu.x5.x[2],fpu.x5.x[3], fpu.x6.x[0],fpu.x6.x[1],fpu.x6.x[2],fpu.x6.x[3], fpu.x7.x[0],fpu.x7.x[1],fpu.x7.x[2],fpu.x7.x[3], fpu.x8.x[0],fpu.x8.x[1],fpu.x8.x[2],fpu.x8.x[3], fpu.x9.x[0],fpu.x9.x[1],fpu.x9.x[2],fpu.x9.x[3], fpu.x10.x[0],fpu.x10.x[1],fpu.x10.x[2],fpu.x10.x[3], fpu.x11.x[0],fpu.x11.x[1],fpu.x11.x[2],fpu.x11.x[3], fpu.x12.x[0],fpu.x12.x[1],fpu.x12.x[2],fpu.x12.x[3], fpu.x13.x[0],fpu.x13.x[1],fpu.x13.x[2],fpu.x13.x[3], fpu.x14.x[0],fpu.x14.x[1],fpu.x14.x[2],fpu.x14.x[3], fpu.x15.x[0],fpu.x15.x[1],fpu.x15.x[2],fpu.x15.x[3], fpu.x16.x[0],fpu.x16.x[1],fpu.x16.x[2],fpu.x16.x[3], fpu.x17.x[0],fpu.x17.x[1],fpu.x17.x[2],fpu.x17.x[3], fpu.x18.x[0],fpu.x18.x[1],fpu.x18.x[2],fpu.x18.x[3], fpu.x19.x[0],fpu.x19.x[1],fpu.x19.x[2],fpu.x19.x[3], fpu.x20.x[0],fpu.x20.x[1],fpu.x20.x[2],fpu.x20.x[3], fpu.x21.x[0],fpu.x21.x[1],fpu.x21.x[2],fpu.x21.x[3], fpu.x22.x[0],fpu.x22.x[1],fpu.x22.x[2],fpu.x22.x[3], fpu.x23.x[0],fpu.x23.x[1],fpu.x23.x[2],fpu.x23.x[3], fpu.x24.x[0],fpu.x24.x[1],fpu.x24.x[2],fpu.x24.x[3], fpu.x25.x[0],fpu.x25.x[1],fpu.x25.x[2],fpu.x25.x[3], fpu.x26.x[0],fpu.x26.x[1],fpu.x26.x[2],fpu.x26.x[3], fpu.x27.x[0],fpu.x27.x[1],fpu.x27.x[2],fpu.x27.x[3], fpu.x28.x[0],fpu.x28.x[1],fpu.x28.x[2],fpu.x28.x[3], fpu.x29.x[0],fpu.x29.x[1],fpu.x29.x[2],fpu.x29.x[3], fpu.x30.x[0],fpu.x30.x[1],fpu.x30.x[2],fpu.x30.x[3], fpu.x31.x[0],fpu.x31.x[1],fpu.x31.x[2],fpu.x31.x[3]); printf(" fpsr xmod %d afinv %d afdvz %d afunf %d " "afovf %d afinx %d\n", fpu.fpsr.xmod, fpu.fpsr.afinv, fpu.fpsr.afdvz, fpu.fpsr.afunf, fpu.fpsr.afovf, fpu.fpsr.afinx); printf(" fpcr rm "); switch(fpu.fpcr.rm){ case M88K_RM_NEAREST: printf("RM_NEAREST "); break; case M88K_RM_ZERO: printf("RM_ZERO "); break; case M88K_RM_NEGINF: printf("RM_NEGINF "); break; case M88K_RM_POSINF: printf("RM_POSINF "); break; } printf("efinv %d efdvz %d efunf %d efovf %d efinx %d\n", fpu.fpcr.efinv, fpu.fpcr.efdvz, fpu.fpcr.efunf, fpu.fpcr.efovf, fpu.fpcr.efinx); break; case M88K_THREAD_STATE_USER: printf(" flavor M88K_THREAD_STATE_USER\n"); if(count == M88K_THREAD_STATE_USER_COUNT) printf(" count M88K_THREAD_STATE_USER_COUNT\n"); else printf(" count %lu (not M88K_THREAD_STATE_USER_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(m88k_thread_state_user_t)){ memcpy((char *)&user, begin, sizeof(m88k_thread_state_user_t)); begin += sizeof(m88k_thread_state_user_t); } else{ memset((char *)&user, '\0', sizeof(m88k_thread_state_user_t)); memcpy((char *)&user, begin, left); begin += left; } if(swapped) swap_m88k_thread_state_user_t(&user, host_byte_sex); printf(" user 0x%08x\n", (unsigned int)user.user); break; case M88110_THREAD_STATE_IMPL: printf(" flavor M88110_THREAD_STATE_IMPL\n"); if(count == M88110_THREAD_STATE_IMPL_COUNT) printf(" count M88110_THREAD_STATE_IMPL_COUNT\n"); else printf(" count %lu (not M88110_THREAD_STATE_IMPL_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(m88110_thread_state_impl_t)){ memcpy((char *)&spu, begin, sizeof(m88110_thread_state_impl_t)); begin += sizeof(m88110_thread_state_impl_t); } else{ memset((char *)&spu, '\0', sizeof(m88110_thread_state_impl_t)); memcpy((char *)&spu, begin, left); begin += left; } if(swapped) swap_m88110_thread_state_impl_t(&spu, host_byte_sex); for(j = 0; j < M88110_N_DATA_BP; j++){ printf(" data_bp[%lu] addr 0x%08x\n", j, (unsigned int)spu.data_bp[i].addr); printf(" cntl rw %d rwm %d " "addr_match ", spu.data_bp[j].ctrl.rw, spu.data_bp[j].ctrl.rwm); switch(spu.data_bp[j].ctrl.addr_match){ case M88110_MATCH_BYTE: printf("MATCH_BYTE "); break; case M88110_MATCH_SHORT: printf("MATCH_SHORT "); break; case M88110_MATCH_WORD: printf("MATCH_WORD "); break; case M88110_MATCH_DOUBLE: printf("MATCH_DOUBLE "); break; case M88110_MATCH_QUAD: printf("MATCH_QUAD "); break; case M88110_MATCH_32: printf("MATCH_32 "); break; case M88110_MATCH_64: printf("MATCH_64 "); break; case M88110_MATCH_128: printf("MATCH_128 "); break; case M88110_MATCH_256: printf("MATCH_256 "); break; case M88110_MATCH_512: printf("MATCH_512 "); break; case M88110_MATCH_1024: printf("MATCH_1024 "); break; case M88110_MATCH_2048: printf("MATCH_2048 "); break; case M88110_MATCH_4096: printf("MATCH_4096 "); break; default: printf("%d (?)", spu.data_bp[j].ctrl.addr_match); break; } printf("v %d\n", spu.data_bp[j].ctrl.v); } printf(" psr le %d se %d c %d sgn_imd %d sm %d " "sfu1dis %d mxm_dis %d\n" , spu.psr.le, spu.psr.se, spu.psr.c, spu.psr.sgn_imd, spu.psr.sm, spu.psr.sfu1dis, spu.psr.mxm_dis); break; default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else if(cputype == CPU_TYPE_I860){ struct i860_thread_state_regs cpu; while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case I860_THREAD_STATE_REGS: printf(" flavor I860_THREAD_STATE_REGS\n"); if(count == I860_THREAD_STATE_REGS_COUNT) printf(" count I860_THREAD_STATE_REGS_COUNT\n"); else printf(" count %lu (not I860_THREAD_STATE_REGS_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(struct i860_thread_state_regs)){ memcpy((char *)&cpu, begin, sizeof(struct i860_thread_state_regs)); begin += sizeof(struct i860_thread_state_regs); } else{ memset((char *)&cpu, '\0', sizeof(struct i860_thread_state_regs)); memcpy((char *)&cpu, begin, left); begin += left; } if(swapped) swap_i860_thread_state_regs(&cpu, host_byte_sex); printf(" iregs\n"); for(j = 0 ; j < 31 ; j += k){ for(k = 0 ; k < 5 && j + k < 31 ; k++) printf(" i%-2lu 0x%08x", j + k, (unsigned int)cpu.ireg[j + k]); printf("\n"); } printf(" fregs\n"); for(j = 0 ; j < 30 ; j += k){ for(k = 0 ; k < 5 && j + k < 30 ; k++) printf(" f%-2lu 0x%08x", j + k, (unsigned int)cpu.freg[j + k]); printf("\n"); } printf(" psr 0x%08x epsr 0x%08x db 0x%08x pc 0x%08x\n", (unsigned int)cpu.psr, (unsigned int)cpu.epsr, (unsigned int)cpu.db, (unsigned int)cpu.pc); printf(" Mres3 %e Ares3 %e\n", cpu.Mres3, cpu.Ares3); printf(" Mres2 %e Ares2 %e\n", cpu.Mres2, cpu.Ares2); printf(" Mres1 %e Ares1 %e\n", cpu.Mres1, cpu.Ares1); printf(" Ires1 %e\n", cpu.Ires1); printf(" Lres3m %e Lres2m %e Lres1m %e\n", cpu.Lres3m, cpu.Lres2m, cpu.Lres1m); printf(" KR %e KI %e T %e\n", cpu.KR, cpu.KI, cpu.T); printf(" Fsr3 0x%08x Fsr2 0x%08x Fsr1 0x%08x\n", (unsigned int)cpu.Fsr3, (unsigned int)cpu.Fsr2, (unsigned int)cpu.Fsr1); printf(" Mergelo32 0x%08x Mergehi32 0x%08x\n", (unsigned int)cpu.Mergelo32, (unsigned int)cpu.Mergehi32); break; default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else if(cputype == CPU_TYPE_I386 || cputype == CPU_TYPE_X86_64){ i386_thread_state_t cpu; /* current i386 thread states */ #if i386_THREAD_STATE == 1 #ifndef i386_EXCEPTION_STATE_COUNT char *fpu; unsigned long fpu_size; #else /* defined(i386_EXCEPTION_STATE_COUNT) */ i386_float_state_t fpu; #endif /* defined(i386_EXCEPTION_STATE_COUNT) */ i386_exception_state_t exc; unsigned long f, g; #ifdef x86_THREAD_STATE64 x86_thread_state64_t cpu64; x86_float_state64_t fpu64; x86_exception_state64_t exc64; x86_debug_state64_t debug64; x86_debug_state32_t debug; struct x86_thread_state ts; struct x86_float_state fs; struct x86_exception_state es; struct x86_debug_state ds; #endif /* x86_THREAD_STATE64 */ #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 i386_thread_fpstate_t fpu; i386_thread_exceptstate_t exc; i386_thread_cthreadstate_t user; const char *tags[] = { "VALID", "ZERO", "SPEC", "EMPTY" }; #endif /* i386_THREAD_STATE == -1 */ while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); switch(flavor){ case i386_THREAD_STATE: printf(" flavor i386_THREAD_STATE\n"); if(count == i386_THREAD_STATE_COUNT) printf(" count i386_THREAD_STATE_COUNT\n"); else printf(" count %lu (not i386_THREAD_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(i386_thread_state_t)){ memcpy((char *)&cpu, begin, sizeof(i386_thread_state_t)); begin += sizeof(i386_thread_state_t); } else{ memset((char *)&cpu, '\0', sizeof(i386_thread_state_t)); memcpy((char *)&cpu, begin, left); begin += left; } #ifdef x86_THREAD_STATE64 print_x86_thread_state32: #endif /* x86_THREAD_STATE64 */ if(swapped) swap_i386_thread_state(&cpu, host_byte_sex); printf( "\t eax 0x%08x ebx 0x%08x ecx 0x%08x edx 0x%08x\n" "\t edi 0x%08x esi 0x%08x ebp 0x%08x esp 0x%08x\n" "\t ss 0x%08x eflags 0x%08x eip 0x%08x cs 0x%08x\n" "\t ds 0x%08x es 0x%08x fs 0x%08x gs 0x%08x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx, cpu.edi, cpu.esi, cpu.ebp, cpu.esp, cpu.ss, cpu.eflags, cpu.eip, cpu.cs, cpu.ds, cpu.es, cpu.fs, cpu.gs); break; /* current i386 thread states */ #if i386_THREAD_STATE == 1 case i386_FLOAT_STATE: printf(" flavor i386_FLOAT_STATE\n"); if(count == i386_FLOAT_STATE_COUNT) printf(" count i386_FLOAT_STATE_COUNT\n"); else printf(" count %lu (not i386_FLOAT_STATE_COUNT)\n", count); left = end - begin; #ifndef i386_EXCEPTION_STATE_COUNT fpu = begin; if(left >= sizeof(struct i386_float_state)){ fpu_size = sizeof(struct i386_float_state); begin += sizeof(struct i386_float_state); } else{ fpu_size = left; begin += left; } printf("\t i386_float_state:\n"); for(f = 0; f < fpu_size; /* no increment expr */){ printf("\t "); for(g = 0; g < 16 && f < fpu_size; g++){ printf("%02x ", (unsigned int)(fpu[f] & 0xff)); f++; } printf("\n"); } #else /* defined(i386_EXCEPTION_STATE_COUNT) */ if(left >= sizeof(i386_float_state_t)){ memcpy((char *)&fpu, begin, sizeof(i386_float_state_t)); begin += sizeof(i386_float_state_t); } else{ memset((char *)&fpu, '\0', sizeof(i386_float_state_t)); memcpy((char *)&fpu, begin, left); begin += left; } #ifdef x86_THREAD_STATE64 print_x86_float_state32: #endif /* x86_THREAD_STATE64 */ if(swapped) swap_i386_float_state(&fpu, host_byte_sex); printf("\t fpu_reserved[0] %d fpu_reserved[1] %d\n", fpu.fpu_reserved[0], fpu.fpu_reserved[1]); printf("\t control: invalid %d denorm %d zdiv %d ovrfl " "%d undfl %d precis %d\n", fpu.fpu_fcw.invalid, fpu.fpu_fcw.denorm, fpu.fpu_fcw.zdiv, fpu.fpu_fcw.ovrfl, fpu.fpu_fcw.undfl, fpu.fpu_fcw.precis); printf("\t\t pc "); switch(fpu.fpu_fcw.pc){ case FP_PREC_24B: printf("FP_PREC_24B "); break; case FP_PREC_53B: printf("FP_PREC_53B "); break; case FP_PREC_64B: printf("FP_PREC_64B "); break; default: printf("%d ", fpu.fpu_fcw.pc); break; } printf("rc "); switch(fpu.fpu_fcw.rc){ case FP_RND_NEAR: printf("FP_RND_NEAR "); break; case FP_RND_DOWN: printf("FP_RND_DOWN "); break; case FP_RND_UP: printf("FP_RND_UP "); break; case FP_CHOP: printf("FP_CHOP "); break; } printf("\n"); printf("\t status: invalid %d denorm %d zdiv %d ovrfl " "%d undfl %d precis %d stkflt %d\n", fpu.fpu_fsw.invalid, fpu.fpu_fsw.denorm, fpu.fpu_fsw.zdiv, fpu.fpu_fsw.ovrfl, fpu.fpu_fsw.undfl, fpu.fpu_fsw.precis, fpu.fpu_fsw.stkflt); printf("\t errsumm %d c0 %d c1 %d c2 %d tos %d " "c3 %d busy %d\n", fpu.fpu_fsw.errsumm, fpu.fpu_fsw.c0, fpu.fpu_fsw.c1, fpu.fpu_fsw.c2, fpu.fpu_fsw.tos, fpu.fpu_fsw.c3, fpu.fpu_fsw.busy); printf("\t fpu_ftw 0x%02x fpu_rsrv1 0x%02x fpu_fop " "0x%04x fpu_ip 0x%08x\n", (unsigned int)fpu.fpu_ftw, (unsigned int)fpu.fpu_rsrv1, (unsigned int)fpu.fpu_fop, (unsigned int)fpu.fpu_ip); printf("\t fpu_cs 0x%04x fpu_rsrv2 0x%04x fpu_dp 0x%08x " "fpu_ds 0x%04x\n", (unsigned int)fpu.fpu_cs, (unsigned int)fpu.fpu_rsrv2, (unsigned int)fpu.fpu_dp, (unsigned int)fpu.fpu_ds); printf("\t fpu_rsrv3 0x%04x fpu_mxcsr 0x%08x " "fpu_mxcsrmask 0x%08x\n", (unsigned int)fpu.fpu_rsrv3, (unsigned int)fpu.fpu_mxcsr, (unsigned int)fpu.fpu_mxcsrmask); printf("\t fpu_stmm0:\n"); print_mmst_reg(&fpu.fpu_stmm0); printf("\t fpu_stmm1:\n"); print_mmst_reg(&fpu.fpu_stmm1); printf("\t fpu_stmm2:\n"); print_mmst_reg(&fpu.fpu_stmm2); printf("\t fpu_stmm3:\n"); print_mmst_reg(&fpu.fpu_stmm3); printf("\t fpu_stmm4:\n"); print_mmst_reg(&fpu.fpu_stmm4); printf("\t fpu_stmm5:\n"); print_mmst_reg(&fpu.fpu_stmm5); printf("\t fpu_stmm6:\n"); print_mmst_reg(&fpu.fpu_stmm6); printf("\t fpu_stmm7:\n"); print_mmst_reg(&fpu.fpu_stmm7); printf("\t fpu_xmm0:\n"); print_xmm_reg(&fpu.fpu_xmm0); printf("\t fpu_xmm1:\n"); print_xmm_reg(&fpu.fpu_xmm1); printf("\t fpu_xmm2:\n"); print_xmm_reg(&fpu.fpu_xmm2); printf("\t fpu_xmm3:\n"); print_xmm_reg(&fpu.fpu_xmm3); printf("\t fpu_xmm4:\n"); print_xmm_reg(&fpu.fpu_xmm4); printf("\t fpu_xmm5:\n"); print_xmm_reg(&fpu.fpu_xmm5); printf("\t fpu_xmm6:\n"); print_xmm_reg(&fpu.fpu_xmm6); printf("\t fpu_xmm7:\n"); print_xmm_reg(&fpu.fpu_xmm7); printf("\t fpu_rsrv4:\n"); for(f = 0; f < 14; f++){ printf("\t "); for(g = 0; g < 16; g++){ printf("%02x ", (unsigned int)(fpu.fpu_rsrv4[f*g] & 0xff)); } printf("\n"); } printf("\t fpu_reserved1 0x%08x\n", (unsigned int)fpu.fpu_reserved1); #endif /* defined(i386_EXCEPTION_STATE_COUNT) */ break; case i386_EXCEPTION_STATE: printf(" flavor i386_EXCEPTION_STATE\n"); if(count == I386_EXCEPTION_STATE_COUNT) printf(" count I386_EXCEPTION_STATE_COUNT\n"); else printf(" count %lu (not I386_EXCEPTION_STATE_COUNT" ")\n", count); left = end - begin; if(left >= sizeof(i386_exception_state_t)){ memcpy((char *)&exc, begin, sizeof(i386_exception_state_t)); begin += sizeof(i386_exception_state_t); } else{ memset((char *)&exc, '\0', sizeof(i386_exception_state_t)); memcpy((char *)&exc, begin, left); begin += left; } #ifdef x86_THREAD_STATE64 print_x86_exception_state32: #endif /* x86_THREAD_STATE64 */ if(swapped) swap_i386_exception_state(&exc, host_byte_sex); printf("\t trapno 0x%08x err 0x%08x faultvaddr 0x%08x\n", exc.trapno, exc.err, exc.faultvaddr); break; #ifdef x86_THREAD_STATE64 case x86_DEBUG_STATE32: printf(" flavor x86_DEBUG_STATE32\n"); if(count == x86_DEBUG_STATE32_COUNT) printf(" count x86_DEBUG_STATE32_COUNT\n"); else printf(" count %lu (not x86_DEBUG_STATE32_COUNT" ")\n", count); left = end - begin; if(left >= sizeof(x86_debug_state32_t)){ memcpy((char *)&debug, begin, sizeof(x86_debug_state32_t)); begin += sizeof(x86_debug_state32_t); } else{ memset((char *)&debug, '\0', sizeof(x86_debug_state32_t)); memcpy((char *)&debug, begin, left); begin += left; } print_x86_debug_state32: if(swapped) swap_x86_debug_state32(&debug, host_byte_sex); printf("\t dr0 0x%08x dr1 0x%08x dr2 0x%08x dr3 " "0x%08x\n", debug.dr0, debug.dr1, debug.dr2, debug.dr3); printf("\t dr4 0x%08x dr5 0x%08x dr6 0x%08x dr7 " "0x%08x\n", debug.dr4, debug.dr5, debug.dr6, debug.dr7); break; case x86_THREAD_STATE64: printf(" flavor x86_THREAD_STATE64\n"); if(count == x86_THREAD_STATE64_COUNT) printf(" count x86_THREAD_STATE64_COUNT\n"); else printf(" count %lu (not x86_THREAD_STATE64_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(x86_thread_state64_t)){ memcpy((char *)&cpu64, begin, sizeof(x86_thread_state64_t)); begin += sizeof(x86_thread_state64_t); } else{ memset((char *)&cpu64, '\0', sizeof(x86_thread_state64_t)); memcpy((char *)&cpu64, begin, left); begin += left; } print_x86_thread_state64: if(swapped) swap_x86_thread_state64(&cpu64, host_byte_sex); printf(" rax 0x%016llx rbx 0x%016llx rcx 0x%016llx\n" " rdx 0x%016llx rdi 0x%016llx rsi 0x%016llx\n" " rbp 0x%016llx rsp 0x%016llx r8 0x%016llx\n" " r9 0x%016llx r10 0x%016llx r11 0x%016llx\n" " r12 0x%016llx r13 0x%016llx r14 0x%016llx\n" " r15 0x%016llx rip 0x%016llx\n" "rflags 0x%016llx cs 0x%016llx fs 0x%016llx\n" " gs 0x%016llx\n", cpu64.rax, cpu64.rbx, cpu64.rcx, cpu64.rdx, cpu64.rdi, cpu64.rsi, cpu64.rbp, cpu64.rsp, cpu64.r8, cpu64.r9, cpu64.r10, cpu64.r11, cpu64.r12, cpu64.r13, cpu64.r14, cpu64.r15, cpu64.rip, cpu64.rflags, cpu64.cs, cpu64.fs, cpu64.gs); break; case x86_FLOAT_STATE64: printf(" flavor x86_FLOAT_STATE64\n"); if(count == x86_FLOAT_STATE64_COUNT) printf(" count x86_FLOAT_STATE64_COUNT\n"); else printf(" count %lu (not x86_FLOAT_STATE64_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(x86_float_state64_t)){ memcpy((char *)&fpu64, begin, sizeof(x86_float_state64_t)); begin += sizeof(x86_float_state64_t); } else{ memset((char *)&fpu64, '\0', sizeof(x86_float_state64_t)); memcpy((char *)&fpu64, begin, left); begin += left; } print_x86_float_state64: if(swapped) swap_x86_float_state64(&fpu64, host_byte_sex); printf("\t fpu_reserved[0] %d fpu_reserved[1] %d\n", fpu64.fpu_reserved[0], fpu64.fpu_reserved[1]); printf("\t control: invalid %d denorm %d zdiv %d ovrfl " "%d undfl %d precis %d\n", fpu64.fpu_fcw.invalid, fpu64.fpu_fcw.denorm, fpu64.fpu_fcw.zdiv, fpu64.fpu_fcw.ovrfl, fpu64.fpu_fcw.undfl, fpu64.fpu_fcw.precis); printf("\t\t pc "); switch(fpu64.fpu_fcw.pc){ case FP_PREC_24B: printf("FP_PREC_24B "); break; case FP_PREC_53B: printf("FP_PREC_53B "); break; case FP_PREC_64B: printf("FP_PREC_64B "); break; default: printf("%d ", fpu64.fpu_fcw.pc); break; } printf("rc "); switch(fpu64.fpu_fcw.rc){ case FP_RND_NEAR: printf("FP_RND_NEAR "); break; case FP_RND_DOWN: printf("FP_RND_DOWN "); break; case FP_RND_UP: printf("FP_RND_UP "); break; case FP_CHOP: printf("FP_CHOP "); break; } printf("\n"); printf("\t status: invalid %d denorm %d zdiv %d ovrfl " "%d undfl %d precis %d stkflt %d\n", fpu64.fpu_fsw.invalid, fpu64.fpu_fsw.denorm, fpu64.fpu_fsw.zdiv, fpu64.fpu_fsw.ovrfl, fpu64.fpu_fsw.undfl, fpu64.fpu_fsw.precis, fpu64.fpu_fsw.stkflt); printf("\t errsumm %d c0 %d c1 %d c2 %d tos %d " "c3 %d busy %d\n", fpu64.fpu_fsw.errsumm, fpu64.fpu_fsw.c0, fpu64.fpu_fsw.c1, fpu64.fpu_fsw.c2, fpu64.fpu_fsw.tos, fpu64.fpu_fsw.c3, fpu64.fpu_fsw.busy); printf("\t fpu_ftw 0x%02x fpu_rsrv1 0x%02x fpu_fop " "0x%04x fpu_ip 0x%08x\n", (unsigned int)fpu64.fpu_ftw, (unsigned int)fpu64.fpu_rsrv1, (unsigned int)fpu64.fpu_fop, (unsigned int)fpu64.fpu_ip); printf("\t fpu_cs 0x%04x fpu_rsrv2 0x%04x fpu_dp 0x%08x " "fpu_ds 0x%04x\n", (unsigned int)fpu64.fpu_cs, (unsigned int)fpu64.fpu_rsrv2, (unsigned int)fpu64.fpu_dp, (unsigned int)fpu64.fpu_ds); printf("\t fpu_rsrv3 0x%04x fpu_mxcsr 0x%08x " "fpu_mxcsrmask 0x%08x\n", (unsigned int)fpu64.fpu_rsrv3, (unsigned int)fpu64.fpu_mxcsr, (unsigned int)fpu64.fpu_mxcsrmask); printf("\t fpu_stmm0:\n"); print_mmst_reg(&fpu64.fpu_stmm0); printf("\t fpu_stmm1:\n"); print_mmst_reg(&fpu64.fpu_stmm1); printf("\t fpu_stmm2:\n"); print_mmst_reg(&fpu64.fpu_stmm2); printf("\t fpu_stmm3:\n"); print_mmst_reg(&fpu64.fpu_stmm3); printf("\t fpu_stmm4:\n"); print_mmst_reg(&fpu64.fpu_stmm4); printf("\t fpu_stmm5:\n"); print_mmst_reg(&fpu64.fpu_stmm5); printf("\t fpu_stmm6:\n"); print_mmst_reg(&fpu64.fpu_stmm6); printf("\t fpu_stmm7:\n"); print_mmst_reg(&fpu64.fpu_stmm7); printf("\t fpu_xmm0:\n"); print_xmm_reg(&fpu64.fpu_xmm0); printf("\t fpu_xmm1:\n"); print_xmm_reg(&fpu64.fpu_xmm1); printf("\t fpu_xmm2:\n"); print_xmm_reg(&fpu64.fpu_xmm2); printf("\t fpu_xmm3:\n"); print_xmm_reg(&fpu64.fpu_xmm3); printf("\t fpu_xmm4:\n"); print_xmm_reg(&fpu64.fpu_xmm4); printf("\t fpu_xmm5:\n"); print_xmm_reg(&fpu64.fpu_xmm5); printf("\t fpu_xmm6:\n"); print_xmm_reg(&fpu64.fpu_xmm6); printf("\t fpu_xmm7:\n"); print_xmm_reg(&fpu64.fpu_xmm7); printf("\t fpu_xmm8:\n"); print_xmm_reg(&fpu64.fpu_xmm8); printf("\t fpu_xmm9:\n"); print_xmm_reg(&fpu64.fpu_xmm9); printf("\t fpu_xmm10:\n"); print_xmm_reg(&fpu64.fpu_xmm10); printf("\t fpu_xmm11:\n"); print_xmm_reg(&fpu64.fpu_xmm11); printf("\t fpu_xmm12:\n"); print_xmm_reg(&fpu64.fpu_xmm12); printf("\t fpu_xmm13:\n"); print_xmm_reg(&fpu64.fpu_xmm13); printf("\t fpu_xmm14:\n"); print_xmm_reg(&fpu64.fpu_xmm14); printf("\t fpu_xmm15:\n"); print_xmm_reg(&fpu64.fpu_xmm15); printf("\t fpu_rsrv4:\n"); for(f = 0; f < 6; f++){ printf("\t "); for(g = 0; g < 16; g++){ printf("%02x ", (unsigned int)(fpu64.fpu_rsrv4[f*g] & 0xff)); } printf("\n"); } printf("\t fpu_reserved1 0x%08x\n", (unsigned int)fpu64.fpu_reserved1); break; case x86_EXCEPTION_STATE64: printf(" flavor x86_EXCEPTION_STATE64\n"); if(count == x86_EXCEPTION_STATE64_COUNT) printf(" count x86_EXCEPTION_STATE64_COUNT\n"); else printf(" count %lu (not x86_EXCEPTION_STATE64_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(x86_exception_state64_t)){ memcpy((char *)&exc64, begin, sizeof(x86_exception_state64_t)); begin += sizeof(x86_exception_state64_t); } else{ memset((char *)&exc64, '\0', sizeof(x86_exception_state64_t)); memcpy((char *)&exc64, begin, left); begin += left; } print_x86_exception_state64: if(swapped) swap_x86_exception_state64(&exc64, host_byte_sex); printf("\t trapno 0x%08x err 0x%08x faultvaddr " "0x%016llx\n", exc64.trapno, exc64.err, exc64.faultvaddr); break; case x86_DEBUG_STATE64: printf(" flavor x86_DEBUG_STATE64\n"); if(count == x86_DEBUG_STATE64_COUNT) printf(" count x86_DEBUG_STATE64_COUNT\n"); else printf(" count %lu (not x86_DEBUG_STATE64_COUNT" ")\n", count); left = end - begin; if(left >= sizeof(x86_debug_state64_t)){ memcpy((char *)&debug64, begin, sizeof(x86_debug_state32_t)); begin += sizeof(x86_debug_state32_t); } else{ memset((char *)&debug64, '\0', sizeof(x86_debug_state64_t)); memcpy((char *)&debug64, begin, left); begin += left; } print_x86_debug_state64: if(swapped) swap_x86_debug_state64(&debug64, host_byte_sex); printf("\t dr0 0x%016llx dr1 0x%016llx dr2 0x%016llx " "dr3 0x%016llx\n", debug64.dr0, debug64.dr1, debug64.dr2, debug64.dr3); printf("\t dr4 0x%016llx dr5 0x%016llx dr6 0x%016llx " "dr7 0x%016llx\n", debug64.dr4, debug64.dr5, debug64.dr6, debug64.dr7); break; case x86_THREAD_STATE: printf(" flavor x86_THREAD_STATE\n"); if(count == x86_THREAD_STATE_COUNT) printf(" count x86_THREAD_STATE_COUNT\n"); else printf(" count %lu (not x86_THREAD_STATE_COUNT)\n", count); left = end - begin; if(left >= sizeof(x86_thread_state_t)){ memcpy((char *)&ts, begin, sizeof(x86_thread_state_t)); begin += sizeof(x86_thread_state_t); } else{ memset((char *)&ts, '\0', sizeof(x86_thread_state_t)); memcpy((char *)&ts, begin, left); begin += left; } if(swapped) swap_x86_state_hdr(&ts.tsh, host_byte_sex); if(ts.tsh.flavor == x86_THREAD_STATE32){ printf("\t tsh.flavor x86_THREAD_STATE32 "); if(ts.tsh.count == x86_THREAD_STATE32_COUNT) printf("tsh.count x86_THREAD_STATE32_COUNT\n"); else printf("tsh.count %d (not x86_THREAD_STATE32_" "COUNT\n", ts.tsh.count); cpu = ts.uts.ts32; goto print_x86_thread_state32; } else if(ts.tsh.flavor == x86_THREAD_STATE64){ printf("\t tsh.flavor x86_THREAD_STATE64 "); if(ts.tsh.count == x86_THREAD_STATE64_COUNT) printf("tsh.count x86_THREAD_STATE64_COUNT\n"); else printf("tsh.count %d (not x86_THREAD_STATE64_" "COUNT\n", ts.tsh.count); cpu64 = ts.uts.ts64; goto print_x86_thread_state64; } else{ printf("\t tsh.flavor %d tsh.count %d\n", ts.tsh.flavor, ts.tsh.count); } break; case x86_FLOAT_STATE: printf(" flavor x86_FLOAT_STATE\n"); if(count == x86_FLOAT_STATE_COUNT) printf(" count x86_FLOAT_STATE_COUNT\n"); else printf(" count %lu (not x86_FLOAT_STATE_COUNT)\n", count); left = end - begin; if(left >= sizeof(x86_float_state_t)){ memcpy((char *)&fs, begin, sizeof(x86_float_state_t)); begin += sizeof(x86_float_state_t); } else{ memset((char *)&fs, '\0', sizeof(x86_float_state_t)); memcpy((char *)&fs, begin, left); begin += left; } if(swapped) swap_x86_state_hdr(&fs.fsh, host_byte_sex); if(fs.fsh.flavor == x86_FLOAT_STATE32){ printf("\t fsh.flavor x86_FLOAT_STATE32 "); if(fs.fsh.count == x86_FLOAT_STATE32_COUNT) printf("tsh.count x86_FLOAT_STATE32_COUNT\n"); else printf("tsh.count %d (not x86_FLOAT_STATE32_COUNT" "\n", fs.fsh.count); fpu = fs.ufs.fs32; goto print_x86_float_state32; } else if(fs.fsh.flavor == x86_FLOAT_STATE64){ printf("\t fsh.flavor x86_FLOAT_STATE64 "); if(fs.fsh.count == x86_FLOAT_STATE64_COUNT) printf("tsh.count x86_FLOAT_STATE64_COUNT\n"); else printf("tsh.count %d (not x86_FLOAT_STATE64_COUNT" "\n", fs.fsh.count); fpu64 = fs.ufs.fs64; goto print_x86_float_state64; } else{ printf("\t fsh.flavor %d fsh.count %d\n", fs.fsh.flavor, fs.fsh.count); } break; case x86_EXCEPTION_STATE: printf(" flavor x86_EXCEPTION_STATE\n"); if(count == x86_EXCEPTION_STATE_COUNT) printf(" count x86_EXCEPTION_STATE_COUNT\n"); else printf(" count %lu (not x86_EXCEPTION_STATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(x86_exception_state_t)){ memcpy((char *)&es, begin, sizeof(x86_exception_state_t)); begin += sizeof(x86_exception_state_t); } else{ memset((char *)&es, '\0', sizeof(x86_exception_state_t)); memcpy((char *)&es, begin, left); begin += left; } if(swapped) swap_x86_state_hdr(&es.esh, host_byte_sex); if(es.esh.flavor == x86_EXCEPTION_STATE32){ printf("\t esh.flavor x86_EXCEPTION_STATE32\n"); if(es.esh.count == x86_EXCEPTION_STATE32_COUNT) printf("\t esh.count x86_EXCEPTION_STATE32_" "COUNT\n"); else printf("\t esh.count %d (not x86_EXCEPTION_" "STATE32_COUNT\n", es.esh.count); exc = es.ues.es32; goto print_x86_exception_state32; } else if(es.esh.flavor == x86_EXCEPTION_STATE64){ printf("\t esh.flavor x86_EXCEPTION_STATE64\n"); if(es.esh.count == x86_EXCEPTION_STATE64_COUNT) printf("\t esh.count x86_EXCEPTION_STATE64_" "COUNT\n"); else printf("\t esh.count %d (not x86_EXCEPTION_" "STATE64_COUNT\n", es.esh.count); exc64 = es.ues.es64; goto print_x86_exception_state64; } else{ printf("\t esh.flavor %d esh.count %d\n", es.esh.flavor, es.esh.count); } break; case x86_DEBUG_STATE: printf(" flavor x86_DEBUG_STATE\n"); if(count == x86_DEBUG_STATE_COUNT) printf(" count x86_DEBUG_STATE_COUNT\n"); else printf(" count %lu (not x86_DEBUG_STATE_COUNT" "\n", count); left = end - begin; if(left >= sizeof(x86_debug_state_t)){ memcpy((char *)&ds, begin, sizeof(x86_debug_state_t)); begin += sizeof(x86_debug_state_t); } else{ memset((char *)&ds, '\0', sizeof(x86_debug_state_t)); memcpy((char *)&ds, begin, left); begin += left; } if(swapped) swap_x86_state_hdr(&ds.dsh, host_byte_sex); if(ds.dsh.flavor == x86_DEBUG_STATE32){ printf("\t dsh.flavor x86_DEBUG_STATE32\n"); if(ds.dsh.count == x86_DEBUG_STATE32_COUNT) printf("\t dsh.count x86_DEBUG_STATE32_COUNT\n"); else printf("\t esh.count %d (not x86_DEBUG_STATE32_" "_COUNT\n", ds.dsh.count); debug = ds.uds.ds32; goto print_x86_debug_state32; } if(ds.dsh.flavor == x86_DEBUG_STATE64){ printf("\t dsh.flavor x86_DEBUG_STATE64\n"); if(ds.dsh.count == x86_DEBUG_STATE64_COUNT) printf("\t dsh.count x86_DEBUG_STATE64_COUNT\n"); else printf("\t esh.count %d (not x86_DEBUG_STATE64_" "_COUNT\n", ds.dsh.count); debug64 = ds.uds.ds64; goto print_x86_debug_state64; } else{ printf("\t dsh.flavor %d dsh.count %d\n", ds.dsh.flavor, ds.dsh.count); } break; #endif /* x86_THREAD_STATE64 */ #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 case i386_THREAD_FPSTATE: printf(" flavor i386_THREAD_FPSTATE\n"); if(count == i386_THREAD_FPSTATE_COUNT) printf(" count i386_THREAD_FPSTATE_COUNT\n"); else printf(" count %lu (not i386_THREAD_FPSTATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(i386_thread_fpstate_t)){ memcpy((char *)&fpu, begin, sizeof(i386_thread_fpstate_t)); begin += sizeof(i386_thread_fpstate_t); } else{ memset((char *)&fpu, '\0', sizeof(i386_thread_fpstate_t)); memcpy((char *)&fpu, begin, left); begin += left; } if(swapped) swap_i386_thread_fpstate(&fpu, host_byte_sex); printf("\t control: invalid %d denorm %d zdiv %d ovrfl " "%d undfl %d precis %d\n", fpu.environ.control.invalid, fpu.environ.control.denorm, fpu.environ.control.zdiv, fpu.environ.control.ovrfl, fpu.environ.control.undfl, fpu.environ.control.precis); printf("\t\t pc "); switch(fpu.environ.control.pc){ case FP_PREC_24B: printf("FP_PREC_24B "); break; case FP_PREC_53B: printf("FP_PREC_53B "); break; case FP_PREC_64B: printf("FP_PREC_64B "); break; default: printf("%d ", fpu.environ.control.pc); break; } printf("rc "); switch(fpu.environ.control.rc){ case FP_RND_NEAR: printf("FP_RND_NEAR "); break; case FP_RND_DOWN: printf("FP_RND_DOWN "); break; case FP_RND_UP: printf("FP_RND_UP "); break; case FP_CHOP: printf("FP_CHOP "); break; } printf("\n"); printf("\t status: invalid %d denorm %d zdiv %d ovrfl " "%d undfl %d precis %d stkflt %d\n", fpu.environ.status.invalid, fpu.environ.status.denorm, fpu.environ.status.zdiv, fpu.environ.status.ovrfl, fpu.environ.status.undfl, fpu.environ.status.precis, fpu.environ.status.stkflt); printf("\t\t errsumm %d c0 %d c1 %d c2 %d tos %d c3 %d " "busy %d\n", fpu.environ.status.errsumm, fpu.environ.status.c0, fpu.environ.status.c1, fpu.environ.status.c2, fpu.environ.status.tos, fpu.environ.status.c3, fpu.environ.status.busy); printf("\t tags: tag0 %s tag1 %s tag2 %s tag3 %s\n" "\t tag4 %s tag5 %s tag6 %s tag7 %s\n", tags[fpu.environ.tag.tag0], tags[fpu.environ.tag.tag1], tags[fpu.environ.tag.tag2], tags[fpu.environ.tag.tag3], tags[fpu.environ.tag.tag4], tags[fpu.environ.tag.tag5], tags[fpu.environ.tag.tag6], tags[fpu.environ.tag.tag7]); printf("\t ip 0x%08x\n", fpu.environ.ip); printf("\t cs: rpl "); switch(fpu.environ.cs.rpl){ case KERN_PRIV: printf("KERN_PRIV "); break; case USER_PRIV: printf("USER_PRIV "); break; default: printf("%d ", fpu.environ.cs.rpl); break; } printf("ti "); switch(fpu.environ.cs.ti){ case SEL_GDT: printf("SEL_GDT "); break; case SEL_LDT: printf("SEL_LDT "); break; } printf("index %d\n", fpu.environ.cs.index); printf("\t opcode 0x%04x\n", (unsigned int)fpu.environ.opcode); printf("\t dp 0x%08x\n", fpu.environ.dp); printf("\t ds: rpl "); switch(fpu.environ.ds.rpl){ case KERN_PRIV: printf("KERN_PRIV "); break; case USER_PRIV: printf("USER_PRIV "); break; default: printf("%d ", fpu.environ.ds.rpl); break; } printf("ti "); switch(fpu.environ.ds.ti){ case SEL_GDT: printf("SEL_GDT "); break; case SEL_LDT: printf("SEL_LDT "); break; } printf("index %d\n", fpu.environ.ds.index); printf("\t stack:\n"); for(i = 0; i < 8; i++){ printf("\t\tST[%lu] mant 0x%04x 0x%04x 0x%04x 0x%04x " "exp 0x%04x sign %d\n", i, (unsigned int)fpu.stack.ST[i].mant, (unsigned int)fpu.stack.ST[i].mant1, (unsigned int)fpu.stack.ST[i].mant2, (unsigned int)fpu.stack.ST[i].mant3, (unsigned int)fpu.stack.ST[i].exp, fpu.stack.ST[i].sign); } break; case i386_THREAD_EXCEPTSTATE: printf(" flavor i386_THREAD_EXCEPTSTATE\n"); if(count == i386_THREAD_EXCEPTSTATE_COUNT) printf(" count i386_THREAD_EXCEPTSTATE_COUNT\n"); else printf(" count %lu (not i386_THREAD_EXCEPTSTATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(i386_thread_exceptstate_t)){ memcpy((char *)&exc, begin, sizeof(i386_thread_exceptstate_t)); begin += sizeof(i386_thread_exceptstate_t); } else{ memset((char *)&exc, '\0', sizeof(i386_thread_exceptstate_t)); memcpy((char *)&exc, begin, left); begin += left; } if(swapped) swap_i386_thread_exceptstate(&exc, host_byte_sex); printf("\t trapno 0x%08x\n", exc.trapno); if(exc.trapno == 14){ printf("\t err.pgfault: prot %d wrtflt %d user %d\n", exc.err.pgfault.prot, exc.err.pgfault.wrtflt, exc.err.pgfault.user); } else{ printf("\t err.normal: ext %d ", exc.err.normal.ext); printf("tbl "); switch(exc.err.normal.tbl){ case ERR_GDT: printf("ERR_GDT "); break; case ERR_IDT: printf("ERR_IDT "); break; case ERR_LDT: printf("ERR_LDT "); break; default: printf("%d ", exc.err.normal.tbl); break; } printf("index %d\n", exc.err.normal.index); } break; case i386_THREAD_CTHREADSTATE: printf(" flavor i386_THREAD_CTHREADSTATE\n"); if(count == i386_THREAD_CTHREADSTATE_COUNT) printf(" count i386_THREAD_CTHREADSTATE_COUNT\n"); else printf(" count %lu (not i386_THREAD_CTHREADSTATE_" "COUNT)\n", count); left = end - begin; if(left >= sizeof(i386_thread_cthreadstate_t)){ memcpy((char *)&user, begin, sizeof(i386_thread_cthreadstate_t)); begin += sizeof(i386_thread_cthreadstate_t); } else{ memset((char *)&user, '\0', sizeof(i386_thread_cthreadstate_t)); memcpy((char *)&user, begin, left); begin += left; } if(swapped) swap_i386_thread_cthreadstate(&user, host_byte_sex); printf("\t self 0x%08x\n", user.self); break; #endif /* i386_THREAD_STATE == -1 */ default: printf(" flavor %lu (unknown)\n", flavor); printf(" count %lu\n", count); printf(" state:\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); break; } } } else{ while(begin < end){ if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&flavor, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ flavor = 0; begin = end; } if(swapped) flavor = SWAP_LONG(flavor); if(end - begin > (ptrdiff_t)sizeof(unsigned long)){ memcpy((char *)&count, begin, sizeof(unsigned long)); begin += sizeof(unsigned long); } else{ count = 0; begin = end; } if(swapped) count = SWAP_LONG(count); printf(" flavor %lu\n", flavor); printf(" count %lu\n", count); printf(" state (Unknown cputype/cpusubtype):\n"); print_unknown_state(begin, end, count, swapped); begin += count * sizeof(unsigned long); } } } /* current i386 thread states */ #if i386_THREAD_STATE == 1 #ifdef i386_EXCEPTION_STATE_COUNT static void print_mmst_reg( struct mmst_reg *r) { unsigned long f; printf("\t mmst_reg "); for(f = 0; f < 10; f++){ printf("%02x ", (unsigned int)(r->mmst_reg[f] & 0xff)); } printf("\n"); printf("\t mmst_rsrv "); for(f = 0; f < 6; f++){ printf("%02x ", (unsigned int)(r->mmst_rsrv[f] & 0xff)); } printf("\n"); } static void print_xmm_reg( struct xmm_reg *r) { unsigned long f; printf("\t xmm_reg "); for(f = 0; f < 16; f++){ printf("%02x ", (unsigned int)(r->xmm_reg[f] & 0xff)); } printf("\n"); } #endif /* defined(i386_EXCEPTION_STATE_COUNT) */ #endif /* i386_THREAD_STATE == 1 */ static void print_unknown_state( char *begin, char *end, unsigned int count, enum bool swapped) { unsigned long left, *state, i, j; left = end - begin; if(left * sizeof(unsigned long) >= count){ state = allocate(count * sizeof(unsigned long)); memcpy((char *)state, begin, count * sizeof(unsigned long)); begin += count * sizeof(unsigned long); } else{ state = allocate(left); memset((char *)state, '\0', left); memcpy((char *)state, begin, left); count = left / sizeof(unsigned long); begin += left; } if(swapped) for(i = 0 ; i < count; i++) state[i] = SWAP_LONG(state[i]); for(i = 0 ; i < count; i += j){ for(j = 0 ; j < 8 && i + j < count; j++) printf("%08x ", (unsigned int)state[i + j]); printf("\n"); } free(state); } /* * Print the relocation information. */ void print_reloc( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, cpu_type_t cputype, enum byte_sex load_commands_byte_sex, char *object_addr, unsigned long object_size, struct nlist *symbols, struct nlist_64 *symbols64, long nsymbols, char *strings, long strings_size, enum bool verbose) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, j, k, left, size, nsects; char *p; struct load_command *lc, l; struct segment_command sg; struct section s; struct segment_command_64 sg64; struct section_64 s64; struct reloc_section_info *sect_rel; struct dysymtab_command dyst; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; /* * Create an array of section structures in the host byte sex so it * can be processed and indexed into directly. */ k = 0; nsects = 0; sect_rel = NULL; lc = load_commands; dyst.cmd = 0; for(i = 0 ; i < ncmds; i++){ memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&l, host_byte_sex); if(l.cmdsize % sizeof(long) != 0) printf("load command %lu size not a multiple of " "sizeof(long)\n", i); if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %lu extends past end of load " "commands\n", i); left = sizeofcmds - ((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: memset((char *)&sg, '\0', sizeof(struct segment_command)); size = left < sizeof(struct segment_command) ? left : sizeof(struct segment_command); memcpy((char *)&sg, (char *)lc, size); if(swapped) swap_segment_command(&sg, host_byte_sex); nsects += sg.nsects; sect_rel = reallocate(sect_rel, nsects * sizeof(struct reloc_section_info)); memset((char *)(sect_rel + (nsects - sg.nsects)), '\0', sizeof(struct reloc_section_info) * sg.nsects); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ left = sizeofcmds - (p - (char *)load_commands); size = left < sizeof(struct section) ? left : sizeof(struct section); memcpy((char *)&s, p, size); if(swapped) swap_section(&s, 1, host_byte_sex); if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds) break; p += size; memcpy(sect_rel[k].segname, s.segname, 16); memcpy(sect_rel[k].sectname, s.sectname, 16); sect_rel[k].nreloc = s.nreloc; sect_rel[k].reloff = s.reloff; k++; } break; case LC_SEGMENT_64: memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); size = left < sizeof(struct segment_command_64) ? left : sizeof(struct segment_command_64); memcpy((char *)&sg64, (char *)lc, size); if(swapped) swap_segment_command_64(&sg64, host_byte_sex); nsects += sg64.nsects; sect_rel = reallocate(sect_rel, nsects * sizeof(struct reloc_section_info)); memset((char *)(sect_rel + (nsects - sg64.nsects)), '\0', sizeof(struct reloc_section_info) * sg64.nsects); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ left = sizeofcmds - (p - (char *)load_commands); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); memcpy((char *)&s64, p, size); if(swapped) swap_section_64(&s64, 1, host_byte_sex); if(p + sizeof(struct section_64) > (char *)load_commands + sizeofcmds) break; p += size; memcpy(sect_rel[k].segname, s64.segname, 16); memcpy(sect_rel[k].sectname, s64.sectname, 16); sect_rel[k].nreloc = s64.nreloc; sect_rel[k].reloff = s64.reloff; k++; } break; case LC_DYSYMTAB: memset((char *)&dyst, '\0', sizeof(struct dysymtab_command)); size = left < sizeof(struct dysymtab_command) ? left : sizeof(struct dysymtab_command); memcpy((char *)&dyst, (char *)lc, size); if(swapped) swap_dysymtab_command(&dyst, host_byte_sex); break; } if(l.cmdsize == 0){ printf("load command %lu size zero (can't advance to other " "load commands)\n", i); break; } lc = (struct load_command *)((char *)lc + l.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) break; } if((char *)load_commands + sizeofcmds != (char *)lc) printf("Inconsistent sizeofcmds\n"); if(dyst.cmd != 0){ if(dyst.nextrel != 0){ printf("External relocation information %u entries", dyst.nextrel); if(dyst.extreloff > object_size){ printf(" (offset to relocation entries extends past the " "end of the file)\n"); } else{ printf("\naddress pcrel length extern type scattered " "symbolnum/value\n"); print_relocs(dyst.extreloff, dyst.nextrel, sect_rel, nsects, swapped, cputype, object_addr, object_size, symbols, symbols64, nsymbols, strings, strings_size, verbose); } } if(dyst.nlocrel != 0){ printf("Local relocation information %u entries", dyst.nlocrel); if(dyst.locreloff > object_size){ printf(" (offset to relocation entries extends past the " "end of the file)\n"); } else{ printf("\naddress pcrel length extern type scattered " "symbolnum/value\n"); print_relocs(dyst.locreloff, dyst.nlocrel, sect_rel, nsects, swapped, cputype, object_addr, object_size, symbols, symbols64, nsymbols, strings, strings_size, verbose); } } } for(i = 0 ; i < nsects ; i++){ if(sect_rel[i].nreloc == 0) continue; printf("Relocation information (%.16s,%.16s) %u entries", sect_rel[i].segname, sect_rel[i].sectname, sect_rel[i].nreloc); if(sect_rel[i].reloff > object_size){ printf(" (offset to relocation entries extends past the end of " " the file)\n"); continue; } printf("\naddress pcrel length extern type scattered " "symbolnum/value\n"); print_relocs(sect_rel[i].reloff, sect_rel[i].nreloc, sect_rel, nsects, swapped, cputype, object_addr, object_size, symbols, symbols64, nsymbols, strings, strings_size, verbose); } } static void print_relocs( unsigned reloff, unsigned nreloc, struct reloc_section_info *sect_rel, unsigned long nsects, enum bool swapped, cpu_type_t cputype, char *object_addr, unsigned long object_size, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, enum bool verbose) { enum byte_sex host_byte_sex; unsigned long j; struct relocation_info *r, reloc; struct scattered_relocation_info *sr; enum bool previous_sectdiff, previous_ppc_jbsr, predicted; unsigned long sectdiff_r_type; uint32_t n_strx; host_byte_sex = get_host_byte_sex(); previous_sectdiff = FALSE; previous_ppc_jbsr = FALSE; sectdiff_r_type = 0; for(j = 0 ; j < nreloc && reloff + (j + 1) * sizeof(struct relocation_info) <= object_size; j++){ predicted = FALSE; r = (struct relocation_info *) (object_addr + reloff + j * sizeof(struct relocation_info)); memcpy((char *)&reloc, (char *)r, sizeof(struct relocation_info)); if(swapped) swap_relocation_info(&reloc, 1, host_byte_sex); if((reloc.r_address & R_SCATTERED) != 0){ sr = (struct scattered_relocation_info *)&reloc; if(verbose){ if((cputype == CPU_TYPE_MC680x0 && sr->r_type == GENERIC_RELOC_PAIR) || (cputype == CPU_TYPE_I386 && sr->r_type == GENERIC_RELOC_PAIR) || (cputype == CPU_TYPE_MC88000 && sr->r_type == M88K_RELOC_PAIR) || ((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && sr->r_type == PPC_RELOC_PAIR) || (cputype == CPU_TYPE_HPPA && sr->r_type == HPPA_RELOC_PAIR) || (cputype == CPU_TYPE_SPARC && sr->r_type == SPARC_RELOC_PAIR) || (cputype == CPU_TYPE_ARM && sr->r_type == ARM_RELOC_PAIR) || (cputype == CPU_TYPE_I860 && sr->r_type == I860_RELOC_PAIR)) printf(" "); else printf("%08x ", (unsigned int)sr->r_address); if(sr->r_pcrel) printf("True "); else printf("False "); switch(sr->r_length){ case 0: printf("byte "); break; case 1: printf("word "); break; case 2: printf("long "); break; case 3: /* * The value of 3 for r_length for PowerPC is to encode * that a conditional branch using the Y-bit for static * branch prediction was predicted in the assembly * source. */ if((cputype == CPU_TYPE_POWERPC64 && reloc.r_type == PPC_RELOC_VANILLA) || cputype == CPU_TYPE_X86_64) { printf("quad "); } else if(cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO){ printf("long "); predicted = TRUE; } else printf("?(%2d) ", sr->r_length); break; default: printf("?(%2d) ", sr->r_length); break; } printf("n/a "); print_r_type(cputype, sr->r_type, predicted); printf("True 0x%08x", (unsigned int)sr->r_value); if(previous_sectdiff == FALSE){ if((cputype == CPU_TYPE_MC88000 && sr->r_type == M88K_RELOC_PAIR) || (cputype == CPU_TYPE_SPARC && sr->r_type == SPARC_RELOC_PAIR) || (cputype == CPU_TYPE_ARM && sr->r_type == ARM_RELOC_PAIR) || (cputype == CPU_TYPE_I860 && sr->r_type == I860_RELOC_PAIR)) printf(" half = 0x%04x ", (unsigned int)sr->r_address); else if(cputype == CPU_TYPE_HPPA && sr->r_type == HPPA_RELOC_PAIR) printf(" other_part = 0x%06x ", (unsigned int)sr->r_address); else if(((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && sr->r_type == PPC_RELOC_PAIR)){ if(previous_ppc_jbsr == FALSE) printf(" half = 0x%04x ", (unsigned int)reloc.r_address); else{ printf(" <- other_part "); } } } else if(cputype == CPU_TYPE_HPPA && (sectdiff_r_type == HPPA_RELOC_HI21_SECTDIFF || sectdiff_r_type == HPPA_RELOC_LO14_SECTDIFF)){ printf(" other_part = 0x%06x ", (unsigned int)sr->r_address); } else if(cputype == CPU_TYPE_SPARC && (sectdiff_r_type == SPARC_RELOC_HI22_SECTDIFF || sectdiff_r_type == SPARC_RELOC_LO10_SECTDIFF)){ printf(" other_part = 0x%06x ", (unsigned int)sr->r_address); } else if((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && (sectdiff_r_type == PPC_RELOC_HI16_SECTDIFF || sectdiff_r_type == PPC_RELOC_LO16_SECTDIFF || sectdiff_r_type == PPC_RELOC_LO14_SECTDIFF || sectdiff_r_type == PPC_RELOC_HA16_SECTDIFF)){ printf(" other_half = 0x%04x ", (unsigned int)sr->r_address); } if((cputype == CPU_TYPE_MC680x0 && (sr->r_type == GENERIC_RELOC_SECTDIFF || sr->r_type == GENERIC_RELOC_LOCAL_SECTDIFF)) || (cputype == CPU_TYPE_I386 && (sr->r_type == GENERIC_RELOC_SECTDIFF || sr->r_type == GENERIC_RELOC_LOCAL_SECTDIFF)) || (cputype == CPU_TYPE_MC88000 && sr->r_type == M88K_RELOC_SECTDIFF) || ((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && (sr->r_type == PPC_RELOC_SECTDIFF || sr->r_type == PPC_RELOC_LOCAL_SECTDIFF || sr->r_type == PPC_RELOC_HI16_SECTDIFF || sr->r_type == PPC_RELOC_LO16_SECTDIFF || sr->r_type == PPC_RELOC_LO14_SECTDIFF || sr->r_type == PPC_RELOC_HA16_SECTDIFF)) || (cputype == CPU_TYPE_I860 && sr->r_type == I860_RELOC_SECTDIFF) || (cputype == CPU_TYPE_HPPA && (sr->r_type == HPPA_RELOC_SECTDIFF || sr->r_type == HPPA_RELOC_HI21_SECTDIFF || sr->r_type == HPPA_RELOC_LO14_SECTDIFF)) || (cputype == CPU_TYPE_ARM && sr->r_type == ARM_RELOC_SECTDIFF) || (cputype == CPU_TYPE_SPARC && (sr->r_type == SPARC_RELOC_SECTDIFF || sr->r_type == SPARC_RELOC_HI22_SECTDIFF || sr->r_type == SPARC_RELOC_LO10_SECTDIFF))){ previous_sectdiff = TRUE; sectdiff_r_type = sr->r_type; } else previous_sectdiff = FALSE; if(((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && sr->r_type == PPC_RELOC_JBSR)) previous_ppc_jbsr = TRUE; else previous_ppc_jbsr = FALSE; printf("\n"); } else{ printf("%08x %1d %-2d n/a %-7d 1 " "0x%08x\n", (unsigned int)sr->r_address, sr->r_pcrel, sr->r_length, sr->r_type, (unsigned int)sr->r_value); } } else{ if(verbose){ if((cputype == CPU_TYPE_MC88000 && reloc.r_type == M88K_RELOC_PAIR) || ((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && reloc.r_type == PPC_RELOC_PAIR) || (cputype == CPU_TYPE_HPPA && reloc.r_type == HPPA_RELOC_PAIR) || (cputype == CPU_TYPE_SPARC && reloc.r_type == SPARC_RELOC_PAIR) || (cputype == CPU_TYPE_ARM && reloc.r_type == ARM_RELOC_PAIR) || (cputype == CPU_TYPE_I860 && reloc.r_type == I860_RELOC_PAIR)) printf(" "); else printf("%08x ", (unsigned int)reloc.r_address); if(reloc.r_pcrel) printf("True "); else printf("False "); switch(reloc.r_length){ case 0: printf("byte "); break; case 1: printf("word "); break; case 2: printf("long "); break; case 3: /* * The value of 3 for r_length for PowerPC is to encode * that a conditional branch using the Y-bit for static * branch prediction was predicted in the assembly * source. */ if((cputype == CPU_TYPE_POWERPC64 && reloc.r_type == PPC_RELOC_VANILLA) || cputype == CPU_TYPE_X86_64) { printf("quad "); } else if(cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO){ printf("long "); predicted = TRUE; } else printf("?(%2d) ", reloc.r_length); break; default: printf("?(%2d) ", reloc.r_length); break; } if(reloc.r_extern){ printf("True "); print_r_type(cputype, reloc.r_type, predicted); printf("False "); if((symbols == NULL && symbols64 == NULL) || strings == NULL || reloc.r_symbolnum > nsymbols) printf("?(%d)\n", reloc.r_symbolnum); else{ if(symbols != NULL) n_strx = symbols[reloc.r_symbolnum].n_un.n_strx; else n_strx = symbols64[reloc.r_symbolnum]. n_un.n_strx; if(n_strx > strings_size) printf("?(%d)\n", reloc.r_symbolnum); else printf("%s\n", strings + n_strx); } } else{ printf("False "); print_r_type(cputype, reloc.r_type, predicted); printf("False "); if((cputype == CPU_TYPE_I860 && reloc.r_type == I860_RELOC_PAIR) || (cputype == CPU_TYPE_MC88000 && reloc.r_type == M88K_RELOC_PAIR) ){ printf("half = 0x%04x\n", (unsigned int)reloc.r_address); } else if((cputype == CPU_TYPE_HPPA && reloc.r_type == HPPA_RELOC_PAIR) || (cputype == CPU_TYPE_ARM && reloc.r_type == ARM_RELOC_PAIR) || (cputype == CPU_TYPE_SPARC && reloc.r_type == SPARC_RELOC_PAIR)){ printf(" other_part = 0x%06x\n", (unsigned int)reloc.r_address); } else if(((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && reloc.r_type == PPC_RELOC_PAIR)){ if(previous_ppc_jbsr == FALSE) printf("half = 0x%04x\n", (unsigned int)reloc.r_address); else printf("other_part = 0x%08x\n", (unsigned int)reloc.r_address); } else{ printf("%d ", reloc.r_symbolnum); if(reloc.r_symbolnum > nsects + 1) printf("(?,?)\n"); else{ if(reloc.r_symbolnum == R_ABS) printf("R_ABS\n"); else printf("(%.16s,%.16s)\n", sect_rel[reloc.r_symbolnum-1].segname, sect_rel[reloc.r_symbolnum-1].sectname); } } } if(((cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_POWERPC64 || cputype == CPU_TYPE_VEO) && reloc.r_type == PPC_RELOC_JBSR)) previous_ppc_jbsr = TRUE; else previous_ppc_jbsr = FALSE; } else{ printf("%08x %1d %-2d %1d %-7d 0" " %d\n", (unsigned int)reloc.r_address, reloc.r_pcrel, reloc.r_length, reloc.r_extern, reloc.r_type, reloc.r_symbolnum); } } } } static char *generic_r_types[] = { "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", " 5 (?) ", " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static char *m88k_r_types[] = { "VANILLA ", "PAIR ", "PC16 ", "PC26 ", "HI16 ", "LO16 ", "SECTDIF ", "PBLAPTR ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static char *i860_r_types[] = { "VANILLA ", "PAIR ", "HIGH ", "LOW0 ", "LOW1 ", "LOW2 ", "LOW3 ", "LOW4 ", "SPLIT0 ", "SPLIT1 ", "SPLIT2 ", "HIGHADJ ", "BRADDR ", "SECTDIF ", " 14 (?) ", " 15 (?) " }; static char *ppc_r_types[] = { "VANILLA ", "PAIR ", "BR14", "BR24 ", "HI16 ", "LO16 ", "HA16 ", "LO14 ", "SECTDIF ", "PBLAPTR ", "HI16DIF ", "LO16DIF ", "HA16DIF ", "JBSR ", "LO14DIF ", "LOCSDIF " }; static char *x86_64_r_types[] = { "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", " 9 (?) ", " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static char *hppa_r_types[] = { "VANILLA ", "PAIR ", "HI21 ", "LO14 ", "BR17 ", "BL17 ", "JBSR ", "SECTDIF ", "HI21DIF ", "LO14DIF ", "PBLAPTR ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static char *sparc_r_types[] = { "VANILLA ", "PAIR ", "HI22 ", "LO10 ", "DISP22 ", "DISP30 ", "SECTDIFF", "HI22DIFF", "LO10DIFF", "PBLAPTR ", " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static char *arm_r_types[] = { "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", "BR24 ", "T_BR22 ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " }; static void print_r_type( cpu_type_t cputype, unsigned long r_type, enum bool predicted) { if(r_type > 0xf){ printf("%-7lu ", r_type); return; } switch(cputype){ case CPU_TYPE_MC680x0: case CPU_TYPE_I386: printf("%s", generic_r_types[r_type]); break; case CPU_TYPE_X86_64: printf("%s", x86_64_r_types[r_type]); break; case CPU_TYPE_MC88000: printf("%s", m88k_r_types[r_type]); break; case CPU_TYPE_I860: printf("%s", i860_r_types[r_type]); break; case CPU_TYPE_POWERPC: case CPU_TYPE_POWERPC64: case CPU_TYPE_VEO: printf("%s", ppc_r_types[r_type]); if(r_type == PPC_RELOC_BR14){ if(predicted == TRUE) printf("+/- "); else printf(" "); } break; case CPU_TYPE_HPPA: printf("%s", hppa_r_types[r_type]); break; case CPU_TYPE_SPARC: printf("%s", sparc_r_types[r_type]); break; case CPU_TYPE_ARM: printf("%s", arm_r_types[r_type]); break; default: printf("%-7lu ", r_type); } } /* * Print the table of contents. */ void print_toc( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, char *object_addr, unsigned long object_size, struct dylib_table_of_contents *tocs, unsigned long ntocs, struct dylib_module *mods, struct dylib_module_64 *mods64, unsigned long nmods, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, enum bool verbose) { unsigned long i; uint32_t n_strx; uint8_t n_type; printf("Table of contents (%lu entries)\n", ntocs); if(verbose) printf("module name symbol name\n"); else printf("module index symbol index\n"); for(i = 0; i < ntocs; i++){ if(verbose){ if(tocs[i].module_index > nmods) printf("%-16u (past the end of the module table) ", tocs[i].module_index); else if(mods != NULL){ if(mods[tocs[i].module_index].module_name > strings_size) printf("%-16u (string index past the end of string " "table) ", tocs[i].module_index); else printf("%-16s ", strings + mods[tocs[i].module_index].module_name); } else{ if(mods64[tocs[i].module_index].module_name > strings_size) printf("%-16u (string index past the end of string " "table) ", tocs[i].module_index); else printf("%-16s ", strings + mods64[tocs[i].module_index].module_name); } if(tocs[i].symbol_index > nsymbols) printf("%u (past the end of the symbol table)\n", tocs[i].symbol_index); else{ if(symbols != NULL){ n_strx = symbols[tocs[i].symbol_index].n_un.n_strx; n_type = symbols[tocs[i].symbol_index].n_type; } else{ n_strx = symbols64[tocs[i].symbol_index].n_un.n_strx; n_type = symbols64[tocs[i].symbol_index].n_type; } if(n_strx > strings_size){ printf("%u (string index past the end of the string " "table)\n", tocs[i].symbol_index); } else{ printf("%s", strings + n_strx); if(n_type & N_EXT) printf("\n"); else printf(" [private]\n"); } } } else{ printf("%-12u %u\n", tocs[i].module_index, tocs[i].symbol_index); } } } /* * Print the module table (32-bit). */ void print_module_table( struct dylib_module *mods, unsigned long nmods, char *strings, unsigned long strings_size, enum bool verbose) { unsigned long i; printf("Module table (%lu entries)\n", nmods); for(i = 0; i < nmods; i++){ printf("module %lu\n", i); if(verbose){ if(mods[i].module_name > strings_size) printf(" module_name = %u (past end of string table)\n", mods[i].module_name); else printf(" module_name = %s\n", strings + mods[i].module_name); } else{ if(mods[i].module_name > strings_size) printf(" module_name = %u (past end of string table)\n", mods[i].module_name); else printf(" module_name = %u\n", mods[i].module_name); } printf(" iextdefsym = %u\n", mods[i].iextdefsym); printf(" nextdefsym = %u\n", mods[i].nextdefsym); printf(" irefsym = %u\n", mods[i].irefsym); printf(" nrefsym = %u\n", mods[i].nrefsym); printf(" ilocalsym = %u\n", mods[i].ilocalsym); printf(" nlocalsym = %u\n", mods[i].nlocalsym); printf(" iextrel = %u\n", mods[i].iextrel); printf(" nextrel = %u\n", mods[i].nextrel); printf(" iinit_iterm = %u %u\n", mods[i].iinit_iterm & 0xffff, (mods[i].iinit_iterm >> 16) & 0xffff); printf(" ninit_nterm = %u %u\n", mods[i].ninit_nterm & 0xffff, (mods[i].ninit_nterm >> 16) & 0xffff); printf(" objc_addr = 0x%x\n", (unsigned int)mods[i].objc_module_info_addr); printf(" objc_size = %u\n", mods[i].objc_module_info_size); } } /* * Print the module table (64-bit). */ void print_module_table_64( struct dylib_module_64 *mods64, unsigned long nmods, char *strings, unsigned long strings_size, enum bool verbose) { unsigned long i; printf("Module table (%lu entries)\n", nmods); for(i = 0; i < nmods; i++){ printf("module %lu\n", i); if(verbose){ if(mods64[i].module_name > strings_size) printf(" module_name = %u (past end of string table)\n", mods64[i].module_name); else printf(" module_name = %s\n", strings + mods64[i].module_name); } else{ if(mods64[i].module_name > strings_size) printf(" module_name = %u (past end of string table)\n", mods64[i].module_name); else printf(" module_name = %u\n", mods64[i].module_name); } printf(" iextdefsym = %u\n", mods64[i].iextdefsym); printf(" nextdefsym = %u\n", mods64[i].nextdefsym); printf(" irefsym = %u\n", mods64[i].irefsym); printf(" nrefsym = %u\n", mods64[i].nrefsym); printf(" ilocalsym = %u\n", mods64[i].ilocalsym); printf(" nlocalsym = %u\n", mods64[i].nlocalsym); printf(" iextrel = %u\n", mods64[i].iextrel); printf(" nextrel = %u\n", mods64[i].nextrel); printf(" iinit_iterm = %u %u\n", mods64[i].iinit_iterm & 0xffff, (mods64[i].iinit_iterm >> 16) & 0xffff); printf(" ninit_nterm = %u %u\n", mods64[i].ninit_nterm & 0xffff, (mods64[i].ninit_nterm >> 16) & 0xffff); printf(" objc_addr = 0x%016llx\n", mods64[i].objc_module_info_addr); printf(" objc_size = %u\n", mods64[i].objc_module_info_size); } } /* * Print the reference table. */ void print_refs( struct dylib_reference *refs, unsigned long nrefs, struct dylib_module *mods, struct dylib_module_64 *mods64, unsigned long nmods, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, enum bool verbose) { unsigned long i, j; uint32_t module_name, irefsym, nrefsym, n_strx; printf("Reference table (%lu entries)\n", nrefs); for(i = 0; i < nmods; i++){ if(mods != NULL){ module_name = mods[i].module_name; irefsym = mods[i].irefsym; nrefsym = mods[i].nrefsym; } else{ module_name = mods64[i].module_name; irefsym = mods64[i].irefsym; nrefsym = mods64[i].nrefsym; } if(verbose){ if(module_name > strings_size) printf(" module %u (past end of string table)", module_name); else printf(" module %s", strings + module_name); } else{ printf(" module %u", module_name); } if(irefsym > nrefs){ printf(" %u entries, at index %u (past end of reference " "table)\n", nrefsym, irefsym); continue; } if(irefsym + nrefsym > nrefs) printf(" %u entries (extends past the end of the reference " "table), at index %u\n", nrefsym, irefsym); else printf(" %u entries, at index %u\n", nrefsym, irefsym); for(j = irefsym; j - irefsym < nrefsym && j < nrefs; j++){ if(refs[j].isym > nsymbols) printf("\t%u (past the end of the symbol table) ", refs[j].isym); else{ if(verbose){ if(refs[j].isym > nsymbols) printf("\t%u (past the end of the symbol table) ", refs[j].isym); else{ if(symbols != NULL) n_strx = symbols[refs[j].isym].n_un.n_strx; else n_strx = symbols64[refs[j].isym].n_un.n_strx; if(n_strx > strings_size) printf("\t%u (string index past the end of the " "string table) ", refs[j].isym); else printf("\t%s ", strings + n_strx); } } else printf("\tisym %u ", refs[j].isym); } if(verbose){ switch(refs[j].flags){ case REFERENCE_FLAG_UNDEFINED_NON_LAZY: printf("undefined [non-lazy]\n"); break; case REFERENCE_FLAG_UNDEFINED_LAZY: printf("undefined [lazy]\n"); break; case REFERENCE_FLAG_DEFINED: printf("defined\n"); break; case REFERENCE_FLAG_PRIVATE_DEFINED: printf("private defined\n"); break; case REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY: printf("private undefined [non-lazy]\n"); break; case REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY: printf("private undefined [lazy]\n"); break; default: printf("%u\n", (unsigned int)refs[j].flags); break; } } else printf("flags %u\n", (unsigned int)refs[j].flags); } } } /* * Print the indirect symbol table. */ void print_indirect_symbols( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, cpu_type_t cputype, enum byte_sex load_commands_byte_sex, uint32_t *indirect_symbols, unsigned long nindirect_symbols, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, enum bool verbose) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, j, k, left, size, nsects, n, count, stride, section_type; char *p; struct load_command *lc, l; struct segment_command sg; struct section s; struct segment_command_64 sg64; struct section_64 s64; struct section_indirect_info { char segname[16]; char sectname[16]; uint64_t size; uint64_t addr; uint32_t reserved1; uint32_t reserved2; uint32_t flags; } *sect_ind; uint32_t n_strx; sect_ind = NULL; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; /* * Create an array of section structures in the host byte sex so it * can be processed and indexed into directly. */ k = 0; nsects = 0; lc = load_commands; for(i = 0 ; i < ncmds; i++){ memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&l, host_byte_sex); if(l.cmdsize % sizeof(long) != 0) printf("load command %lu size not a multiple of " "sizeof(long)\n", i); if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %lu extends past end of load " "commands\n", i); left = sizeofcmds - ((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_SEGMENT: memset((char *)&sg, '\0', sizeof(struct segment_command)); size = left < sizeof(struct segment_command) ? left : sizeof(struct segment_command); memcpy((char *)&sg, (char *)lc, size); if(swapped) swap_segment_command(&sg, host_byte_sex); nsects += sg.nsects; sect_ind = reallocate(sect_ind, nsects * sizeof(struct section_indirect_info)); memset((char *)(sect_ind + (nsects - sg.nsects)), '\0', sizeof(struct section_indirect_info) * sg.nsects); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ left = sizeofcmds - (p - (char *)load_commands); size = left < sizeof(struct section) ? left : sizeof(struct section); memcpy((char *)&s, p, size); if(swapped) swap_section(&s, 1, host_byte_sex); if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds) break; p += size; memcpy(sect_ind[k].segname, s.segname, 16); memcpy(sect_ind[k].sectname, s.sectname, 16); sect_ind[k].size = s.size; sect_ind[k].addr = s.addr; sect_ind[k].reserved1 = s.reserved1; sect_ind[k].reserved2 = s.reserved2; sect_ind[k].flags = s.flags; k++; } break; case LC_SEGMENT_64: memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); size = left < sizeof(struct segment_command_64) ? left : sizeof(struct segment_command_64); memcpy((char *)&sg64, (char *)lc, size); if(swapped) swap_segment_command_64(&sg64, host_byte_sex); nsects += sg64.nsects; sect_ind = reallocate(sect_ind, nsects * sizeof(struct section_indirect_info)); memset((char *)(sect_ind + (nsects - sg64.nsects)), '\0', sizeof(struct section_indirect_info) * sg64.nsects); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ left = sizeofcmds - (p - (char *)load_commands); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); memcpy((char *)&s64, p, size); if(swapped) swap_section_64(&s64, 1, host_byte_sex); if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds) break; p += size; memcpy(sect_ind[k].segname, s64.segname, 16); memcpy(sect_ind[k].sectname, s64.sectname, 16); sect_ind[k].size = s64.size; sect_ind[k].addr = s64.addr; sect_ind[k].reserved1 = s64.reserved1; sect_ind[k].reserved2 = s64.reserved2; sect_ind[k].flags = s64.flags; k++; } break; } if(l.cmdsize == 0){ printf("load command %lu size zero (can't advance to other " "load commands)\n", i); break; } lc = (struct load_command *)((char *)lc + l.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) break; } if((char *)load_commands + sizeofcmds != (char *)lc) printf("Inconsistent sizeofcmds\n"); for(i = 0 ; i < nsects ; i++){ section_type = sect_ind[i].flags & SECTION_TYPE; if(section_type == S_SYMBOL_STUBS){ stride = sect_ind[i].reserved2; if(stride == 0){ printf("Can't print indirect symbols for (%.16s,%.16s) " "(size of stubs in reserved2 field is zero)\n", sect_ind[i].segname, sect_ind[i].sectname); continue; } } else if(section_type == S_LAZY_SYMBOL_POINTERS || section_type == S_NON_LAZY_SYMBOL_POINTERS){ if(cputype & CPU_ARCH_ABI64) stride = 8; else stride = 4; } else continue; count = sect_ind[i].size / stride; printf("Indirect symbols for (%.16s,%.16s) %lu entries", sect_ind[i].segname, sect_ind[i].sectname, count); n = sect_ind[i].reserved1; if(n > nindirect_symbols) printf(" (entries start past the end of the indirect symbol " "table) (reserved1 field greater than the table size)"); else if(n + count > nindirect_symbols) printf(" (entries extends past the end of the indirect symbol " "table)"); if(cputype & CPU_ARCH_ABI64) printf("\naddress index"); else printf("\naddress index"); if(verbose) printf(" name\n"); else printf("\n"); for(j = 0 ; j < count && n + j < nindirect_symbols; j++){ if(cputype & CPU_ARCH_ABI64) printf("0x%016llx ", sect_ind[i].addr + j * stride); else printf("0x%08x ",(uint32_t) (sect_ind[i].addr + j * stride)); if(indirect_symbols[j + n] == INDIRECT_SYMBOL_LOCAL){ printf("LOCAL\n"); continue; } if(indirect_symbols[j + n] == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)){ printf("LOCAL ABSOLUTE\n"); continue; } printf("%5u ", indirect_symbols[j + n]); if(verbose){ if(indirect_symbols[j + n] >= nsymbols || (symbols == NULL && symbols64 == NULL) || strings == NULL) printf("?\n"); else{ if(symbols != NULL) n_strx = symbols[indirect_symbols[j+n]].n_un.n_strx; else n_strx = symbols64[indirect_symbols[j+n]]. n_un.n_strx; if(n_strx >= strings_size) printf("?\n"); else printf("%s\n", strings + n_strx); } } else printf("\n"); } n += count; } } void print_hints( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex load_commands_byte_sex, struct twolevel_hint *hints, unsigned long nhints, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, enum bool verbose) { enum byte_sex host_byte_sex; enum bool swapped, is_framework; unsigned long i, left, size, nlibs, dyst_cmd, lib_ord; char *p, **libs, *short_name, *has_suffix; struct load_command *lc, l; struct dysymtab_command dyst; struct dylib_command dl; uint32_t n_strx; uint16_t n_desc; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; /* * If verbose is TRUE create an array of load dylibs names so it * indexed into directly. */ nlibs = 0; libs = NULL; dyst_cmd = ULONG_MAX; lc = load_commands; for(i = 0 ; verbose == TRUE && i < ncmds; i++){ memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&l, host_byte_sex); if(l.cmdsize % sizeof(long) != 0) printf("load command %lu size not a multiple of " "sizeof(long)\n", i); if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %lu extends past end of load " "commands\n", i); left = sizeofcmds - ((char *)lc - (char *)load_commands); switch(l.cmd){ case LC_DYSYMTAB: if(dyst_cmd != ULONG_MAX){ printf("more than one LC_DYSYMTAB command (using command " "%lu)\n", dyst_cmd); break; } memset((char *)&dyst, '\0', sizeof(struct dysymtab_command)); size = left < sizeof(struct dysymtab_command) ? left : sizeof(struct dysymtab_command); memcpy((char *)&dyst, (char *)lc, size); if(swapped) swap_dysymtab_command(&dyst, host_byte_sex); dyst_cmd = i; break; case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: case LC_REEXPORT_DYLIB: memset((char *)&dl, '\0', sizeof(struct dylib_command)); size = left < sizeof(struct dylib_command) ? left : sizeof(struct dylib_command); memcpy((char *)&dl, (char *)lc, size); if(swapped) swap_dylib_command(&dl, host_byte_sex); if(dl.dylib.name.offset < dl.cmdsize){ p = (char *)lc + dl.dylib.name.offset; short_name = guess_short_name(p, &is_framework, &has_suffix); if(short_name != NULL) p = short_name; } else{ p = "bad dylib.name.offset"; } libs = reallocate(libs, (nlibs+1) * sizeof(char *)); libs[nlibs] = p; nlibs++; break; } if(l.cmdsize == 0){ printf("load command %lu size zero (can't advance to other " "load commands)\n", i); break; } lc = (struct load_command *)((char *)lc + l.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) break; } if(verbose == TRUE && (char *)load_commands + sizeofcmds != (char *)lc) printf("Inconsistent sizeofcmds\n"); printf("Two-level namespace hints table (%lu hints)\n", nhints); printf("index isub itoc\n"); for(i = 0; i < nhints; i++){ printf("%5lu %5d %5u", i, (int)hints[i].isub_image, hints[i].itoc); if(verbose){ if(dyst_cmd != ULONG_MAX && dyst.iundefsym + i < nsymbols){ if(symbols != NULL){ n_strx = symbols[dyst.iundefsym + i].n_un.n_strx; n_desc = symbols[dyst.iundefsym + i].n_desc; } else{ n_strx = symbols64[dyst.iundefsym + i].n_un.n_strx; n_desc = symbols64[dyst.iundefsym + i].n_desc; } if(n_strx > strings_size) printf(" (bad string index in symbol %lu)\n", dyst.iundefsym + i); else{ printf(" %s", strings + n_strx); lib_ord = GET_LIBRARY_ORDINAL(n_desc); if(lib_ord != SELF_LIBRARY_ORDINAL && lib_ord - 1 < nlibs) printf(" (from %s)\n", libs[lib_ord - 1]); else printf("\n"); } } else printf("\n"); } else printf("\n"); } } void print_cstring_section( char *sect, unsigned long sect_size, unsigned long sect_addr, enum bool print_addresses) { unsigned long i; for(i = 0; i < sect_size ; i++){ if(print_addresses == TRUE) printf("%08x ", (unsigned int)(sect_addr + i)); for( ; i < sect_size && sect[i] != '\0'; i++) print_cstring_char(sect[i]); if(i < sect_size && sect[i] == '\0') printf("\n"); } } static void print_cstring_char( char c) { if(isprint(c)){ if(c == '\\') /* backslash */ printf("\\\\"); else /* all other printable characters */ printf("%c", c); } else{ switch(c){ case '\n': /* newline */ printf("\\n"); break; case '\t': /* tab */ printf("\\t"); break; case '\v': /* vertical tab */ printf("\\v"); break; case '\b': /* backspace */ printf("\\b"); break; case '\r': /* carriage return */ printf("\\r"); break; case '\f': /* formfeed */ printf("\\f"); break; case '\a': /* audiable alert */ printf("\\a"); break; default: printf("\\%03o", (unsigned int)c); } } } void print_literal4_section( char *sect, unsigned long sect_size, unsigned long sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, l; float f; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != literal_byte_sex; for(i = 0; i < sect_size ; i += sizeof(float)){ if(print_addresses == TRUE) printf("%08x ", (unsigned int)(sect_addr + i)); memcpy((char *)&f, sect + i, sizeof(float)); memcpy((char *)&l, sect + i, sizeof(unsigned long)); if(swapped){ f = SWAP_FLOAT(f); l = SWAP_LONG(l); } print_literal4(l, f); } } static void print_literal4( unsigned long l, float f) { printf("0x%08x", (unsigned int)l); if((l & 0x7f800000) != 0x7f800000){ printf(" (%.16e)\n", f); } else{ if(l == 0x7f800000) printf(" (+Infinity)\n"); else if(l == 0xff800000) printf(" (-Infinity)\n"); else if((l & 0x00400000) == 0x00400000) printf(" (non-signaling Not-a-Number)\n"); else printf(" (signaling Not-a-Number)\n"); } } void print_literal8_section( char *sect, unsigned long sect_size, unsigned long sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, l0, l1; double d; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != literal_byte_sex; for(i = 0; i < sect_size ; i += sizeof(double)){ if(print_addresses == TRUE) printf("%08x ", (unsigned int)(sect_addr + i)); memcpy((char *)&d, sect + i, sizeof(double)); memcpy((char *)&l0, sect + i, sizeof(unsigned long)); memcpy((char *)&l1, sect + i + sizeof(unsigned long), sizeof(unsigned long)); if(swapped){ d = SWAP_DOUBLE(d); l0 = SWAP_LONG(l0); l1 = SWAP_LONG(l1); } print_literal8(l0, l1, d); } } static void print_literal8( unsigned long l0, unsigned long l1, double d) { printf("0x%08x 0x%08x", (unsigned int)l0, (unsigned int)l1); /* l0 is the high word, so this is equivalent to if(isfinite(d)) */ if((l0 & 0x7ff00000) != 0x7ff00000) printf(" (%.16e)\n", d); else{ if(l0 == 0x7ff00000 && l1 == 0) printf(" (+Infinity)\n"); else if(l0 == 0xfff00000 && l1 == 0) printf(" (-Infinity)\n"); else if((l0 & 0x00080000) == 0x00080000) printf(" (non-signaling Not-a-Number)\n"); else printf(" (signaling Not-a-Number)\n"); } } void print_literal16_section( char *sect, unsigned long sect_size, unsigned long sect_addr, enum byte_sex literal_byte_sex, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, l0, l1, l2, l3; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != literal_byte_sex; for(i = 0; i < sect_size ; i += 4 * sizeof(unsigned long)){ if(print_addresses == TRUE) printf("%08x ", (unsigned int)(sect_addr + i)); memcpy((char *)&l0, sect + i, sizeof(unsigned long)); memcpy((char *)&l1, sect + i + sizeof(unsigned long), sizeof(unsigned long)); memcpy((char *)&l2, sect + i + 2 * sizeof(unsigned long), sizeof(unsigned long)); memcpy((char *)&l3, sect + i + 3 * sizeof(unsigned long), sizeof(unsigned long)); if(swapped){ l0 = SWAP_LONG(l0); l1 = SWAP_LONG(l1); l2 = SWAP_LONG(l2); l3 = SWAP_LONG(l3); } print_literal16(l0, l1, l2, l3); } } static void print_literal16( unsigned long l0, unsigned long l1, unsigned long l2, unsigned long l3) { printf("0x%08x 0x%08x 0x%08x 0x%08x\n", (unsigned int)l0,\ (unsigned int)l1, (unsigned int)l2, (unsigned int)l3); } void print_literal_pointer_section( struct load_command *load_commands, uint32_t ncmds, uint32_t sizeofcmds, enum byte_sex object_byte_sex, char *object_addr, unsigned long object_size, char *sect, unsigned long sect_size, unsigned long sect_addr, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, struct relocation_info *relocs, unsigned long nrelocs, enum bool print_addresses) { enum byte_sex host_byte_sex; enum bool swapped, found; unsigned long i, j, k, l, l0, l1, left, size; struct load_command lcmd, *lc; struct segment_command sg; struct section s; struct segment_command_64 sg64; struct section_64 s64; struct literal_section { char segname[16]; char sectname[16]; uint64_t addr; uint32_t flags; char *contents; unsigned long size; } *literal_sections; char *p; unsigned long nliteral_sections; float f; double d; struct relocation_info *reloc; uint32_t n_strx; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; literal_sections = NULL; nliteral_sections = 0; lc = load_commands; for(i = 0 ; i < ncmds; i++){ memcpy((char *)&lcmd, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&lcmd, host_byte_sex); if(lcmd.cmdsize % sizeof(long) != 0) printf("load command %lu size not a multiple of " "sizeof(long)\n", i); if((char *)lc + lcmd.cmdsize > (char *)load_commands + sizeofcmds) printf("load command %lu extends past end of load " "commands\n", i); left = sizeofcmds - ((char *)lc - (char *)load_commands); switch(lcmd.cmd){ case LC_SEGMENT: memset((char *)&sg, '\0', sizeof(struct segment_command)); size = left < sizeof(struct segment_command) ? left : sizeof(struct segment_command); memcpy((char *)&sg, (char *)lc, size); if(swapped) swap_segment_command(&sg, host_byte_sex); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds){ printf("section structure command extends past " "end of load commands\n"); } left = sizeofcmds - (p - (char *)load_commands); memset((char *)&s, '\0', sizeof(struct section)); size = left < sizeof(struct section) ? left : sizeof(struct section); memcpy((char *)&s, p, size); if(swapped) swap_section(&s, 1, host_byte_sex); if(s.flags == S_CSTRING_LITERALS || s.flags == S_4BYTE_LITERALS || s.flags == S_8BYTE_LITERALS){ literal_sections = reallocate(literal_sections, sizeof(struct literal_section) * (nliteral_sections + 1)); memcpy(literal_sections[nliteral_sections].segname, s.segname, 16); memcpy(literal_sections[nliteral_sections].sectname, s.sectname, 16); literal_sections[nliteral_sections].addr = s.addr; literal_sections[nliteral_sections].flags = s.flags; literal_sections[nliteral_sections].contents = object_addr + s.offset; if(s.offset > object_size){ printf("section contents of: (%.16s,%.16s) is past " "end of file\n", s.segname, s.sectname); literal_sections[nliteral_sections].size = 0; } else if(s.offset + s.size > object_size){ printf("part of section contents of: (%.16s,%.16s) " "is past end of file\n", s.segname, s.sectname); literal_sections[nliteral_sections].size = object_size - s.offset; } else literal_sections[nliteral_sections].size = s.size; nliteral_sections++; } if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds) break; p += size; } break; case LC_SEGMENT_64: memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); size = left < sizeof(struct segment_command_64) ? left : sizeof(struct segment_command_64); memcpy((char *)&sg64, (char *)lc, size); if(swapped) swap_segment_command_64(&sg64, host_byte_sex); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ if(p + sizeof(struct section_64) > (char *)load_commands + sizeofcmds){ printf("section structure command extends past " "end of load commands\n"); } left = sizeofcmds - (p - (char *)load_commands); memset((char *)&s64, '\0', sizeof(struct section_64)); size = left < sizeof(struct section_64) ? left : sizeof(struct section_64); memcpy((char *)&s64, p, size); if(swapped) swap_section_64(&s64, 1, host_byte_sex); if(s64.flags == S_CSTRING_LITERALS || s64.flags == S_4BYTE_LITERALS || s64.flags == S_8BYTE_LITERALS){ literal_sections = reallocate(literal_sections, sizeof(struct literal_section) * (nliteral_sections + 1)); memcpy(literal_sections[nliteral_sections].segname, s64.segname, 16); memcpy(literal_sections[nliteral_sections].sectname, s64.sectname, 16); literal_sections[nliteral_sections].addr = s64.addr; literal_sections[nliteral_sections].flags = s64.flags; literal_sections[nliteral_sections].contents = object_addr + s64.offset; if(s64.offset > object_size){ printf("section contents of: (%.16s,%.16s) is past " "end of file\n", s64.segname, s64.sectname); literal_sections[nliteral_sections].size = 0; } else if(s64.offset + s64.size > object_size){ printf("part of section contents of: (%.16s,%.16s) " "is past end of file\n", s64.segname, s64.sectname); literal_sections[nliteral_sections].size = object_size - s64.offset; } else literal_sections[nliteral_sections].size = s64.size; nliteral_sections++; } if(p + sizeof(struct section) > (char *)load_commands + sizeofcmds) break; p += size; } break; } if(lcmd.cmdsize == 0){ printf("load command %lu size zero (can't advance to other " "load commands)\n", i); break; } lc = (struct load_command *)((char *)lc + lcmd.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) break; } /* loop through the literal pointer section and print the pointers */ for(i = 0; i < sect_size ; i += sizeof(long)){ if(print_addresses == TRUE) printf("%08x ", (unsigned int)(sect_addr + i)); l = (long)*((long *)(sect + i)); memcpy((char *)&l, sect + i, sizeof(unsigned long)); if(swapped) l = SWAP_LONG(l); /* * If there is an external relocation entry for this pointer then * print the symbol and any offset. */ reloc = bsearch(&i, relocs, nrelocs, sizeof(struct relocation_info), (int (*)(const void *, const void *))rel_bsearch); if(reloc != NULL && (reloc->r_address & R_SCATTERED) == 0 && reloc->r_extern == 1){ printf("external relocation entry for symbol:"); if(reloc->r_symbolnum < nsymbols){ if(symbols != NULL) n_strx = symbols[reloc->r_symbolnum].n_un.n_strx; else n_strx = symbols64[reloc->r_symbolnum].n_un.n_strx; if(n_strx < strings_size){ if(l != 0) printf("%s+0x%x\n", strings + n_strx, (unsigned int)l); else printf("%s\n", strings + n_strx); } else{ printf("bad string index for symbol: %u\n", reloc->r_symbolnum); } } else{ printf("bad relocation entry\n"); } continue; } found = FALSE; for(j = 0; j < nliteral_sections; j++){ if(l >= literal_sections[j].addr && l < literal_sections[j].addr + literal_sections[j].size){ printf("%.16s:%.16s:", literal_sections[j].segname, literal_sections[j].sectname); switch(literal_sections[j].flags){ case S_CSTRING_LITERALS: for(k = l - literal_sections[j].addr; k < literal_sections[j].size && literal_sections[j].contents[k] != '\0'; k++) print_cstring_char(literal_sections[j].contents[k]); printf("\n"); break; case S_4BYTE_LITERALS: memcpy((char *)&f, (char *)(literal_sections[j].contents + l - literal_sections[j].addr), sizeof(float)); memcpy((char *)&l0, (char *)(literal_sections[j].contents + l - literal_sections[j].addr), sizeof(unsigned long)); if(swapped){ d = SWAP_DOUBLE(d); l0 = SWAP_LONG(l0); } print_literal4(l0, f); break; case S_8BYTE_LITERALS: memcpy((char *)&d, (char *)(literal_sections[j].contents + l - literal_sections[j].addr), sizeof(double)); memcpy((char *)&l0, (char *)(literal_sections[j].contents + l - literal_sections[j].addr), sizeof(unsigned long)); memcpy((char *)&l1, (char *)(literal_sections[j].contents + l - literal_sections[j].addr + sizeof(unsigned long)), sizeof(unsigned long)); if(swapped){ d = SWAP_DOUBLE(d); l0 = SWAP_LONG(l0); l1 = SWAP_LONG(l1); } print_literal8(l0, l1, d); break; } found = TRUE; break; } } if(found == FALSE) printf("0x%x (not in a literal section)\n", (unsigned int)l); } if(literal_sections != NULL) free(literal_sections); } void print_init_term_pointer_section( cpu_type_t cputype, char *sect, uint32_t sect_size, uint64_t sect_addr, enum byte_sex object_byte_sex, struct symbol *sorted_symbols, uint32_t nsorted_symbols, enum bool verbose) { uint32_t i, stride, p; uint64_t q; enum byte_sex host_byte_sex; enum bool swapped; const char *name; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; p = 0; q = 0; if(cputype & CPU_ARCH_ABI64) stride = sizeof(uint64_t); else stride = sizeof(uint32_t); for(i = 0 ; i < sect_size; i += stride){ if(cputype & CPU_ARCH_ABI64) printf("0x%016llx ", sect_addr + i * stride); else printf("0x%08x ",(uint32_t)(sect_addr + i * stride)); if(cputype & CPU_ARCH_ABI64) memcpy(&q, sect + i, stride); else memcpy(&p, sect + i, stride); if(swapped == TRUE){ if(cputype & CPU_ARCH_ABI64) q = SWAP_LONG_LONG(q); else p = SWAP_LONG(p); } if(cputype & CPU_ARCH_ABI64) printf("0x%016llx", q); else printf("0x%08x", p); if(verbose == TRUE){ if(cputype & CPU_ARCH_ABI64) name = guess_symbol(q, sorted_symbols, nsorted_symbols, verbose); else name = guess_symbol(p, sorted_symbols, nsorted_symbols, verbose); if(name != NULL) printf(" %s\n", name); else printf("\n"); } else{ printf("\n"); } } } /* * Function for bsearch for searching relocation entries. */ static int rel_bsearch( unsigned long *address, struct relocation_info *rel) { struct scattered_relocation_info *srel; unsigned long r_address; if((rel->r_address & R_SCATTERED) != 0){ srel = (struct scattered_relocation_info *)rel; r_address = srel->r_address; } else r_address = rel->r_address; if(*address == r_address) return(0); if(*address < r_address) return(-1); else return(1); } /* * Print the shared library initialization table. */ void print_shlib_init( enum byte_sex object_byte_sex, char *sect, unsigned long sect_size, unsigned long sect_addr, struct symbol *sorted_symbols, unsigned long nsorted_symbols, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, char *strings, unsigned long strings_size, struct relocation_info *relocs, unsigned long nrelocs, enum bool verbose) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i; struct shlib_init { long value; /* the value to be stored at the address */ long address; /* the address to store the value */ } shlib_init; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; for(i = 0; i < sect_size; i += sizeof(struct shlib_init)){ memcpy((char *)&shlib_init, sect + i, sizeof(struct shlib_init)); if(swapped){ shlib_init.value = SWAP_LONG(shlib_init.value); shlib_init.address = SWAP_LONG(shlib_init.address); } printf("\tvalue 0x%08x ", (unsigned int)shlib_init.value); (void)print_symbol(shlib_init.value, sect_addr + i, 0, relocs, nrelocs, symbols, symbols64, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); printf("\n"); printf("\taddress 0x%08x ", (unsigned int)shlib_init.address); (void)print_symbol(shlib_init.address, sect_addr+i+sizeof(long), 0, relocs, nrelocs, symbols, symbols64, nsymbols, sorted_symbols, nsorted_symbols, strings, strings_size, verbose); printf("\n"); } } /* * Print_symbol prints a symbol name for the addr if a symbol exist with the * same address. Nothing else is printed, no whitespace, no newline. If it * prints something then it returns TRUE, else it returns FALSE. */ enum bool print_symbol( unsigned long value, unsigned long r_address, unsigned long dot_value, struct relocation_info *relocs, unsigned long nrelocs, struct nlist *symbols, struct nlist_64 *symbols64, unsigned long nsymbols, struct symbol *sorted_symbols, unsigned long nsorted_symbols, char *strings, unsigned long strings_size, enum bool verbose) { unsigned long i, offset; struct scattered_relocation_info *sreloc, *pair; unsigned int r_symbolnum; unsigned long n_strx; const char *name, *add, *sub; if(verbose == FALSE) return(FALSE); for(i = 0; i < nrelocs; i++){ if(((relocs[i].r_address) & R_SCATTERED) != 0){ sreloc = (struct scattered_relocation_info *)(relocs + i); if(sreloc->r_type == GENERIC_RELOC_PAIR){ fprintf(stderr, "Stray GENERIC_RELOC_PAIR relocation entry " "%lu\n", i); continue; } if(sreloc->r_type == GENERIC_RELOC_VANILLA){ if(sreloc->r_address == r_address){ name = guess_symbol(sreloc->r_value, sorted_symbols, nsorted_symbols, verbose); offset = value - sreloc->r_value; if(name != NULL){ printf("%s+0x%x", name, (unsigned int)offset); return(TRUE); } } continue; } if(sreloc->r_type != GENERIC_RELOC_SECTDIFF && sreloc->r_type != GENERIC_RELOC_LOCAL_SECTDIFF){ fprintf(stderr, "Unknown relocation r_type for entry " "%lu\n", i); continue; } if(i + 1 < nrelocs){ pair = (struct scattered_relocation_info *)(relocs + i + 1); if(pair->r_scattered == 0 || pair->r_type != GENERIC_RELOC_PAIR){ fprintf(stderr, "No GENERIC_RELOC_PAIR relocation " "entry after entry %lu\n", i); continue; } } else{ fprintf(stderr, "No GENERIC_RELOC_PAIR relocation entry " "after entry %lu\n", i); continue; } i++; /* skip the pair reloc */ if(sreloc->r_address == r_address){ add = guess_symbol(sreloc->r_value, sorted_symbols, nsorted_symbols, verbose); sub = guess_symbol(pair->r_value, sorted_symbols, nsorted_symbols, verbose); offset = value - (sreloc->r_value - pair->r_value); if(add != NULL) printf("%s", add); else printf("0x%x", (unsigned int)sreloc->r_value); if(sub != NULL) printf("-%s", sub); else{ if((unsigned long)pair->r_value == dot_value) printf("-."); else printf("-0x%x", (unsigned int)pair->r_value); } if(offset != 0) printf("+0x%x", (unsigned int)offset); return(TRUE); } } else{ if((unsigned long)relocs[i].r_address == r_address){ r_symbolnum = relocs[i].r_symbolnum; if(relocs[i].r_extern){ if(r_symbolnum >= nsymbols) return(FALSE); if(symbols != NULL) n_strx = symbols[r_symbolnum].n_un.n_strx; else n_strx = symbols64[r_symbolnum].n_un.n_strx; if(n_strx <= 0 || n_strx >= strings_size) return(FALSE); if(value != 0) printf("%s+0x%x", strings + n_strx, (unsigned int)value); else printf("%s", strings + n_strx); return(TRUE); } break; } } } name = guess_symbol(value, sorted_symbols, nsorted_symbols, verbose); if(name != NULL){ printf("%s", name); return(TRUE); } return(FALSE); } /* * guess_symbol() guesses the name for a symbol based on the specified value. * It returns the name of symbol or NULL. It only returns a symbol name if * a symbol with that exact value exists. */ const char * guess_symbol( const uint64_t value, /* the value of this symbol (in) */ const struct symbol *sorted_symbols, const unsigned long nsorted_symbols, const enum bool verbose) { long high, low, mid; if(verbose == FALSE) return(NULL); low = 0; high = nsorted_symbols - 1; mid = (high - low) / 2; while(high >= low){ if(sorted_symbols[mid].n_value == value){ return(sorted_symbols[mid].name); } if(sorted_symbols[mid].n_value > value){ high = mid - 1; mid = (high + low) / 2; } else{ low = mid + 1; mid = (high + low) / 2; } } return(NULL); } /* * guess_indirect_symbol() returns the name of the indirect symbol for the * value passed in or NULL. */ const char * guess_indirect_symbol( const unsigned long value, /* the value of this symbol (in) */ const uint32_t ncmds, const uint32_t sizeofcmds, const struct load_command *load_commands, const enum byte_sex load_commands_byte_sex, const uint32_t *indirect_symbols, const unsigned long nindirect_symbols, const struct nlist *symbols, const struct nlist_64 *symbols64, const unsigned long nsymbols, const char *strings, const unsigned long strings_size) { enum byte_sex host_byte_sex; enum bool swapped; unsigned long i, j, section_type, index, stride; const struct load_command *lc; struct load_command l; struct segment_command sg; struct section s; struct segment_command_64 sg64; struct section_64 s64; char *p; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != load_commands_byte_sex; lc = load_commands; for(i = 0 ; i < ncmds; i++){ memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); if(swapped) swap_load_command(&l, host_byte_sex); if(l.cmdsize % sizeof(long) != 0) return(NULL); if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds) return(NULL); switch(l.cmd){ case LC_SEGMENT: memcpy((char *)&sg, (char *)lc, sizeof(struct segment_command)); if(swapped) swap_segment_command(&sg, host_byte_sex); p = (char *)lc + sizeof(struct segment_command); for(j = 0 ; j < sg.nsects ; j++){ memcpy((char *)&s, p, sizeof(struct section)); p += sizeof(struct section); if(swapped) swap_section(&s, 1, host_byte_sex); section_type = s.flags & SECTION_TYPE; if((section_type == S_NON_LAZY_SYMBOL_POINTERS || section_type == S_LAZY_SYMBOL_POINTERS || section_type == S_SYMBOL_STUBS) && value >= s.addr && value < s.addr + s.size){ if(section_type == S_SYMBOL_STUBS) stride = s.reserved2; else stride = 4; index = s.reserved1 + (value - s.addr) / stride; if(index < nindirect_symbols && symbols != NULL && strings != NULL && indirect_symbols[index] < nsymbols && (unsigned long)symbols[indirect_symbols[index]]. n_un.n_strx < strings_size) return(strings + symbols[indirect_symbols[index]].n_un.n_strx); else return(NULL); } } break; case LC_SEGMENT_64: memcpy((char *)&sg64, (char *)lc, sizeof(struct segment_command_64)); if(swapped) swap_segment_command_64(&sg64, host_byte_sex); p = (char *)lc + sizeof(struct segment_command_64); for(j = 0 ; j < sg64.nsects ; j++){ memcpy((char *)&s64, p, sizeof(struct section_64)); p += sizeof(struct section_64); if(swapped) swap_section_64(&s64, 1, host_byte_sex); section_type = s64.flags & SECTION_TYPE; if((section_type == S_NON_LAZY_SYMBOL_POINTERS || section_type == S_LAZY_SYMBOL_POINTERS || section_type == S_SYMBOL_STUBS) && value >= s64.addr && value < s64.addr + s64.size){ if(section_type == S_SYMBOL_STUBS) stride = s64.reserved2; else stride = 8; index = s64.reserved1 + (value - s64.addr) / stride; if(index < nindirect_symbols && symbols64 != NULL && strings != NULL && indirect_symbols[index] < nsymbols && (unsigned long)symbols64[indirect_symbols[index]]. n_un.n_strx < strings_size) return(strings + symbols64[indirect_symbols[index]].n_un.n_strx); else return(NULL); } } break; } if(l.cmdsize == 0){ return(NULL); } lc = (struct load_command *)((char *)lc + l.cmdsize); if((char *)lc > (char *)load_commands + sizeofcmds) return(NULL); } return(NULL); } void print_sect( cpu_type_t cputype, enum byte_sex object_byte_sex, char *sect, uint64_t size, uint64_t addr) { enum byte_sex host_byte_sex; enum bool swapped; uint64_t i, j; unsigned long long_word; unsigned short short_word; unsigned char byte_word; host_byte_sex = get_host_byte_sex(); swapped = host_byte_sex != object_byte_sex; if(cputype == CPU_TYPE_I386 || cputype == CPU_TYPE_X86_64){ for(i = 0 ; i < size ; i += j , addr += j){ if(cputype & CPU_ARCH_ABI64) printf("%016llx\t", addr); else printf("%08x\t", (uint32_t)addr); for(j = 0; j < 16 * sizeof(char) && i + j < size; j += sizeof(char)){ byte_word = *(sect + i + j); printf("%02x ", (unsigned int)byte_word); } printf("\n"); } } else if(cputype == CPU_TYPE_MC680x0){ for(i = 0 ; i < size ; i += j , addr += j){ printf("%08x ", (unsigned int)addr); for(j = 0; j < 8 * sizeof(short) && i + j < size; j += sizeof(short)){ memcpy(&short_word, sect + i + j, sizeof(short)); if(swapped) short_word = SWAP_SHORT(short_word); printf("%04x ", (unsigned int)short_word); } printf("\n"); } } else{ for(i = 0 ; i < size ; i += j , addr += j){ if(cputype & CPU_ARCH_ABI64) printf("%016llx\t", addr); else printf("%08x\t", (uint32_t)addr); for(j = 0; j < 4 * sizeof(long) && i + j < size; j += sizeof(long)){ memcpy(&long_word, sect + i + j, sizeof(long)); if(swapped) long_word = SWAP_LONG(long_word); printf("%08x ", (unsigned int)long_word); } printf("\n"); } } } /* * Print_label prints a symbol name for the addr if a symbol exist with the * same address in label form, namely:. * * :\n * * The colon and the newline are printed if colon_and_newline is TRUE. */ void print_label( unsigned long addr, enum bool colon_and_newline, struct symbol *sorted_symbols, unsigned long nsorted_symbols) { long high, low, mid; low = 0; high = nsorted_symbols - 1; mid = (high - low) / 2; while(high >= low){ if(sorted_symbols[mid].n_value == addr){ printf("%s", sorted_symbols[mid].name); if(colon_and_newline == TRUE) printf(":\n"); return; } if(sorted_symbols[mid].n_value > addr){ high = mid - 1; mid = (high + low) / 2; } else{ low = mid + 1; mid = (high + low) / 2; } } }