/* * writes a block of memory to the same address space. */ static int inprocess_write(void *ignore, uintptr_t addr, void *buf, size_t size) { DBG_TNF_PROBE_2(inprocess_write_1, "libtnfctl", "sunw%verbosity 3;", tnf_long, num_bytes, size, tnf_opaque, to_address, addr); (void) memcpy((void *)addr, buf, size); return (0); }
/* * removes a breakpoint at the specified location in * the target process, and replaces it with the original instruction. */ prb_status_t unbpt(prb_proc_ctl_t *proc_p, uintptr_t addr) { prb_status_t prbstat; if (proc_p->bpt_inserted) { DBG_TNF_PROBE_2(unbpt_1, "libtnfctl", "sunw%verbosity 2", tnf_opaque, unplanting_at, addr, tnf_opaque, saved_instr, (unsigned)proc_p->saveinstr); prbstat = prb_proc_write(proc_p, addr, &(proc_p->saveinstr), sizeof (proc_p->saveinstr)); if (prbstat) return (prbstat); proc_p->bpt_inserted = B_FALSE; } return (PRB_STATUS_OK); }
/* * _tnfctl_targmem_alloc() - allocates memory in the target process. */ tnfctl_errcode_t _tnfctl_targmem_alloc(tnfctl_handle_t *hndl, size_t size, uintptr_t *addr_p) { int miscstat; tnf_memseg_t memseg; assert(hndl->memseg_p != NULL); *addr_p = NULL; /* read the memseg block from the target process */ miscstat = hndl->p_read(hndl->proc_p, hndl->memseg_p, &memseg, sizeof (memseg)); if (miscstat) return (TNFCTL_ERR_INTERNAL); /* if there is memory left, allocate it */ if ((memseg.min_p + memseg.i_reqsz) <= (memseg.max_p - size)) { memseg.max_p -= size; miscstat = hndl->p_write(hndl->proc_p, hndl->memseg_p, &memseg, sizeof (memseg)); if (miscstat) return (TNFCTL_ERR_INTERNAL); *addr_p = (uintptr_t) memseg.max_p; DBG_TNF_PROBE_2(_tnfctl_targmem_alloc_1, "libtnfctl", "sunw%verbosity 3", tnf_long, size_allocated, size, tnf_opaque, at_location, *addr_p); return (TNFCTL_ERR_NONE); } else { return (TNFCTL_ERR_INTERNAL); } }
/* * _tnfctl_elf_dbgent() - this function finds the address of the * debug struct (DT_DEBUG) in the target process. _DYNAMIC is a symbol * present in every object. The one in the main executable references * an array that is tagged with the kind of each member. We search * for the tag of DT_DEBUG which is where the run time linker maintains * a structure that references the shared object linked list. * * A side effect of searching for DT_DEBUG ensures that the executable is * a dynamic executable - tracing only works on dynamic executables because * static executables don't have relocation tables. */ tnfctl_errcode_t _tnfctl_elf_dbgent(tnfctl_handle_t *hndl, uintptr_t * entaddr_p) { tnfctl_errcode_t prexstat = TNFCTL_ERR_NONE; prb_status_t prbstat = PRB_STATUS_OK; int miscstat; int objfd; int num_dynentries = 0; uintptr_t dynamic_addr; uintptr_t baseaddr; uintptr_t dentry_addr; Elf3264_Dyn *dynam_tab = NULL; long dynam_tab_size; *entaddr_p = NULL; prbstat = prb_mainobj_get(hndl->proc_p, &objfd, &baseaddr); if (prbstat) return (_tnfctl_map_to_errcode(prbstat)); /* find the address of the symbol _DYNAMIC */ prexstat = _tnfctl_sym_find_in_obj(objfd, baseaddr, "_DYNAMIC", &dynamic_addr); if (prexstat) { prexstat = TNFCTL_ERR_NOTDYNAMIC; goto Cleanup; } /* find the number of entries in the .dynamic section */ prexstat = dynsec_num(hndl, baseaddr, objfd, &num_dynentries); if (prexstat) goto Cleanup; DBG_TNF_PROBE_2(_tnfctl_elf_dbgent_1, "libtnfctl", "sunw%verbosity 2", tnf_long, num_of_dynentries, num_dynentries, tnf_opaque, DYNAMIC_address, dynamic_addr); /* read in the dynamic table from the image of the process */ dynam_tab_size = num_dynentries * sizeof (Elf3264_Dyn); dynam_tab = malloc(dynam_tab_size); if (!dynam_tab) { close(objfd); return (TNFCTL_ERR_ALLOCFAIL); } miscstat = hndl->p_read(hndl->proc_p, dynamic_addr, dynam_tab, dynam_tab_size); if (miscstat) { prexstat = TNFCTL_ERR_INTERNAL; goto Cleanup; } prexstat = dyn_findtag(dynam_tab, DT_DEBUG, dynamic_addr, num_dynentries, &dentry_addr); if (prexstat) { goto Cleanup; } *entaddr_p = dentry_addr; Cleanup: close(objfd); if (dynam_tab) free(dynam_tab); return (prexstat); }