This adds some additional output to native crashes. For example, if something tried to access a bit of mmap(/dev/zero) memory that had been mprotect()ed, you might see output like this: I DEBUG : memory map around addr 4015a00c: I DEBUG : 40159000-4015a000 /system/lib/libstdc++.so I DEBUG : 4015a000-40162000 /dev/zero I DEBUG : b0001000-b0009000 /system/bin/linker The idea is to see what's in and around the fault address to make it easier to identify bus errors due to file truncation and segmentation faults caused by buffer over/underruns. No output is generated for accesses below 0x1000 (which are likely NULL pointer dereferences) or for signals that don't set si_addr. Also, suppress the fault address for signals that don't set si_addr: I DEBUG : signal 6 (SIGABRT), code 0 (?), fault addr -------- We still print "fault addr" followed by 8 characters for anything that is parsing the contents. The "address" shown for signals like SIGABRT was meaningless and possibly confusing. Bug 5358516 Change-Id: Icae8ef309ea2d89b129f68d30f96b2ca8a69cc6c
102 lines
2.6 KiB
C
102 lines
2.6 KiB
C
/* 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 <signal.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 *)((char *)dst+i) = ptrace(PTRACE_PEEKTEXT, pid, (char *)src+i, NULL);
|
|
}
|
|
|
|
if (i < size) {
|
|
int val;
|
|
|
|
assert((size - i) < 4);
|
|
val = ptrace(PTRACE_PEEKTEXT, pid, (char *)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)
|
|
{
|
|
*rel_pc = 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 -= mi->start;
|
|
}
|
|
return mi;
|
|
}
|
|
mi = mi->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Returns true if the specified signal has an associated address (i.e. it
|
|
* sets siginfo_t.si_addr).
|
|
*/
|
|
bool signal_has_address(int sig)
|
|
{
|
|
switch (sig) {
|
|
case SIGILL:
|
|
case SIGFPE:
|
|
case SIGSEGV:
|
|
case SIGBUS:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|