Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / misc / decoder_test / XED2 / examples / xed-disas-macho.cpp
1 /*BEGIN_LEGAL 
2 Intel Open Source License 
3
4 Copyright (c) 2002-2007 Intel Corporation 
5 All rights reserved. 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
8 met:
9
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.
18  
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.
30 END_LEGAL */
31 /// @file xed-disas-macho.cpp
32 /// @author Mark Charney   <mark.charney@intel.com>
33
34 #include "xed-disas-macho.H"
35
36 #if defined(XED_MAC_OSX_FILE_READER)
37
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>
43
44 extern "C" {
45 #include "xed-interface.h"
46 #include "xed-examples-util.h"
47 }
48 #include <string.h>
49 #include <iostream>
50 using namespace std;
51
52 ////////////////////////////////////////////////////////////////////////////
53
54 ////////////////////////////////////////////////////////////////////////////
55 xed_uint32_t 
56 swap_endian(xed_uint32_t x)
57 {
58     xed_uint32_t r = 0;
59     xed_uint32_t t = x;
60     xed_uint_t i; 
61     for(i=0;i<4;i++)
62     {
63         xed_uint8_t b = t;
64         r =(r << 8)  | b;
65         t = t >> 8;
66     }
67     return r;
68 }
69
70 xed_bool_t
71 read_fat_header(xed_uint8_t*&current_position, xed_uint32_t& offset, xed_uint32_t& size)
72 {
73     struct fat_header* fh =
74         REINTERPRET_CAST(struct fat_header*,current_position);
75     
76     // we are little endian looking at big endian data
77     if (fh->magic == FAT_CIGAM)
78     {
79         xed_uint32_t narch = swap_endian(fh->nfat_arch);
80         unsigned int i;
81         for( i=0 ;i< narch; i++)
82         {
83             struct fat_arch* fa = 
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);
88
89             if (cpu_type == CPU_TYPE_I386)
90             {
91                 offset  = swap_endian(fa->offset);   
92                 size   = swap_endian(fa->size);   
93                 return true;
94             }
95         }
96     }
97     return false;
98 }
99
100
101 static xed_bool_t 
102 executable(xed_uint32_t flags)
103 {
104     return ( (flags & S_ATTR_PURE_INSTRUCTIONS) !=0  || 
105              (flags & S_ATTR_SOME_INSTRUCTIONS) !=0  );
106 }
107
108 void
109 process_segment32( xed_decode_file_info_t& decode_info,
110                    xed_uint8_t* start,
111                    xed_uint8_t* segment_position,
112                    unsigned int bytes)
113 {
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);
116     unsigned int i;
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++)
120     {
121         struct section* sp = 
122             REINTERPRET_CAST(struct section*,start_of_section_data + i *sizeof(struct section));
123         if (executable(sp->flags))
124         {
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;
128
129             cout << "\tProcessing executable section "
130                  << i 
131                  << " addr in mem: " 
132                  << hex;
133 #if defined(__LP64__)
134             cout << REINTERPRET_CAST(xed_uint64_t,section_text);
135 #else
136             cout << REINTERPRET_CAST(xed_uint32_t,section_text);
137 #endif
138             cout << dec
139                  << " len= " <<  sp->size 
140                  << " at offset " << sp->offset
141                  << " runtime addr " << hex << runtime_vaddr << dec
142                  << endl;
143
144
145             xed_disas_test(&decode_info.dstate, 
146                            start,
147                            section_text, 
148                            section_text + sp->size,
149                            decode_info.ninst,
150                            runtime_vaddr,
151                            decode_info.decode_only,0);
152         }
153
154     }
155 }
156
157 ////////////////////////////////////////////////////////////////////////////
158
159 void
160 process_macho64(xed_uint8_t* start,
161                 unsigned int length,
162                 xed_decode_file_info_t& decode_info)
163 {
164     xedex_derror("process_macho64 not done yet");
165 }
166
167
168
169 void
170 process_macho32(xed_uint8_t* start,
171                 unsigned int length,
172                 xed_decode_file_info_t& decode_info)
173 {
174     xed_uint8_t* current_position = start;
175     //current_position is updated when each section is read
176
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
180     xed_uint32_t size;
181     xed_uint_t i;
182     xed_bool_t okay = read_fat_header(current_position, offset, size);
183     if (!okay)
184     {
185         xedex_dwarn("Could not find x86 section of fat binary -- checking for mach header");
186     }
187     if (CLIENT_VERBOSE2)
188         printf("Offset of load sections = %x\n", offset);
189
190     // skip to the correct architecture
191     current_position += offset;
192
193     struct mach_header* mh = REINTERPRET_CAST(struct mach_header*,current_position);
194     if (mh->magic != MH_MAGIC)
195     {
196          xedex_derror("Could not find mach header");
197     }
198
199     current_position += sizeof(struct mach_header);
200
201     if (CLIENT_VERBOSE2)
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++)
206     {
207         struct load_command* lc = 
208             REINTERPRET_CAST(struct load_command*,current_position);
209         //current_position += sizeof(struct load_command);
210     
211         if (CLIENT_VERBOSE2)
212             printf("load command %d\n",i );
213         if (lc->cmd == LC_SEGMENT)
214         {
215             if (CLIENT_VERBOSE2)
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 );
219         }
220         current_position += lc->cmdsize;
221         //segment_position = segment_position + lc->cmdsize;
222     }
223 }
224
225 void
226 xed_disas_macho(const char* input_file_name,
227                 const xed_state_t* dstate,
228                 int ninst,
229                 xed_bool_t sixty_four_bit,
230                 xed_bool_t decode_only)
231 {
232     xed_uint8_t* region = 0;
233     void* vregion = 0;
234     unsigned int len = 0;
235     xed_map_region(input_file_name, &vregion, &len);
236     region = REINTERPRET_CAST(xed_uint8_t*,vregion);
237     
238     xed_decode_file_info_t decode_info;
239     xed_decode_file_info_init(&decode_info,dstate, ninst, decode_only);    
240
241     if (sixty_four_bit) 
242     {
243         process_macho64(region, len, decode_info);
244     }
245     else 
246     {
247         process_macho32(region, len, decode_info);
248     }
249     xed_print_decode_stats();
250 }
251  
252
253
254 #endif