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 disas-elf.cpp
32 /// @author Mark Charney <mark.charney@intel.com>
34 #include "xed-disas-elf.H"
36 #if defined(XED_ELF_READER)
38 ////////////////////////////////////////////////////////////////////////////
42 #include "xed-interface.h"
43 #include "xed-portability.h"
44 #include "xed-examples-util.h"
53 ////////////////////////////////////////////////////////////////////////////
57 lookup32(Elf32_Word stoffset,
61 char* p = (char*)start + offset;
62 char* q = p + stoffset;
64 //cout << "p = " << (unsigned int) p << endl;
65 //cout << "q = " << (unsigned int) q << endl;
75 lookup64(Elf64_Word stoffset,
79 char* p = (char*)start + offset;
80 char* q = p + stoffset;
82 //cout << "p = " << (unsigned int) p << endl;
83 //cout << "q = " << (unsigned int) q << endl;
93 void make_symbol_vector(map<xed_uint64_t,char*>* sym_map,
94 vector<xed_uint64_t>* sym_vec)
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);
100 sort(sym_vec->begin(), sym_vec->end());
105 uint64_t find_symbol_address(vector<xed_uint64_t>* sym_vec, xed_uint64_t tgt)
107 vector<xed_uint64_t>::iterator i = lower_bound(sym_vec->begin(), sym_vec->end(), tgt);
108 if (i == sym_vec->end())
111 // take previous value
112 if (i != sym_vec->begin())
122 static vector<xed_uint64_t>* global_sym_vec=0;
123 uint64_t find_symbol_address_global(xed_uint64_t tgt)
125 return find_symbol_address(global_sym_vec, tgt);
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()) {
138 int xed_disassembly_callback_function(
141 uint32_t buffer_length,
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);
150 if (xed_strlen(symbol) < buffer_length)
151 xed_strncpy(symbol_buffer, symbol, buffer_length);
153 xed_strncpy(symbol_buffer, symbol, buffer_length-1);
154 symbol_buffer[buffer_length-1]=0;
156 *offset = address - symbol_address;
163 void xed_disas_elf_init() {
164 xed_register_disassembly_callback(xed_disassembly_callback_function);
170 disas_test32(const xed_state_t* dstate,
175 Elf32_Addr runtime_vaddr,
177 map<xed_uint64_t,char*>& sym_map,
178 vector<xed_uint64_t>& sym_vec)
180 unsigned char* s = (unsigned char*)start;
181 unsigned char* a = (unsigned char*)start + offset;
182 unsigned char* q = a + size; // end of region
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);
191 disas_test64(const xed_state_t* dstate,
196 Elf64_Addr runtime_vaddr,
198 map<xed_uint64_t,char*>& sym_map,
199 vector<xed_uint64_t>& sym_vec)
201 unsigned char* s = (unsigned char*)start;
202 unsigned char* a = (unsigned char*)start + offset;
203 unsigned char* q = a + size; // end of region
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);
213 process_elf32(void* start,
215 const char* tgt_section,
216 const xed_state_t* dstate,
218 xed_bool_t decode_only,
219 map<xed_uint64_t,char*>& sym_map,
220 vector<xed_uint64_t>& sym_vec)
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;
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;
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) {
239 if (strcmp(tgt_section, name)==0)
242 else if (shp[i].sh_flags & SHF_EXECINSTR)
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));
255 start, shp[i].sh_offset, shp[i].sh_size,
265 (void) length;// pacify compiler
269 process_elf64(void* start,
271 const char* tgt_section,
272 const xed_state_t* dstate,
274 xed_bool_t decode_only,
275 map<xed_uint64_t,char*>& sym_map,
276 vector<xed_uint64_t>& sym_vec)
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;
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;
290 printf("# sections %d\n" , nsect);
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);
297 if (shp[i].sh_type == SHT_PROGBITS) {
299 if (strcmp(tgt_section, name)==0)
302 else if (shp[i].sh_flags & SHF_EXECINSTR)
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));
313 start, shp[i].sh_offset, shp[i].sh_size,
315 shp[i].sh_addr, decode_only, sym_map, sym_vec);
319 (void) length;// pacify compiler
323 void read_symbols64(void* start,
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);
333 char* name = lookup64(p->st_name, start, string_table_offset);
335 cout << "SYM " << setw(3) << i << " "
337 << p->st_value << dec
338 << " " << name << endl;
340 if (xed_strlen(name) > 0)
341 sym_map[static_cast<xed_uint64_t>(p->st_value)] = name;
347 /*-----------------------------------------------------------------*/
349 int check_binary_32b(void* start) {
350 Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*) start;
351 if (elf_hdr->e_machine == EM_386)
356 int check_binary_64b(void* start) {
357 Elf64_Ehdr* elf_hdr = (Elf64_Ehdr*) start;
358 if (elf_hdr->e_machine == EM_X86_64)
362 /*-----------------------------------------------------------------*/
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;
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;
376 printf("# sections %d\n" , nsect);
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
389 string_table_offset = shp[i].sh_offset;
391 if (strcmp(name,".dynstr")==0) {
392 cout << "# Found dynamic strtab: " << i
393 << " offset " <<shp[i].sh_offset
394 << " size " << shp[i].sh_size
396 dynamic_string_table_offset = shp[i].sh_offset;
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
407 read_symbols64(start,shp[i].sh_offset, shp[i].sh_size, string_table_offset,sym_map);
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
414 read_symbols64(start,shp[i].sh_offset, shp[i].sh_size, dynamic_string_table_offset, sym_map);
421 void read_symbols32(void* start,
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);
431 char* name = lookup32(p->st_name, start, string_table_offset);
433 cout << "SYM " << setw(3) << i << " "
435 << p->st_value << dec
436 << " " << name << endl;
438 if (xed_strlen(name) > 0)
439 sym_map[static_cast<xed_uint64_t>(p->st_value)] = name;
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;
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;
457 printf("# sections %d\n" , nsect);
459 Elf32_Off string_table_offset=0;
460 Elf32_Off dynamic_string_table_offset=0;
461 int sect_strings = elf_hdr->e_shstrndx;
463 for( i=0;i<nsect;i++) {
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
472 string_table_offset = shp[i].sh_offset;
474 if (strcmp(name,".dynstr")==0) {
475 cout << "# Found dynamic strtab: " << i
476 << " offset " <<shp[i].sh_offset
477 << " size " << shp[i].sh_size
479 dynamic_string_table_offset = shp[i].sh_offset;
484 for( i=0;i<nsect;i++) {
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
491 read_symbols32(start,shp[i].sh_offset, shp[i].sh_size, string_table_offset,sym_map);
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
498 read_symbols32(start,shp[i].sh_offset, shp[i].sh_size, dynamic_string_table_offset, sym_map);
507 xed_disas_elf(const char* input_file_name,
508 const xed_state_t* dstate,
510 xed_bool_t sixty_four_bit,
511 xed_bool_t decode_only,
512 const char* target_section)
516 unsigned int len = 0;
517 xed_disas_elf_init();
518 xed_map_region(input_file_name, ®ion, &len);
521 map<xed_uint64_t,char*> sym_map;
522 vector<xed_uint64_t> sym_vec;
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
529 local_dstate.mmode = XED_MACHINE_MODE_LONG_64;
530 local_dstate.addr_width = XED_ADDRESS_WIDTH_64b;
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);
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);
543 cerr << "Not a recognized 32b or 64b ELF binary." << endl;
546 xed_print_decode_stats();
553 ////////////////////////////////////////////////////////////////////////////