--- /dev/null
+/*BEGIN_LEGAL
+Intel Open Source License
+
+Copyright (c) 2002-2007 Intel Corporation
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer. Redistributions
+in binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution. Neither the name of
+the Intel Corporation nor the names of its contributors may be used to
+endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
+ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+END_LEGAL */
+/// @file xed-disas-macho.cpp
+/// @author Mark Charney <mark.charney@intel.com>
+
+#include "xed-disas-macho.H"
+
+#if defined(XED_MAC_OSX_FILE_READER)
+
+// mac specific headers
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <mach-o/stab.h>
+#include <mach-o/nlist.h>
+
+extern "C" {
+#include "xed-interface.h"
+#include "xed-examples-util.h"
+}
+#include <string.h>
+#include <iostream>
+using namespace std;
+
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+xed_uint32_t
+swap_endian(xed_uint32_t x)
+{
+ xed_uint32_t r = 0;
+ xed_uint32_t t = x;
+ xed_uint_t i;
+ for(i=0;i<4;i++)
+ {
+ xed_uint8_t b = t;
+ r =(r << 8) | b;
+ t = t >> 8;
+ }
+ return r;
+}
+
+xed_bool_t
+read_fat_header(xed_uint8_t*¤t_position, xed_uint32_t& offset, xed_uint32_t& size)
+{
+ struct fat_header* fh =
+ REINTERPRET_CAST(struct fat_header*,current_position);
+
+ // we are little endian looking at big endian data
+ if (fh->magic == FAT_CIGAM)
+ {
+ xed_uint32_t narch = swap_endian(fh->nfat_arch);
+ unsigned int i;
+ for( i=0 ;i< narch; i++)
+ {
+ struct fat_arch* fa =
+ REINTERPRET_CAST(struct fat_arch*,current_position +
+ sizeof(struct fat_header) +
+ i*sizeof(struct fat_arch) );
+ const cpu_type_t cpu_type = swap_endian(fa->cputype);
+
+ if (cpu_type == CPU_TYPE_I386)
+ {
+ offset = swap_endian(fa->offset);
+ size = swap_endian(fa->size);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+static xed_bool_t
+executable(xed_uint32_t flags)
+{
+ return ( (flags & S_ATTR_PURE_INSTRUCTIONS) !=0 ||
+ (flags & S_ATTR_SOME_INSTRUCTIONS) !=0 );
+}
+
+void
+process_segment32( xed_decode_file_info_t& decode_info,
+ xed_uint8_t* start,
+ xed_uint8_t* segment_position,
+ unsigned int bytes)
+{
+ struct segment_command* sc = REINTERPRET_CAST(struct segment_command*,segment_position);
+ xed_uint8_t* start_of_section_data = segment_position + sizeof(struct segment_command);
+ unsigned int i;
+ cout << sc->nsects << " sections" << endl;
+ // look through the array of section headers for this segment.
+ for( i=0; i< sc->nsects;i++)
+ {
+ struct section* sp =
+ REINTERPRET_CAST(struct section*,start_of_section_data + i *sizeof(struct section));
+ if (executable(sp->flags))
+ {
+ // this section is executable. Go get it and process it.
+ xed_uint8_t* section_text = start + sp->offset;
+ xed_uint32_t runtime_vaddr = sp->addr;
+
+ cout << "\tProcessing executable section "
+ << i
+ << " addr in mem: "
+ << hex;
+#if defined(__LP64__)
+ cout << REINTERPRET_CAST(xed_uint64_t,section_text);
+#else
+ cout << REINTERPRET_CAST(xed_uint32_t,section_text);
+#endif
+ cout << dec
+ << " len= " << sp->size
+ << " at offset " << sp->offset
+ << " runtime addr " << hex << runtime_vaddr << dec
+ << endl;
+
+
+ xed_disas_test(&decode_info.dstate,
+ start,
+ section_text,
+ section_text + sp->size,
+ decode_info.ninst,
+ runtime_vaddr,
+ decode_info.decode_only,0);
+ }
+
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+void
+process_macho64(xed_uint8_t* start,
+ unsigned int length,
+ xed_decode_file_info_t& decode_info)
+{
+ xedex_derror("process_macho64 not done yet");
+}
+
+
+
+void
+process_macho32(xed_uint8_t* start,
+ unsigned int length,
+ xed_decode_file_info_t& decode_info)
+{
+ xed_uint8_t* current_position = start;
+ //current_position is updated when each section is read
+
+ // the fat header reader bumps current_position to the value for the
+ // correct architecture.
+ xed_uint32_t offset=0; // offset to of load commands for this architecture
+ xed_uint32_t size;
+ xed_uint_t i;
+ xed_bool_t okay = read_fat_header(current_position, offset, size);
+ if (!okay)
+ {
+ xedex_dwarn("Could not find x86 section of fat binary -- checking for mach header");
+ }
+ if (CLIENT_VERBOSE2)
+ printf("Offset of load sections = %x\n", offset);
+
+ // skip to the correct architecture
+ current_position += offset;
+
+ struct mach_header* mh = REINTERPRET_CAST(struct mach_header*,current_position);
+ if (mh->magic != MH_MAGIC)
+ {
+ xedex_derror("Could not find mach header");
+ }
+
+ current_position += sizeof(struct mach_header);
+
+ if (CLIENT_VERBOSE2)
+ printf("Number of load command sections = %d\n", mh->ncmds);
+ // load commands point to segments which contain sections.
+ //xed_uint8_t* segment_position = current_position + mh->sizeofcmds;
+ for( i=0;i< mh->ncmds; i++)
+ {
+ struct load_command* lc =
+ REINTERPRET_CAST(struct load_command*,current_position);
+ //current_position += sizeof(struct load_command);
+
+ if (CLIENT_VERBOSE2)
+ printf("load command %d\n",i );
+ if (lc->cmd == LC_SEGMENT)
+ {
+ if (CLIENT_VERBOSE2)
+ printf("\tload command %d is a LC_SEGMENT\n", i);
+ // we add the FAT offset to the start pointer to get to the relative start point.
+ process_segment32( decode_info, start + offset, current_position, lc->cmdsize );
+ }
+ current_position += lc->cmdsize;
+ //segment_position = segment_position + lc->cmdsize;
+ }
+}
+
+void
+xed_disas_macho(const char* input_file_name,
+ const xed_state_t* dstate,
+ int ninst,
+ xed_bool_t sixty_four_bit,
+ xed_bool_t decode_only)
+{
+ xed_uint8_t* region = 0;
+ void* vregion = 0;
+ unsigned int len = 0;
+ xed_map_region(input_file_name, &vregion, &len);
+ region = REINTERPRET_CAST(xed_uint8_t*,vregion);
+
+ xed_decode_file_info_t decode_info;
+ xed_decode_file_info_init(&decode_info,dstate, ninst, decode_only);
+
+ if (sixty_four_bit)
+ {
+ process_macho64(region, len, decode_info);
+ }
+ else
+ {
+ process_macho32(region, len, decode_info);
+ }
+ xed_print_decode_stats();
+}
+
+
+
+#endif