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-elf.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 disas-elf.cpp
32 /// @author Mark Charney   <mark.charney@intel.com>
33
34 #include "xed-disas-elf.H"
35
36 #if defined(XED_ELF_READER)
37
38 ////////////////////////////////////////////////////////////////////////////
39 #include <elf.h>
40
41 extern "C" {
42 #include "xed-interface.h"
43 #include "xed-portability.h"
44 #include "xed-examples-util.h"
45 }
46
47 #include <string.h>
48 #include <stdlib.h>
49 #include <iostream>
50 #include <iomanip>
51 #include <map>
52 using namespace std;
53 ////////////////////////////////////////////////////////////////////////////
54
55
56 char* 
57 lookup32(Elf32_Word stoffset,
58        void* start,
59        Elf32_Off offset)
60 {
61     char* p = (char*)start + offset;
62     char* q = p + stoffset;
63     // int i;
64     //cout << "p = " << (unsigned int) p <<  endl;
65     //cout << "q = " << (unsigned int) q <<  endl;
66     //for(i=0;i<20;i++)
67     //{
68     //    cout << q[i];
69     //}
70     //cout << endl;
71     return q;
72 }
73
74 char* 
75 lookup64(Elf64_Word stoffset,
76          void* start,
77          Elf64_Off offset)
78 {
79   char* p = (char*)start + offset;
80   char* q = p + stoffset;
81   //int i;
82   //cout << "p = " << (unsigned int) p <<  endl;
83   //cout << "q = " << (unsigned int) q <<  endl;
84   //for( i=0;i<20;i++)
85   //{
86   //    cout << q[i];
87   //}
88   //cout << endl;
89   return q;
90 }
91
92 #include <vector>
93 void make_symbol_vector(map<xed_uint64_t,char*>* sym_map, 
94                         vector<xed_uint64_t>* sym_vec) 
95 {
96     map<xed_uint64_t,char*>::iterator i = sym_map->begin();
97     for( ; i != sym_map->end() ;i ++) {
98         sym_vec->push_back(i->first);
99     }
100     sort(sym_vec->begin(), sym_vec->end());
101 }
102
103
104 #include <algorithm>
105 uint64_t find_symbol_address(vector<xed_uint64_t>* sym_vec, xed_uint64_t tgt) 
106 {
107     vector<xed_uint64_t>::iterator i = lower_bound(sym_vec->begin(), sym_vec->end(), tgt);
108     if (i == sym_vec->end())
109         return 0;
110     if (*i > tgt) {
111         // take previous value
112         if (i != sym_vec->begin())
113             return *(i-1);
114     }
115     if (*i == tgt) {
116         return *i;
117     }
118     return 0;
119     
120 }
121
122 static vector<xed_uint64_t>* global_sym_vec=0;
123 uint64_t find_symbol_address_global(xed_uint64_t tgt) 
124 {
125     return find_symbol_address(global_sym_vec, tgt);
126 }
127
128 static map<xed_uint64_t,char*>* global_sym_map;
129 char* get_symbol(xed_uint64_t a) {
130     map<xed_uint64_t,char*>::iterator i = global_sym_map->find(a);
131     if (i != global_sym_map->end()) {
132          return i->second;
133     }
134     return 0;
135 }
136
137
138 int xed_disassembly_callback_function(
139     uint64_t address,
140     char* symbol_buffer,
141     uint32_t buffer_length,
142     uint64_t* offset,
143     void* caller_data) 
144 {
145     (void)caller_data; /* not used */
146     uint64_t symbol_address = find_symbol_address_global(address);
147     if (symbol_address) {
148         char* symbol  = get_symbol(symbol_address);
149         if (symbol) {
150             if (xed_strlen(symbol) < buffer_length)
151                 xed_strncpy(symbol_buffer, symbol, buffer_length);
152             else {
153                 xed_strncpy(symbol_buffer, symbol, buffer_length-1);
154                 symbol_buffer[buffer_length-1]=0;
155             }
156             *offset = address - symbol_address;
157             return 1;
158         }
159     }
160     return 0;
161 }
162
163 void xed_disas_elf_init() {
164     xed_register_disassembly_callback(xed_disassembly_callback_function);
165 }
166
167
168
169 void
170 disas_test32(const xed_state_t* dstate,
171              void* start, 
172              Elf32_Off offset,
173              Elf32_Word size, 
174              int ninst,
175              Elf32_Addr runtime_vaddr,
176              bool decode_only,
177              map<xed_uint64_t,char*>& sym_map,
178              vector<xed_uint64_t>& sym_vec)
179 {
180   unsigned char* s = (unsigned char*)start;
181   unsigned char* a = (unsigned char*)start + offset;
182   unsigned char* q = a + size; // end of region
183   
184   // pass in a function to retreive valid symbol names
185   global_sym_map = & sym_map;
186   global_sym_vec = & sym_vec;
187   xed_disas_test(dstate, s,a,q, ninst, runtime_vaddr, decode_only,get_symbol);
188 }
189
190 void
191 disas_test64(const xed_state_t* dstate,
192              void* start, 
193              Elf64_Off offset,
194              Elf64_Word size,
195              int ninst,
196              Elf64_Addr runtime_vaddr,
197              bool decode_only,
198              map<xed_uint64_t,char*>& sym_map,
199              vector<xed_uint64_t>& sym_vec)
200 {
201   unsigned char* s = (unsigned char*)start;
202   unsigned char* a = (unsigned char*)start + offset;
203   unsigned char* q = a + size; // end of region
204
205   // pass in a function to retreive valid symbol names
206   global_sym_map = & sym_map;
207   global_sym_vec = & sym_vec;
208   xed_disas_test(dstate, s,a,q, ninst, runtime_vaddr, decode_only,get_symbol);
209 }
210
211
212 void
213 process_elf32(void* start,
214               unsigned int length,
215               const char* tgt_section,
216               const xed_state_t* dstate,
217               int ninst,
218               xed_bool_t decode_only,
219               map<xed_uint64_t,char*>& sym_map,
220               vector<xed_uint64_t>& sym_vec)
221 {
222     Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*) start;
223     if (elf_hdr->e_machine != EM_386) {
224         cerr << "Not an IA32 binary. Consider using the -64 switch" << endl;
225         exit(1);
226     }
227
228     Elf32_Off shoff = elf_hdr->e_shoff;  // section hdr table offset
229     Elf32_Shdr* shp = (Elf32_Shdr*) ((char*)start + shoff);
230     int sect_strings  = elf_hdr->e_shstrndx;
231     //cout << "String section " << sect_strings << endl;
232     int nsect = elf_hdr->e_shnum;
233     int i;
234     for(i=0;i<nsect;i++) {
235         char* name = lookup32(shp[i].sh_name, start, shp[sect_strings].sh_offset);
236         xed_bool_t text = false;
237         if (shp[i].sh_type == SHT_PROGBITS) {
238             if (tgt_section) {
239                 if (strcmp(tgt_section, name)==0) 
240                     text = true;
241             }
242             else if (shp[i].sh_flags & SHF_EXECINSTR)
243                 text = true;
244         }
245
246         if (text) {
247             printf("# SECTION " XED_FMT_D " ", i);
248             printf("%25s ", name);
249             printf("addr " XED_FMT_LX " ",static_cast<xed_uint64_t>(shp[i].sh_addr)); 
250             printf("offset " XED_FMT_LX " ",static_cast<xed_uint64_t>(shp[i].sh_offset));
251             printf("size " XED_FMT_LU " ", static_cast<xed_uint64_t>(shp[i].sh_size));
252             printf("type " XED_FMT_LU "\n", static_cast<xed_uint64_t>(shp[i].sh_type));
253
254             disas_test32(dstate,
255                          start, shp[i].sh_offset, shp[i].sh_size,
256                          ninst,
257                          shp[i].sh_addr,
258                          decode_only,
259                          sym_map, 
260                          sym_vec);
261         }
262
263     }
264
265     (void) length;// pacify compiler
266 }
267
268 void
269 process_elf64(void* start,
270               unsigned int length,
271               const char* tgt_section,
272               const xed_state_t* dstate,
273               int ninst,
274               xed_bool_t decode_only,
275               map<xed_uint64_t,char*>& sym_map,
276               vector<xed_uint64_t>& sym_vec)
277 {
278     Elf64_Ehdr* elf_hdr = (Elf64_Ehdr*) start;
279     if (elf_hdr->e_machine != EM_X86_64) {
280         cerr << "Not an x86-64  binary. Consider not using the -64 switch." << endl;
281         exit(1);
282     }
283
284     Elf64_Off shoff = elf_hdr->e_shoff;  // section hdr table offset
285     Elf64_Shdr* shp = (Elf64_Shdr*) ((char*)start + shoff);
286     Elf64_Half sect_strings  = elf_hdr->e_shstrndx;
287     //cout << "String section " << sect_strings << endl;
288     Elf64_Half nsect = elf_hdr->e_shnum;
289     if (CLIENT_VERBOSE1) 
290         printf("# sections %d\n" , nsect);
291     unsigned int i;
292     xed_bool_t text = false;
293     for( i=0;i<nsect;i++)  {
294         char* name = lookup64(shp[i].sh_name, start, shp[sect_strings].sh_offset);
295         
296         text = false;
297         if (shp[i].sh_type == SHT_PROGBITS) {
298             if (tgt_section) {
299                 if (strcmp(tgt_section, name)==0) 
300                     text = true;
301             }
302             else if (shp[i].sh_flags & SHF_EXECINSTR)
303                 text = true;
304         }
305
306         if (text) {
307             printf("# SECTION " XED_FMT_U " ", i);
308             printf("%25s ", name);
309             printf("addr " XED_FMT_LX " ",static_cast<xed_uint64_t>(shp[i].sh_addr)); 
310             printf("offset " XED_FMT_LX " ",static_cast<xed_uint64_t>(shp[i].sh_offset));
311             printf("size " XED_FMT_LU "\n", static_cast<xed_uint64_t>(shp[i].sh_size));
312             disas_test64(dstate,
313                          start, shp[i].sh_offset, shp[i].sh_size, 
314                          ninst,
315                          shp[i].sh_addr, decode_only, sym_map, sym_vec);
316
317         }
318     }
319     (void) length;// pacify compiler
320 }
321
322
323 void read_symbols64(void* start, 
324                     Elf64_Off offset,
325                     Elf64_Word size,
326                     Elf64_Off string_table_offset,
327                     map<xed_uint64_t,char*>& sym_map) {
328     char* a = static_cast<char*>(start);
329     Elf64_Sym* p = reinterpret_cast<Elf64_Sym*>(a + offset);
330     Elf64_Sym* q = reinterpret_cast<Elf64_Sym*>(a + offset + size);
331     int i = 0;
332     while(p<q) {
333         char* name = lookup64(p->st_name, start, string_table_offset);
334 /*
335         cout << "SYM " << setw(3) << i << " " 
336              << hex << setw(16) 
337              << p->st_value << dec
338              << " " << name << endl;
339 */
340         if (xed_strlen(name) > 0)
341             sym_map[static_cast<xed_uint64_t>(p->st_value)] = name;
342         p++; 
343         i++;
344     }
345 }
346
347 /*-----------------------------------------------------------------*/
348
349 int check_binary_32b(void* start) {
350     Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*) start;
351     if (elf_hdr->e_machine == EM_386) 
352         return 1;
353     return 0;
354 }
355
356 int check_binary_64b(void* start) {
357     Elf64_Ehdr* elf_hdr = (Elf64_Ehdr*) start;
358     if (elf_hdr->e_machine == EM_X86_64) 
359         return 1;
360     return 0;
361 }
362 /*-----------------------------------------------------------------*/
363
364
365 void symbols_elf64(void* start, map<xed_uint64_t,char*>& sym_map) {
366     Elf64_Ehdr* elf_hdr = (Elf64_Ehdr*) start;
367     if (elf_hdr->e_machine != EM_X86_64) {
368         cerr << "Not an x86-64  binary. Consider not using the -64 switch." << endl;
369         exit(1);
370     }
371
372     Elf64_Off shoff = elf_hdr->e_shoff;  // section hdr table offset
373     Elf64_Shdr* shp = (Elf64_Shdr*) ((char*)start + shoff);
374     Elf64_Half nsect = elf_hdr->e_shnum;
375     if (CLIENT_VERBOSE1) 
376         printf("# sections %d\n" , nsect);
377     unsigned int i;
378     Elf64_Half sect_strings  = elf_hdr->e_shstrndx;
379     Elf64_Off string_table_offset=0;
380     Elf64_Off dynamic_string_table_offset=0;
381     for( i=0;i<nsect;i++)  {
382         if (shp[i].sh_type == SHT_STRTAB) {
383             char* name = lookup32(shp[i].sh_name, start, shp[sect_strings].sh_offset);
384             if (strcmp(name,".strtab")==0) {
385                 cout << "# Found strtab: " << i 
386                      << " offset " <<shp[i].sh_offset
387                      << " size " << shp[i].sh_size 
388                      << endl;
389                 string_table_offset = shp[i].sh_offset;
390             }
391             if (strcmp(name,".dynstr")==0) {
392                 cout << "# Found dynamic strtab: " << i 
393                      << " offset " <<shp[i].sh_offset
394                      << " size " << shp[i].sh_size 
395                      << endl;
396                 dynamic_string_table_offset = shp[i].sh_offset;
397             }
398         }
399     }
400
401     for( i=0;i<nsect;i++)  {
402         if (shp[i].sh_type == SHT_SYMTAB) {
403             cout << "# Found symtab: " << i 
404                  << " offset " <<shp[i].sh_offset
405                  << " size " << shp[i].sh_size 
406                  << endl;
407             read_symbols64(start,shp[i].sh_offset, shp[i].sh_size, string_table_offset,sym_map);
408         }
409         else if (shp[i].sh_type == SHT_DYNSYM) {
410             cout << "# Found dynamic symtab: " << i 
411                  << " offset " <<shp[i].sh_offset
412                  << " size " << shp[i].sh_size 
413                  << endl;
414             read_symbols64(start,shp[i].sh_offset, shp[i].sh_size, dynamic_string_table_offset, sym_map);
415         }
416     }
417 }
418
419
420
421 void read_symbols32(void* start, 
422                     Elf32_Off offset,
423                     Elf32_Word size,
424                     Elf32_Off string_table_offset,
425                     map<xed_uint64_t,char*>& sym_map) {
426     char* a = static_cast<char*>(start);
427     Elf32_Sym* p = reinterpret_cast<Elf32_Sym*>(a + offset);
428     Elf32_Sym* q = reinterpret_cast<Elf32_Sym*>(a + offset + size);
429     int i = 0;
430     while(p<q) {
431         char* name = lookup32(p->st_name, start, string_table_offset);
432 /*
433         cout << "SYM " << setw(3) << i << " " 
434              << hex << setw(16) 
435              << p->st_value << dec
436              << " " << name << endl;
437 */
438         if (xed_strlen(name) > 0)
439             sym_map[static_cast<xed_uint64_t>(p->st_value)] = name;
440         p++; 
441         i++;
442     }
443 }
444
445
446 void symbols_elf32(void* start, map<xed_uint64_t,char*>& sym_map) {
447     Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*) start;
448     if (elf_hdr->e_machine != EM_386) {
449         cerr << "Not an IA32 binary. Consider using the -64 switch" << endl;
450         exit(1);
451     }
452
453     Elf32_Off shoff = elf_hdr->e_shoff;  // section hdr table offset
454     Elf32_Shdr* shp = (Elf32_Shdr*) ((char*)start + shoff);
455     Elf32_Half nsect = elf_hdr->e_shnum;
456     if (CLIENT_VERBOSE1) 
457         printf("# sections %d\n" , nsect);
458     unsigned int i;
459     Elf32_Off string_table_offset=0;
460     Elf32_Off dynamic_string_table_offset=0;
461     int sect_strings  = elf_hdr->e_shstrndx;
462
463     for( i=0;i<nsect;i++)  {
464         
465         if (shp[i].sh_type == SHT_STRTAB) {
466             char* name = lookup32(shp[i].sh_name, start, shp[sect_strings].sh_offset);
467             if (strcmp(name,".strtab")==0) {
468                 cout << "# Found strtab: " << i 
469                      << " offset " <<shp[i].sh_offset
470                      << " size " << shp[i].sh_size 
471                      << endl;
472                 string_table_offset = shp[i].sh_offset;
473             }
474             if (strcmp(name,".dynstr")==0) {
475                 cout << "# Found dynamic strtab: " << i 
476                      << " offset " <<shp[i].sh_offset
477                      << " size " << shp[i].sh_size 
478                      << endl;
479                 dynamic_string_table_offset = shp[i].sh_offset;
480             }
481         }
482     }
483
484     for( i=0;i<nsect;i++)  {
485         
486         if (shp[i].sh_type == SHT_SYMTAB) {
487             cout << "# Found symtab: " << i 
488                  << " offset " <<shp[i].sh_offset
489                  << " size " << shp[i].sh_size 
490                  << endl;
491             read_symbols32(start,shp[i].sh_offset, shp[i].sh_size, string_table_offset,sym_map);
492         } 
493         else if (shp[i].sh_type == SHT_DYNSYM) {
494             cout << "# Found dynamic symtab: " << i 
495                  << " offset " <<shp[i].sh_offset
496                  << " size " << shp[i].sh_size 
497                  << endl;
498             read_symbols32(start,shp[i].sh_offset, shp[i].sh_size, dynamic_string_table_offset, sym_map);
499         }
500     }
501 }
502
503
504
505
506 void
507 xed_disas_elf(const char* input_file_name,
508               const xed_state_t* dstate,
509               int ninst,
510               xed_bool_t sixty_four_bit,
511               xed_bool_t decode_only,
512               const char* target_section)
513 {
514
515     void* region = 0;
516     unsigned int len = 0;
517     xed_disas_elf_init();
518     xed_map_region(input_file_name, &region, &len);
519     
520
521     map<xed_uint64_t,char*> sym_map;
522     vector<xed_uint64_t> sym_vec;
523
524     if (check_binary_64b(region)) {
525         xed_state_t local_dstate = *dstate;
526         if (sixty_four_bit == 0) {
527             /* modify the default dstate values because we were not expecting a
528              * 64b binary */
529             local_dstate.mmode = XED_MACHINE_MODE_LONG_64;
530             local_dstate.addr_width = XED_ADDRESS_WIDTH_64b;
531         }
532
533         symbols_elf64(region, sym_map);
534         make_symbol_vector(&sym_map, &sym_vec);
535         process_elf64(region, len, target_section, &local_dstate, ninst, decode_only, sym_map,sym_vec);
536     }
537     else if (check_binary_32b(region)) {
538         symbols_elf32(region, sym_map);
539         make_symbol_vector(&sym_map, &sym_vec);
540         process_elf32(region, len, target_section, dstate, ninst, decode_only,sym_map, sym_vec);
541     }
542     else {
543         cerr << "Not a recognized 32b or 64b ELF binary." << endl;
544         exit(1);
545     }
546     xed_print_decode_stats();
547
548 }
549  
550
551
552 #endif
553 ////////////////////////////////////////////////////////////////////////////