|  | /* system/debuggerd/utility.c | 
|  | ** | 
|  | ** Copyright 2008, The Android Open Source Project | 
|  | ** | 
|  | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | ** you may not use this file except in compliance with the License. | 
|  | ** You may obtain a copy of the License at | 
|  | ** | 
|  | **     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | ** | 
|  | ** Unless required by applicable law or agreed to in writing, software | 
|  | ** distributed under the License is distributed on an "AS IS" BASIS, | 
|  | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | ** See the License for the specific language governing permissions and | 
|  | ** limitations under the License. | 
|  | */ | 
|  |  | 
|  | #include <sys/ptrace.h> | 
|  | #include <sys/exec_elf.h> | 
|  | #include <assert.h> | 
|  | #include <string.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | #include "utility.h" | 
|  |  | 
|  | /* Get a word from pid using ptrace. The result is the return value. */ | 
|  | int get_remote_word(int pid, void *src) | 
|  | { | 
|  | return ptrace(PTRACE_PEEKTEXT, pid, src, NULL); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Handy routine to read aggregated data from pid using ptrace. The read | 
|  | * values are written to the dest locations directly. | 
|  | */ | 
|  | void get_remote_struct(int pid, void *src, void *dst, size_t size) | 
|  | { | 
|  | unsigned int i; | 
|  |  | 
|  | for (i = 0; i+4 <= size; i+=4) { | 
|  | *(int *)(dst+i) = ptrace(PTRACE_PEEKTEXT, pid, src+i, NULL); | 
|  | } | 
|  |  | 
|  | if (i < size) { | 
|  | int val; | 
|  |  | 
|  | assert((size - i) < 4); | 
|  | val = ptrace(PTRACE_PEEKTEXT, pid, src+i, NULL); | 
|  | while (i < size) { | 
|  | ((unsigned char *)dst)[i] = val & 0xff; | 
|  | i++; | 
|  | val >>= 8; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Map a pc address to the name of the containing ELF file */ | 
|  | const char *map_to_name(mapinfo *mi, unsigned pc, const char* def) | 
|  | { | 
|  | while(mi) { | 
|  | if((pc >= mi->start) && (pc < mi->end)){ | 
|  | return mi->name; | 
|  | } | 
|  | mi = mi->next; | 
|  | } | 
|  | return def; | 
|  | } | 
|  |  | 
|  | /* Find the containing map info for the pc */ | 
|  | const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) | 
|  | { | 
|  | while(mi) { | 
|  | if((pc >= mi->start) && (pc < mi->end)){ | 
|  | // Only calculate the relative offset for shared libraries | 
|  | if (strstr(mi->name, ".so")) { | 
|  | *rel_pc = pc - mi->start; | 
|  | } | 
|  | return mi; | 
|  | } | 
|  | mi = mi->next; | 
|  | } | 
|  | return NULL; | 
|  | } |