/* Copy a LC_DYSYMTAB load command from the input file to the output file, adjusting the file offset fields. */ static void copy_dysymtab (struct load_command *lc, long delta) { struct dysymtab_command *dstp = (struct dysymtab_command *) lc; vm_address_t base; #ifdef _LP64 /* First writable segment address. */ base = data_segment_scp->vmaddr; #else /* First segment address in the file (unless MH_SPLIT_SEGS set). */ base = 0; #endif unrelocate ("local", dstp->locreloff, dstp->nlocrel, base); unrelocate ("external", dstp->extreloff, dstp->nextrel, base); if (dstp->nextrel > 0) { dstp->extreloff += delta; } if (dstp->nlocrel > 0) { dstp->locreloff += delta; } if (dstp->nindirectsyms > 0) dstp->indirectsymoff += delta; printf ("Writing LC_DYSYMTAB command\n"); if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) unexec_error ("cannot write symtab command to header"); curr_header_offset += lc->cmdsize; }
bool insertProc(VMAInterval ival, Proc* proc) { VMAInterval ival_ur(unrelocate(ival.beg()), unrelocate(ival.end())); std::pair<ProcMap::iterator, bool> ret = m_procMap.insert(ProcMap::value_type(ival_ur, proc)); return ret.second; }
// returns false if an overlapping segment already exists bool insertSeg(VMAInterval ival, Seg* seg) { VMAInterval ival_ur(unrelocate(ival.beg()), unrelocate(ival.end())); std::pair<SegMap::iterator, bool> ret = m_segMap.insert(SegMap::value_type(ival_ur, seg)); return ret.second; }
// NOTE: does not check for duplicates void insertInsn(VMA vma, ushort opIndex, Insn* insn) { VMA vma_ur = unrelocate(vma); VMA opvma = isa->convertVMAToOpVMA(vma_ur, opIndex); m_insnMap.insert(InsnMap::value_type(opvma, insn)); }
Proc* findProc(VMA vma) const { VMA vma_ur = unrelocate(vma); VMAInterval ival_ur(vma_ur, vma_ur + 1); // size must be > 0 ProcMap::const_iterator it = m_procMap.find(ival_ur); Proc* proc = (it != m_procMap.end()) ? it->second : NULL; return proc; }
Seg* findSeg(VMA vma) const { VMA vma_ur = unrelocate(vma); VMAInterval ival_ur(vma_ur, vma_ur + 1); // size must be > 0 SegMap::const_iterator it = m_segMap.find(ival_ur); Seg* seg = (it != m_segMap.end()) ? it->second : NULL; return seg; }
Insn* findInsnNear(VMA vma, ushort opIndex) const { VMA vma_ur = unrelocate(vma); VMA opvma = isa->convertVMAToOpVMA(vma_ur, opIndex); InsnMap::const_iterator it = m_insnMap.lower_bound(opvma); Insn* insn = (it != m_insnMap.end()) ? it->second : NULL; return insn; }
/* Copy a LC_DYSYMTAB load command from the input file to the output file, adjusting the file offset fields. */ static void copy_dysymtab (struct load_command *lc, long delta) { struct dysymtab_command *dstp = (struct dysymtab_command *) lc; vm_address_t base; #ifdef _LP64 #if __ppc64__ { int i; base = 0; for (i = 0; i < nlc; i++) if (lca[i]->cmd == LC_SEGMENT) { struct segment_command *scp = (struct segment_command *) lca[i]; if (scp->vmaddr + scp->vmsize > 0x100000000 && (scp->initprot & VM_PROT_WRITE) != 0) { base = data_segment_scp->vmaddr; break; } } } #else /* First writable segment address. */ base = data_segment_scp->vmaddr; #endif #else /* First segment address in the file (unless MH_SPLIT_SEGS set). */ base = 0; #endif unrelocate ("local", dstp->locreloff, dstp->nlocrel, base); unrelocate ("external", dstp->extreloff, dstp->nextrel, base); if (dstp->nextrel > 0) { dstp->extreloff += delta; } if (dstp->nlocrel > 0) { dstp->locreloff += delta; } if (dstp->nindirectsyms > 0) dstp->indirectsymoff += delta; printf ("Writing LC_DYSYMTAB command\n"); if (!unexec_write (curr_header_offset, lc, lc->cmdsize)) unexec_error ("cannot write symtab command to header"); curr_header_offset += lc->cmdsize; #if __ppc64__ /* Check if the relocation base needs to be changed. */ if (base == 0) { vm_address_t newbase = 0; int i; for (i = 0; i < num_unexec_regions; i++) if (unexec_regions[i].range.address + unexec_regions[i].range.size > 0x100000000) { newbase = data_segment_scp->vmaddr; break; } if (newbase) { rebase_reloc_address (dstp->locreloff, dstp->nlocrel, delta, newbase); rebase_reloc_address (dstp->extreloff, dstp->nextrel, delta, newbase); } } #endif }