2 Intel Open Source License
4 Copyright (c) 2002-2007 Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
10 Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer. Redistributions
12 in binary form must reproduce the above copyright notice, this list of
13 conditions and the following disclaimer in the documentation and/or
14 other materials provided with the distribution. Neither the name of
15 the Intel Corporation nor the names of its contributors may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
23 ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /// @file xed-disas-macho.cpp
32 /// @author Mark Charney <mark.charney@intel.com>
34 #include "xed-disas-macho.H"
36 #if defined(XED_MAC_OSX_FILE_READER)
38 // mac specific headers
39 #include <mach-o/fat.h>
40 #include <mach-o/loader.h>
41 #include <mach-o/stab.h>
42 #include <mach-o/nlist.h>
45 #include "xed-interface.h"
46 #include "xed-examples-util.h"
52 ////////////////////////////////////////////////////////////////////////////
54 ////////////////////////////////////////////////////////////////////////////
56 swap_endian(xed_uint32_t x)
71 read_fat_header(xed_uint8_t*¤t_position, xed_uint32_t& offset, xed_uint32_t& size)
73 struct fat_header* fh =
74 REINTERPRET_CAST(struct fat_header*,current_position);
76 // we are little endian looking at big endian data
77 if (fh->magic == FAT_CIGAM)
79 xed_uint32_t narch = swap_endian(fh->nfat_arch);
81 for( i=0 ;i< narch; i++)
84 REINTERPRET_CAST(struct fat_arch*,current_position +
85 sizeof(struct fat_header) +
86 i*sizeof(struct fat_arch) );
87 const cpu_type_t cpu_type = swap_endian(fa->cputype);
89 if (cpu_type == CPU_TYPE_I386)
91 offset = swap_endian(fa->offset);
92 size = swap_endian(fa->size);
102 executable(xed_uint32_t flags)
104 return ( (flags & S_ATTR_PURE_INSTRUCTIONS) !=0 ||
105 (flags & S_ATTR_SOME_INSTRUCTIONS) !=0 );
109 process_segment32( xed_decode_file_info_t& decode_info,
111 xed_uint8_t* segment_position,
114 struct segment_command* sc = REINTERPRET_CAST(struct segment_command*,segment_position);
115 xed_uint8_t* start_of_section_data = segment_position + sizeof(struct segment_command);
117 cout << sc->nsects << " sections" << endl;
118 // look through the array of section headers for this segment.
119 for( i=0; i< sc->nsects;i++)
122 REINTERPRET_CAST(struct section*,start_of_section_data + i *sizeof(struct section));
123 if (executable(sp->flags))
125 // this section is executable. Go get it and process it.
126 xed_uint8_t* section_text = start + sp->offset;
127 xed_uint32_t runtime_vaddr = sp->addr;
129 cout << "\tProcessing executable section "
133 #if defined(__LP64__)
134 cout << REINTERPRET_CAST(xed_uint64_t,section_text);
136 cout << REINTERPRET_CAST(xed_uint32_t,section_text);
139 << " len= " << sp->size
140 << " at offset " << sp->offset
141 << " runtime addr " << hex << runtime_vaddr << dec
145 xed_disas_test(&decode_info.dstate,
148 section_text + sp->size,
151 decode_info.decode_only,0);
157 ////////////////////////////////////////////////////////////////////////////
160 process_macho64(xed_uint8_t* start,
162 xed_decode_file_info_t& decode_info)
164 xedex_derror("process_macho64 not done yet");
170 process_macho32(xed_uint8_t* start,
172 xed_decode_file_info_t& decode_info)
174 xed_uint8_t* current_position = start;
175 //current_position is updated when each section is read
177 // the fat header reader bumps current_position to the value for the
178 // correct architecture.
179 xed_uint32_t offset=0; // offset to of load commands for this architecture
182 xed_bool_t okay = read_fat_header(current_position, offset, size);
185 xedex_dwarn("Could not find x86 section of fat binary -- checking for mach header");
188 printf("Offset of load sections = %x\n", offset);
190 // skip to the correct architecture
191 current_position += offset;
193 struct mach_header* mh = REINTERPRET_CAST(struct mach_header*,current_position);
194 if (mh->magic != MH_MAGIC)
196 xedex_derror("Could not find mach header");
199 current_position += sizeof(struct mach_header);
202 printf("Number of load command sections = %d\n", mh->ncmds);
203 // load commands point to segments which contain sections.
204 //xed_uint8_t* segment_position = current_position + mh->sizeofcmds;
205 for( i=0;i< mh->ncmds; i++)
207 struct load_command* lc =
208 REINTERPRET_CAST(struct load_command*,current_position);
209 //current_position += sizeof(struct load_command);
212 printf("load command %d\n",i );
213 if (lc->cmd == LC_SEGMENT)
216 printf("\tload command %d is a LC_SEGMENT\n", i);
217 // we add the FAT offset to the start pointer to get to the relative start point.
218 process_segment32( decode_info, start + offset, current_position, lc->cmdsize );
220 current_position += lc->cmdsize;
221 //segment_position = segment_position + lc->cmdsize;
226 xed_disas_macho(const char* input_file_name,
227 const xed_state_t* dstate,
229 xed_bool_t sixty_four_bit,
230 xed_bool_t decode_only)
232 xed_uint8_t* region = 0;
234 unsigned int len = 0;
235 xed_map_region(input_file_name, &vregion, &len);
236 region = REINTERPRET_CAST(xed_uint8_t*,vregion);
238 xed_decode_file_info_t decode_info;
239 xed_decode_file_info_init(&decode_info,dstate, ninst, decode_only);
243 process_macho64(region, len, decode_info);
247 process_macho32(region, len, decode_info);
249 xed_print_decode_stats();