4 #include "AsmUnparser_compat.h"
36 <<
" [" <<unparseInstruction(
insn) <<
"]"
41 for (
size_t i=0; i<
bytes.size(); i++) {
43 <<std::hex <<std::setfill(
'0') <<std::setw(2)
45 <<std::dec <<std::setfill(
' ') <<std::setw(1);
47 o <<
"] at bit " <<
bit;
66 enum { SET_BIT, CLEAR_BIT, SET_VALUE, NOT_SPECIFIED } howset = NOT_SPECIFIED;
71 }
else if (s[at]==
'+') {
74 }
else if (s[at]==
'=') {
79 throw Exception(
"heuristic name must follow qualifier");
82 size_t comma = s.find(
",", at);
83 std::string word = std::string(s, at, comma-at);
85 throw Exception(
"heuristic name must follow comma");
88 if (word ==
"following") {
90 }
else if (word ==
"immediate") {
92 }
else if (word ==
"words") {
94 }
else if (word ==
"allbytes") {
96 }
else if (word ==
"unused") {
98 }
else if (word ==
"nonexe") {
100 }
else if (word ==
"deadend") {
102 }
else if (word ==
"unknown") {
104 }
else if (word ==
"funcsyms") {
106 }
else if (word ==
"default") {
108 if (howset==NOT_SPECIFIED) howset = SET_VALUE;
109 }
else if (isdigit(word[0])) {
110 bits = strtol(word.c_str(), NULL, 0);
112 throw Exception(
"unknown disassembler heuristic: " + word);
127 at = comma==std::string::npos ? s.size() : comma+1;
152 ROSE_ASSERT(factory!=NULL);
163 for (
size_t i=0; i<headers.size(); i++) {
165 if (retval && retval!=candidate)
166 throw Exception(
"interpretation has multiple disassemblers");
188 throw Exception(
"no disassembler for architecture");
213 assert(disassembler);
214 disassembler = disassembler->
clone();
215 assert(disassembler);
219 SgNode *file = SageInterface::getEnclosingNode<SgFile>(interp);
254 for (
size_t i=0; i<8*
sizeof(n); i++)
255 nbits += (((
size_t)1<<i) & n) ? 1 : 0;
256 ROSE_ASSERT(1==nbits);
283 time_t now =
time(NULL);
295 vfprintf(debug, fmt, ap);
308 progress(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: disassembled %zu instructions\n",
333 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: disassembling basic block\n", start_va);
344 insn = cache ? cache->get_value_or(va, NULL) : NULL;
350 cache->insert(std::make_pair(va, insn));
356 cache->insert(std::make_pair(va, insn));
362 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: "
363 "disassembly failed in basic block 0x%08"PRIx64
": %s\n",
364 e.
ip, start_va, e.what());
366 for (InstructionMap::iterator ii=insns.begin(); ii!=insns.end(); ++ii)
379 insns.insert(std::make_pair(va, insn));
385 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: \"%s\" at 0x%08"PRIx64
" naively terminates block\n",
386 start_va, unparseMnemonic(insn).c_str(), va);
395 if (insn && complete && suc.size()==1 && *(suc.begin())==next_va) {
398 "Disassembler[va 0x%08"PRIx64
"]: semantic analysis proves basic block continues after 0x%08"PRIx64
"\n",
406 if (!insn && successors) {
407 successors->insert(suc.begin(), suc.end());
409 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: basic block successors:", start_va);
410 for (AddressSet::iterator si=suc.begin(); si!=suc.end(); si++)
411 fprintf(
p_debug,
" 0x%08"PRIx64, *si);
436 worklist.insert(start_va);
451 ~InstructionCache() {
452 for (
iterator ii=begin(); ii!=end(); ++ii)
467 if (worklist.size()>0)
468 next_search = *(--worklist.end())+1;
471 while (worklist.size()>0) {
473 AddressSet::iterator i = worklist.begin();
477 if (insns.find(va)!=insns.end() || (bad && bad->find(va)!=bad->end())) {
479 }
else if (!map->
exists(va)) {
482 successors->insert(va);
493 insns.insert(bb.begin(), bb.end());
494 assert(icache.exists(va));
497 bad->insert(std::make_pair(va, e));
511 if (worklist.size()>0)
512 next_search = *(--worklist.end())+1;
527 following_va = bb_va+1;
529 InstructionMap::const_iterator bbi = bb.end();
535 if (map->
exists(following_va) && !tried.exists(following_va)) {
536 if (
p_debug && worklist->find(following_va)==worklist->end()) {
538 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: SEARCH_FOLLOWING added 0x%08"PRIx64
"\n", va, following_va);
540 worklist->insert(following_va);
548 for (InstructionMap::const_iterator bbi=bb.begin(); bbi!=bb.end(); bbi++) {
549 const std::vector<SgAsmExpression*> &operands = bbi->second->get_operandList()->get_operands();
550 for (
size_t i=0; i<operands.size(); i++) {
553 size_t nbits = ival->get_significant_bits();
554 if (nbits!=16 && nbits!=32 && nbits!=64)
556 constant = ival->get_value();
558 if (map->
exists(constant) && !tried.exists(constant)) {
559 if (
p_debug && worklist->find(constant)==worklist->end())
560 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: SEARCH_IMMEDIATE added 0x%08"PRIx64
"\n",
561 bbi->first, constant);
562 worklist->insert(constant);
585 unsigned char buf[
sizeof constant];
593 constant |= buf[i] << (8*i);
599 ROSE_ASSERT(!
"not implemented");
602 if (map->
exists(constant) && !tried.exists(constant)) {
603 if (d->
get_debug() && worklist->find(constant)==worklist->end())
604 fprintf(d->
get_debug(),
"Disassembler[va 0x%08"PRIx64
"]: SEARCH_WORD added 0x%08"PRIx64
"\n", va, constant);
605 worklist->insert(constant);
611 } visitor(
this, worklist, tried);
634 assert(range.
last()>=next_va);
637 next_va = range.
last() + 1;
644 if (tried.exists(next_va)) {
656 }
else if (insns.find(next_va)!=insns.end()) {
663 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: SEARCH_%s added 0x%08"PRIx64
"\n",
664 start_va, avoid_overlap?
"UNUSED":
"ALLBYTES", next_va);
666 worklist->insert(next_va);
676 : worklist(wl), map(map),
p_debug(f) {}
677 void visit(
SgNode *node) {
685 fprintf(
p_debug,
"Disassembler: SEARCH_FUNCSYMS added 0x%08"PRIx64
" for \"%s\"\n",
687 worklist->insert(va);
702 const size_t max_insns_size = 16;
703 InstructionMap::const_iterator ii=insns.upper_bound(va);
704 if (ii==insns.begin())
708 ROSE_ASSERT(ii->first <= va);
709 if (ii->first + max_insns_size < va)
711 if (ii->first + ii->second->get_size() > va)
713 if (ii==insns.begin())
736 ROSE_ASSERT(file!=NULL);
737 const void *file_buf = &(file->
get_data()[0]);
761 fprintf(
p_debug,
"Disassembler: no memory map; remapping all sections\n");
764 loader = loader->
clone();
769 loader->
load(interp);
774 fprintf(
p_debug,
"Disassembler: MemoryMap for disassembly:\n");
779 for (
size_t i=0; i<headers.size(); i++) {
780 SgRVAList entry_rvalist = headers[i]->get_entry_rvas();
781 for (
size_t j=0; j<entry_rvalist.size(); j++) {
782 rose_addr_t entry_va = entry_rvalist[j].get_rva() + headers[i]->get_base_va();
783 worklist.insert(entry_va);
785 fprintf(
p_debug,
"Disassembler[va 0x%08"PRIx64
"]: entry point\n", entry_va);
827 unsigned char buf[32];
830 bool was_tracking =
false;
835 for (InstructionMap::const_iterator ii=insns.begin(); ii!=insns.end(); ++ii) {
837 ROSE_ASSERT(insn->
get_size()<=
sizeof buf);
857 for (
size_t i=0; i<files.size(); i++) {
858 if (&(files[i]->get_data()[0]) == si->second.get_buffer()->get_data_ptr()) {
869 size_t sgmt_offset = va - si->first.first();
870 size_t n = std::min(nbytes, (
size_t)si->first.size()-sgmt_offset);
872 size_t file_offset = si->second.get_buffer_offset() + sgmt_offset;
892 std::vector<SgAsmInstruction*> block;
893 for (InstructionMap::const_iterator ii=insns.begin(); ii!=insns.end(); ++ii)
894 block.push_back(ii->second);
903 successors.insert(return_va);