From 2b460e0e077a1500c8adedb5630807dca020aa94 Mon Sep 17 00:00:00 2001 From: Jason Hiser <jdhiser@gmail.com> Date: Mon, 6 May 2019 14:32:32 -0400 Subject: [PATCH] arm32 basically working --- irdb-libs/ir_builders/fill_in_cfg.cpp | 35 +- irdb-libs/ir_builders/fill_in_indtargs.cpp | 344 ++++++++++++++++-- irdb-libs/ir_builders/fix_calls.cpp | 140 +++---- .../libIRDB-core/src/operand_csarm32.cpp | 5 +- 4 files changed, 405 insertions(+), 119 deletions(-) diff --git a/irdb-libs/ir_builders/fill_in_cfg.cpp b/irdb-libs/ir_builders/fill_in_cfg.cpp index 122be1ed6..abf8207a2 100644 --- a/irdb-libs/ir_builders/fill_in_cfg.cpp +++ b/irdb-libs/ir_builders/fill_in_cfg.cpp @@ -507,23 +507,35 @@ void PopulateCFG::detect_scoops_in_code(FileIR_t *firp) for(auto insn : firp->getInstructions()) { // look for ldr's with a pcrel operand - const auto d=DecodedInstruction_t::factory(insn); - if(d->getMnemonic()!="ldr") continue; // only valid on arm. - const auto op0=d->getOperand(0); - const auto op1=d->getOperand(1); - if( !op1->isPcrel()) continue; + const auto d = DecodedInstruction_t::factory(insn); + const auto mnemonic = d->getMnemonic(); + if(mnemonic.substr(0,3) != "ldr") continue; // only valid on arm. + const auto op0 = d->getOperand(0); + + // capstone reports ldrd instructions as having 2 "dest" operands. + // so we skip to the 3rd operand to get the memory op. + // todo: fix libirdb-core to fix this and skip the odd operand. + // todo: report to capstone that they are broken. + const auto mem_op = mnemonic[3]=='d' ? d->getOperand(2) : d->getOperand(1); + if( !mem_op->isPcrel()) continue; // sanity check that it's a memory operation, and extract fields - assert(op1->isMemory()); - const auto referenced_address = op1->getMemoryDisplacement() + (is_arm32 ? insn->getAddress()->getVirtualOffset() + 8 : 0); + assert(mem_op->isMemory()); + const auto referenced_address = mem_op->getMemoryDisplacement() + (is_arm32 ? insn->getAddress()->getVirtualOffset() + 8 : 0); const auto op0_str = op0->getString(); + + // if op0 is the PC, the instruction is some switch dispatch that we have to detect in more depth. skip here. see check_arm32_switch... + if(is_arm32 && op0_str == "pc" ) continue; + const auto referenced_size = // could use API call? - is_arm64 && op0_str[0]=='w' ? 4 : + is_arm64 && op0_str[0]=='w' ? 4 : // arm64 regs is_arm64 && op0_str[0]=='x' ? 8 : is_arm64 && op0_str[0]=='s' ? 4 : is_arm64 && op0_str[0]=='d' ? 8 : is_arm64 && op0_str[0]=='q' ? 16 : - is_arm32 && op0_str[0]=='r' ? 4 : + is_arm32 && op0_str[0]=='r' ? 4 : // arm32 regs + is_arm32 && op0_str =="sb"? 4 : // special arm32 regs + is_arm32 && op0_str =="sl"? 4 : is_arm32 && op0_str =="lr"? 4 : is_arm32 && op0_str =="fp"? 4 : is_arm32 && op0_str =="sp"? 4 : @@ -559,8 +571,9 @@ void PopulateCFG::detect_scoops_in_code(FileIR_t *firp) auto newscoop=firp->addNewDataScoop(name, start_addr, end_addr, NULL, permissions, is_relro, the_contents); (void)newscoop; - cout<< "Allocated data in text segment "<<name<<"=("<<start_addr->getVirtualOffset()<<"-" - << end_addr->getVirtualOffset()<<")"<<endl; + cout << "Allocated data in text segment " << name << "=(" << start_addr->getVirtualOffset() << "-" + << end_addr->getVirtualOffset() << ")" + << " for " << d->getDisassembly() << "@" << hex << insn->getAddress()->getVirtualOffset() << endl; } } diff --git a/irdb-libs/ir_builders/fill_in_indtargs.cpp b/irdb-libs/ir_builders/fill_in_indtargs.cpp index 7a0b80cff..25c6ca713 100644 --- a/irdb-libs/ir_builders/fill_in_indtargs.cpp +++ b/irdb-libs/ir_builders/fill_in_indtargs.cpp @@ -260,16 +260,15 @@ void mark_targets(FileIR_t *firp) if(getenv("IB_VERBOSE")!=nullptr) cout<<"Skipping pin for text to printf at "<<hex<<addr<<endl; } + else if(firp->findScoop(addr)) + { + if(getenv("IB_VERBOSE")!=nullptr) + cout<<"Skipping pin data_in_text "<<hex<<addr<<endl; + } else { if(getenv("IB_VERBOSE")!=nullptr) cout<<"Setting pin at "<<hex<<addr<<endl; - /* - AddressID_t* newaddr = new AddressID_t; - newaddr->SetFileID(insn->getAddress()->getFileID()); - newaddr->setVirtualOffset(insn->getAddress()->getVirtualOffset()); - firp->getAddresses().insert(newaddr); - */ auto newaddr=firp->addNewAddress(insn->getAddress()->getFileID(), insn->getAddress()->getVirtualOffset()); insn->setIndirectBranchTargetAddress(newaddr); } @@ -355,6 +354,8 @@ void get_instruction_targets(FileIR_t *firp, EXEIO::exeio* exeiop, const set<Vir else if(mt==admtArm32) { check_for_arm32_switch_type1(firp,insn, *disasm, exeiop); + check_for_arm32_switch_type2(firp,insn, *disasm, exeiop); + check_for_arm32_switch_type3(firp,insn, *disasm, exeiop); } else throw invalid_argument("Cannot determine machine type"); @@ -412,18 +413,20 @@ void get_executable_bounds(FileIR_t *firp, const section* shdr) void infer_targets(FileIR_t *firp, section* shdr) { -// int flags = shdr->get_flags(); - - if( ! shdr->isLoadable()) // (flags & SHF_ALLOC) != SHF_ALLOC) - /* not a loaded section */ + /* check for a not loaded section */ + if( ! shdr->isLoadable()) return; - if( shdr->isExecutable() ) //(flags & SHF_EXECINSTR) == SHF_EXECINSTR) - /* loaded, but contains instruction. we'll look through the VariantIR for this section. */ + /* check for a loaded, but contains instruction section. + * we'll look through the VariantIR for this section. */ + if( shdr->isExecutable() ) return; /* if the type is NOBITS, then there's no actual data to look through */ - if(shdr->isBSS() ) // get_type()==SHT_NOBITS) + if(shdr->isBSS() ) + return; + // skip .dynsym section -- process-dynsym does this. + if(shdr->get_name()==".dynsym") return; @@ -432,7 +435,8 @@ void infer_targets(FileIR_t *firp, section* shdr) const char* data=shdr->get_data() ; // C(char*)malloc(shdr->sh_size); assert(arch_ptr_bytes()==4 || arch_ptr_bytes()==8); - for(auto i=0u;i+arch_ptr_bytes()<=(size_t)shdr->get_size();i++) + // assume pointers need to be at least 4-byte aligned. + for(auto i=0u;i+arch_ptr_bytes()<=(size_t)shdr->get_size();i+=4) { // even on 64-bit, pointers might be stored as 32-bit, as a // elf object has the 32-bit limitations. @@ -445,7 +449,7 @@ void infer_targets(FileIR_t *firp, section* shdr) - ibt_provenance_t prov; + auto prov = ibt_provenance_t(); if(shdr->get_name()==".init_array") prov=ibt_provenance_t::ibtp_initarray; else if(shdr->get_name()==".fini_array") @@ -454,8 +458,6 @@ void infer_targets(FileIR_t *firp, section* shdr) prov=ibt_provenance_t::ibtp_gotplt; else if(shdr->get_name()==".got") prov=ibt_provenance_t::ibtp_got; - else if(shdr->get_name()==".dynsym") - prov=ibt_provenance_t::ibtp_dynsym; else if(shdr->get_name()==".symtab") prov=ibt_provenance_t::ibtp_symtab; else if(shdr->isWriteable()) @@ -650,20 +652,265 @@ bool backup_until(const string &insn_type_regex_str, void check_for_arm32_switch_type1( FileIR_t *firp, - Instruction_t* i10, + Instruction_t* insn, const DecodedInstruction_t &d10, EXEIO::exeio* exeiop) { + const auto prov=ibt_provenance_t::ibtp_switchtable_type1; + + /* + * Check for hand-written assembly for divsi and udivsi that has this dispatch insn: addeq pc, pc, <reg> lsl #2 + */ + const auto d = DecodedInstruction_t::factory(insn); + const auto is_addne = d->getMnemonic() == "addne" ; + if(is_addne) + { + const auto is_op0_pc = d->getOperand(0)->getString()=="pc"; + const auto is_op1_pc = d->getOperand(1)->getString()=="pc"; + if(is_op0_pc && is_op1_pc) + { + cout << "Found gcc addne pc,pc idiom" << endl; + for(auto i=1u;i<32u;i++) + { + const auto ibta = insn->getAddress()->getVirtualOffset() + 8 + i*12; + possible_target(ibta,0,prov); + } + } + } return; } +void check_for_arm32_switch_type2( + FileIR_t *firp, + Instruction_t* i10, + const DecodedInstruction_t &d10, + EXEIO::exeio* exeiop) +{ +#if 0 + +Looking for this pattern: + +I9: cmp r2, #4 +I10: ldrls pc, [pc, r2, lsl #2] + +or this: + +I8: ldr r3, [pc, #k] +I9: cmp r2, r3 +I10: ldrls pc, [pc, r2, lsl #2] + +#endif + + const auto prov=ibt_provenance_t::ibtp_switchtable_type2; + + // check that i10 is what we need + const auto i10_dis = d10.getDisassembly(); + const auto is_i10_ldrls = i10_dis.find("ldrls pc, [pc")==0; + if(!is_i10_ldrls) return; + + // this is sufficient to determine we have a switch dispatch. + // now try to figure out the table size. + auto jt_size = numeric_limits<uint32_t>::max(); + + // and we do that by looking for a cmp on the dispatch register. + // the dispatch register is the index register in the ldrls instruction. + // which we find via string extraction. + const auto i10_dis_15_3 = i10_dis.substr(15,3); // reg or reg, + const auto i10_index_reg = i10_dis_15_3[2] == ',' ? i10_dis_15_3.substr(0,2) : i10_dis_15_3; + + // look for i9 + auto i9=(Instruction_t*)nullptr; + if(!backup_until( string()+"cmp "+i10_index_reg+",", /* look for this pattern. */ + i9, /* find i9 */ + i10, /* before I10 */ + "^"+i10_index_reg+"$" /* stop if i10_reg set */ + )) + { + return; + } + + + if(i9 != nullptr) + { + // decode i9 + const auto d9 = DecodedInstruction_t::factory(i9); + const auto d9_op1 = d9->getOperand(1); + + // look for a constant in the 2nd operand. + if( d9_op1->isConstant()) + jt_size=d9_op1->getConstant(); + else + { + // check if it's a register + // and look backwards for a load of the register from the .text seg + // TBD + } + } + + // extract the jump table -- this is simple as the addresing mode in i10 says it's at is "pc+8". + const auto jt_addr = i10->getAddress()->getVirtualOffset() + 8u; + const auto jt_section = find_section(jt_addr,exeiop); + assert(jt_section); + const auto jt_secdata = jt_section->get_data(); + const auto jt_secaddr = jt_section->get_address(); + const auto jt_secendaddr = jt_secaddr + jt_section->get_size(); + + auto jt_entry_no=0u; + while(true) + { + // calculate some stuff about the jump table entry we're looking at + const auto jte_size = 4u; + const auto jte_offset = jt_entry_no * jte_size; + const auto jte_addr = jt_addr + jte_offset; + + // stop if we've exceeded the section size + if(jte_addr + jte_size > jt_secendaddr) break; + + // extract the table entry + const auto jte = * reinterpret_cast<const uint32_t*>(&jt_secdata[jte_addr - jt_secaddr]); + + // mark the instruction at jte as an ibt + possible_target(jte, jte_addr, prov); + + // check to see if the entry is valid. if not, exit. + const auto ibtarget = lookupInstruction(firp, jte); + if(ibtarget == nullptr) break; + + cout << "Found ARM32 switch (ldrls -- type2)@0x" << hex << i10->getAddress()->getVirtualOffset() + << " table_entry[" << dec << jt_entry_no << "]=" << hex << jte << "@0x " << jte_addr + << " to " << ibtarget->getBaseID() << ":" << ibtarget->getDisassembly() + << "@" << ibtarget->getAddress()->getVirtualOffset() << endl; + + // add to i10 + jmptables[i10].insert(ibtarget); + + // stop if we've exceeded the number of table entries we found. + if(jt_entry_no+1 > jt_size) break; + + jt_entry_no++; + + } + + // add a data scoop for the switch table. + cout << "Detected " << dec << jt_entry_no << "entries in this table. adding data scoop for table" << endl; + addSwitchTableScoop(firp, jt_entry_no + 1 , 4, jt_addr, exeiop, nullptr, 0, false); + + // mark that we figured out all possible targets for this ib. + jmptables[i10].setAnalysisStatus(iasAnalysisComplete); +} + +void check_for_arm32_switch_type3( + FileIR_t *firp, + Instruction_t* i10, + const DecodedInstruction_t &d10, + EXEIO::exeio* exeiop) +{ +#if 0 + +Looking for this pattern: + +I9: cmp r2, #4 +I10: addls pc, [pc, r2, lsl #2] + +or this: + +I8: ldr r3, [pc, #k] +I9: cmp r2, r3 +I10: addls pc, [pc, r2, lsl #2] + +#endif + + const auto prov=ibt_provenance_t::ibtp_switchtable_type3; + + // check that i10 is what we need + const auto i10_dis = d10.getDisassembly(); + const auto is_i10_ldrls = i10_dis.find("addls pc, pc")==0; + if(!is_i10_ldrls) return; + + // this is sufficient to determine we have a switch dispatch. + // now try to figure out the table size. + auto jt_size = numeric_limits<uint32_t>::max(); + + // and we do that by looking for a cmp on the dispatch register. + // the dispatch register is the index register in the ldrls instruction. + // which we find via string extraction. + const auto i10_index_reg = d10.getOperand(2)->getString(); + + // look for i9 + auto i9=(Instruction_t*)nullptr; + if(!backup_until( string()+"cmp "+i10_index_reg+",", /* look for this pattern. */ + i9, /* find i9 */ + i10, /* before I10 */ + "^"+i10_index_reg+"$" /* stop if i10_reg set */ + )) + { + return; + } + + + if(i9 != nullptr) + { + // decode i9 + const auto d9 = DecodedInstruction_t::factory(i9); + const auto d9_op1 = d9->getOperand(1); + + // look for a constant in the 2nd operand. + if( d9_op1->isConstant()) + jt_size=d9_op1->getConstant(); + else + { + // check if it's a register + // and look backwards for a load of the register from the .text seg + // TBD + } + } + + // extract the jump table -- this is simple as the addresing mode in i10 says it's at is "pc+8". + const auto jt_addr = i10->getAddress()->getVirtualOffset() + 8u; + const auto jt_entry_size = 4u; + + auto jt_entry_no=0u; + while(true) + { + // check to see if the entry is valid. if not, exit. + const auto jte = jt_addr + jt_entry_no * jt_entry_size; + const auto ibtarget = lookupInstruction(firp, jte); + if(ibtarget == nullptr) break; + + // check if it's an uncond branch + const auto ibt_dis = DecodedInstruction_t::factory(ibtarget); + if(ibt_dis->getMnemonic() != "b") break; + + // mark the instruction at jte as an ibt + possible_target(jte, 0, prov); + + cout << "Found ARM32 switch (addls -- type2)@0x" << hex << i10->getAddress()->getVirtualOffset() + << " to " << ibtarget->getBaseID() << ":" << ibtarget->getDisassembly() + << "@" << ibtarget->getAddress()->getVirtualOffset() << endl; + + // add to i10 + jmptables[i10].insert(ibtarget); + + // stop if we've exceeded the number of table entries we found. + if(jt_entry_no+1 > jt_size) break; + + jt_entry_no++; + + } + + // add a data scoop for the switch table. + cout << "Detected " << dec << jt_entry_no << "entries in this table. adding data scoop for table" << endl; + + // mark that we figured out all possible targets for this ib. + jmptables[i10].setAnalysisStatus(iasAnalysisComplete); +} void check_for_arm64_switch_type1( FileIR_t *firp, Instruction_t* i10, const DecodedInstruction_t &d10, EXEIO::exeio* exeiop) { - ibt_provenance_t prov=ibt_provenance_t::ibtp_switchtable_type1; + const auto prov=ibt_provenance_t::ibtp_switchtable_type1; #if 0 Sample code for this branch type: @@ -2184,7 +2431,8 @@ void addSwitchTableScoop( const VirtualOffset_t table_base_addr, EXEIO::exeio* exeiop, Instruction_t* I6, - const VirtualOffset_t I5_constant + const VirtualOffset_t I5_constant, + const bool do_unpin=true ) { // make sure we can find the section with the switch table @@ -2195,8 +2443,8 @@ void addSwitchTableScoop( if(sec == nullptr) return; if(!sec->isExecutable()) return; - const auto start_vo = 0u; // start and end offsets in this file - const auto end_vo = start_vo+num_entries*entry_size; + const auto start_vo = do_unpin ? 0u : table_base_addr; // start and end offsets in this file + const auto end_vo = start_vo + num_entries * entry_size -1; auto startaddr = firp->addNewAddress(firp->getFile()->getBaseID(), start_vo); // start and end address auto endaddr = firp->addNewAddress(firp->getFile()->getBaseID(), end_vo); assert(sec); @@ -2213,20 +2461,46 @@ void addSwitchTableScoop( // finally, create the new scoop const auto switch_tab = firp->addNewDataScoop( name, startaddr, endaddr, NULL, permissions, is_relro, the_contents, max_base_id++ ); - // and add a relocation so we can later repin the scoop - firp->addNewRelocation(I6, 0, "absoluteptr_to_scoop", switch_tab); - - // now rewrite the - const auto d6 = DecodedInstruction_t::factory(I6); - const auto operands = d6->getOperands(); - const auto the_arg = find_if(ALLOF(operands), [](const shared_ptr<DecodedOperand_t>& arg) { return arg->isMemory(); }); - const auto disp_offset = uint32_t(d6->getMemoryDisplacementOffset(the_arg->get(),I6)); - const auto disp_size = uint32_t((*the_arg)->getMemoryDisplacementEncodingSize()); - const auto file_base = firp->getArchitecture()->getFileBase(); - const auto new_disp = uint32_t(I5_constant-file_base); - const auto new_bits = I6->getDataBits().replace(disp_offset, disp_size, (const char*)&new_disp, disp_size); - I6->setDataBits(new_bits); + const auto mt=firp->getArchitecture()->getMachineType(); + if(do_unpin) + { + if(mt==admtX86_64 || mt==admtI386) + { + // on x86 we need to rewrite the table base instruction. + + // and add a relocation so we can later repin the scoop + firp->addNewRelocation(I6, 0, "absoluteptr_to_scoop", switch_tab); + + // now rewrite the + const auto d6 = DecodedInstruction_t::factory(I6); + const auto operands = d6->getOperands(); + const auto the_arg = find_if(ALLOF(operands), [](const shared_ptr<DecodedOperand_t>& arg) { return arg->isMemory(); }); + const auto disp_offset = uint32_t(d6->getMemoryDisplacementOffset(the_arg->get(),I6)); + const auto disp_size = uint32_t((*the_arg)->getMemoryDisplacementEncodingSize()); + const auto file_base = firp->getArchitecture()->getFileBase(); + const auto new_disp = uint32_t(I5_constant-file_base); + const auto new_bits = I6->getDataBits().replace(disp_offset, disp_size, (const char*)&new_disp, disp_size); + I6->setDataBits(new_bits); + } + else if(mt==admtArm32 || mt==admtAarch64) + { + // on ARM we need need to update the pc-rel relocation to indicate which scoop is the table. + for(auto &reloc : I6->getRelocations()) + { + if(reloc->getType()=="pcrel") + { + assert(reloc->getWRT() == nullptr); + reloc->setWRT(switch_tab); + } + } + } + else + { + // unknown arch. + assert(0); + } + } } diff --git a/irdb-libs/ir_builders/fix_calls.cpp b/irdb-libs/ir_builders/fix_calls.cpp index d871e1b48..10fa9bdc0 100644 --- a/irdb-libs/ir_builders/fix_calls.cpp +++ b/irdb-libs/ir_builders/fix_calls.cpp @@ -777,93 +777,95 @@ class FixCalls_t : public TransformStep_t // void fix_other_pcrel(FileIR_t* firp, Instruction_t *insn, uintptr_t virt_offset) { - const auto disasm = DecodedInstruction_t::factory(insn); - const auto &operands = disasm->getOperands(); - const auto relop_it = find_if(ALLOF(operands),[](const shared_ptr<DecodedOperand_t>& op) { return op->isPcrel() ; } ); - const auto is_rel = relop_it!=operands.end(); - const auto is_read = is_rel ? (*relop_it)->isRead() : false; - /* if this has already been fixed, we can skip it */ if(virt_offset == 0 || virt_offset == (uintptr_t)-1) return; - if(is_rel && is_read) + const auto disasm = DecodedInstruction_t::factory(insn); + const auto &operands = disasm->getOperands(); + for(const auto &op : operands) { - const auto &the_arg = *(relop_it->get()); - const auto mt = firp->getArchitecture()->getMachineType(); - if(mt==admtAarch64 || mt==admtArm32) - { - // figure out how to rewrite pcrel arm insns, then change the virt addr - // insn->getAddress()->setVirtualOffset(0); - // for now, we aren't doing this... we may need to for doing xforms. - if(getenv("VERBOSE_FIX_CALLS")) - cout << "Detected arm32/64 pc-rel operand in " << disasm->getDisassembly() << endl; - } - else if(mt==admtX86_64 || mt==admtI386) - { - assert(the_arg.isMemory()); - auto offset=disasm->getMemoryDisplacementOffset(&the_arg, insn); - assert(offset>=0 && offset <=15); - auto size=the_arg.getMemoryDisplacementEncodingSize(); - assert(size==1 || size==2 || size==4 || size==8); + const auto &the_arg = *op; + const auto is_rel = the_arg.isPcrel(); + const auto is_read = the_arg.isRead(); - if(getenv("VERBOSE_FIX_CALLS")) + if(is_rel && is_read) + { + const auto mt = firp->getArchitecture()->getMachineType(); + if(mt==admtAarch64 || mt==admtArm32) { - cout<<"Found insn with pcrel memory operand: "<<disasm->getDisassembly() - <<" Displacement="<<hex<<the_arg.getMemoryDisplacement() << dec - <<" size="<<the_arg.getMemoryDisplacementEncodingSize() <<" Offset="<<offset; + // figure out how to rewrite pcrel arm insns, then change the virt addr + // insn->getAddress()->setVirtualOffset(0); + // for now, we aren't doing this... we may need to for doing xforms. + if(getenv("VERBOSE_FIX_CALLS")) + cout << "Detected arm32/64 pc-rel operand in " << disasm->getDisassembly() << endl; } + else if(mt==admtX86_64 || mt==admtI386) + { + assert(the_arg.isMemory()); + auto offset=disasm->getMemoryDisplacementOffset(&the_arg, insn); + assert(offset>=0 && offset <=15); + auto size=the_arg.getMemoryDisplacementEncodingSize(); + assert(size==1 || size==2 || size==4 || size==8); - /* convert [rip_pc+displacement] addresssing mode into [rip_0+displacement] where rip_pc is the actual PC of the insn, - * and rip_0 is means that the PC=0. AKA, we are relocating this instruction to PC=0. Later we add a relocation to undo this transform at runtime - * when we know the actual address. - */ + if(getenv("VERBOSE_FIX_CALLS")) + { + cout<<"Found insn with pcrel memory operand: "<<disasm->getDisassembly() + <<" Displacement="<<hex<<the_arg.getMemoryDisplacement() << dec + <<" size="<<the_arg.getMemoryDisplacementEncodingSize() <<" Offset="<<offset; + } - /* get the data */ - string data=insn->getDataBits(); - char cstr[20]={}; - memcpy(cstr,data.c_str(), data.length()); - void *offsetptr=&cstr[offset]; + /* convert [rip_pc+displacement] addresssing mode into [rip_0+displacement] where rip_pc is the actual PC of the insn, + * and rip_0 is means that the PC=0. AKA, we are relocating this instruction to PC=0. Later we add a relocation to undo this transform at runtime + * when we know the actual address. + */ - auto disp=the_arg.getMemoryDisplacement(); - auto oldpc=virt_offset; - auto newdisp=disp+oldpc-firp->getArchitecture()->getFileBase(); + /* get the data */ + string data=insn->getDataBits(); + char cstr[20]={}; + memcpy(cstr,data.c_str(), data.length()); + void *offsetptr=&cstr[offset]; - assert((uintptr_t)(offset+size)<=(uintptr_t)(data.length())); - - switch(size) - { - case 4: - assert( (uintptr_t)(int)newdisp == (uintptr_t)newdisp); - *(int*)offsetptr=newdisp; - break; - case 1: - case 2: - case 8: - default: - assert(0); - //assert(("Cannot handle offset of given size", 0)); - } + auto disp=the_arg.getMemoryDisplacement(); + auto oldpc=virt_offset; + auto newdisp=disp+oldpc-firp->getArchitecture()->getFileBase(); - /* put the data back into the insn */ - data.replace(0, data.length(), cstr, data.length()); - insn->setDataBits(data); + assert((uintptr_t)(offset+size)<=(uintptr_t)(data.length())); + + switch(size) + { + case 4: + assert( (uintptr_t)(int)newdisp == (uintptr_t)newdisp); + *(int*)offsetptr=newdisp; + break; + case 1: + case 2: + case 8: + default: + assert(0); + //assert(("Cannot handle offset of given size", 0)); + } - other_fixes++; + /* put the data back into the insn */ + data.replace(0, data.length(), cstr, data.length()); + insn->setDataBits(data); - if(getenv("VERBOSE_FIX_CALLS")) - cout << " Converted to: " << insn->getDisassembly() << endl; + other_fixes++; - // and it's important to set the VO to 0, so that the pcrel-ness is calculated correctly. - insn->getAddress()->setVirtualOffset(0); - } - else - throw std::invalid_argument("Unknown architecture in fix_other_pcrel"); + if(getenv("VERBOSE_FIX_CALLS")) + cout << " Converted to: " << insn->getDisassembly() << endl; - // now that we've done the rewriting, go ahead and add the reloc. - auto reloc=firp->addNewRelocation(insn,0,"pcrel"); - (void)reloc; // not used, only given to the IR + // and it's important to set the VO to 0, so that the pcrel-ness is calculated correctly. + insn->getAddress()->setVirtualOffset(0); + } + else + throw std::invalid_argument("Unknown architecture in fix_other_pcrel"); + + // now that we've done the rewriting, go ahead and add the reloc. + auto reloc=firp->addNewRelocation(insn,0,"pcrel"); + (void)reloc; // not used, only given to the IR + } } } diff --git a/irdb-libs/libIRDB-core/src/operand_csarm32.cpp b/irdb-libs/libIRDB-core/src/operand_csarm32.cpp index 060e653a0..f7a61337d 100644 --- a/irdb-libs/libIRDB-core/src/operand_csarm32.cpp +++ b/irdb-libs/libIRDB-core/src/operand_csarm32.cpp @@ -51,7 +51,6 @@ string DecodedOperandCapstoneARM32_t::getString() const return string(cs_reg_name(handle, op.reg)); case ARM_OP_IMM: return to_string(op.imm); -#if 0 case ARM_OP_MEM: { string ret_val; @@ -64,12 +63,10 @@ string DecodedOperandCapstoneARM32_t::getString() const if (op.mem.disp != 0) ret_val+=" + "+ to_string(op.mem.disp); - if(ret_val=="") - return "0"; + ret_val += " lsl/ror? ?? "; return ret_val; } -#endif default: assert(0); } -- GitLab