Merge "memcheck: Remove feature entirely"
diff --git a/Makefile.common b/Makefile.common
index 2d8e0b1..2ff49e8 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -686,52 +686,6 @@
##############################################################################
##############################################################################
###
-### emulator-libelff: TARGET-INDEPENDENT ELF/DWARF PARSER
-###
-### THESE ARE USED BY EVERYTHING EXCEPT 'emulator-ui', BUT WE CANNOT PUT
-### THEM IN emulator-libqemu SINCE THE SOURCES ARE C++
-###
-
-common_LOCAL_CFLAGS =
-common_LOCAL_SRC_FILES =
-
-ELFF_CFLAGS := -I$(LOCAL_PATH)/distrib/elff
-ELFF_LDLIBS := -lstdc++
-
-ELFF_SOURCES := \
- dwarf_cu.cc \
- dwarf_die.cc \
- dwarf_utils.cc \
- elf_alloc.cc \
- elf_file.cc \
- elf_mapped_section.cc \
- elff_api.cc \
-
-common_LOCAL_SRC_FILES += $(ELFF_SOURCES:%=distrib/elff/elff/%)
-
-common_LOCAL_CFLAGS += \
- -fno-exceptions \
- $(ELFF_CFLAGS) \
-
-
-## one for 32-bit
-$(call start-emulator-library, emulator-libelff)
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_CFLAGS += $(common_LOCAL_CFLAGS)
-LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
-$(call end-emulator-library)
-
-
-$(call start-emulator64-library, emulator64-libelff)
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_CFLAGS += $(common_LOCAL_CFLAGS)
-LOCAL_SRC_FILES += $(common_LOCAL_SRC_FILES)
-$(call end-emulator-library)
-
-
-##############################################################################
-##############################################################################
-###
### gen-hx-header: Generate headers from .hx file with "hxtool" script.
###
### The 'hxtool' script is used to generate header files from an input
diff --git a/Makefile.target b/Makefile.target
index 0377cdd..e2d2871 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -177,7 +177,6 @@
target-arm/iwmmxt_helper.c \
target-arm/neon_helper.c \
target-arm/helper.c \
- target-arm/helper-android.c \
target-arm/translate.c \
target-arm/machine.c \
hw/arm/armv7m.c \
@@ -233,25 +232,6 @@
kvm-android.c
endif
-##############################################################################
-# Memory-access checking support.
-# Memory access checker uses information collected by instrumented code in
-# libc.so in order to keep track of memory blocks allocated from heap. Memory
-# checker then uses this information to make sure that every access to allocated
-# memory is within allocated block. This information also allows detecting
-# memory leaks and attempts to free/realloc invalid pointers.
-#
-common_LOCAL_CFLAGS += $(ELFF_CFLAGS)
-
-MCHK_SOURCES := \
- memcheck.c \
- memcheck_proc_management.c \
- memcheck_malloc_map.c \
- memcheck_mmrange_map.c \
- memcheck_util.c
-
-common_LOCAL_SRC_FILES += $(MCHK_SOURCES:%=android/qemu/memcheck/%)
-
common_LOCAL_SRC_FILES += \
cpus.c \
arch_init.c
@@ -296,7 +276,6 @@
emulator-libui \
emulator-libqemu \
emulator-target-$(EMULATOR_TARGET_CPU) \
- emulator-libelff \
emulator-common \
emulator-zlib
@@ -345,6 +324,8 @@
common_LOCAL_SRC_FILES += $(BLOCK_SOURCES)
common_LOCAL_CFLAGS += $(BLOCK_CFLAGS)
+common_LOCAL_LDLIBS += -lstdc++
+
# Generate a completely static executable if needed.
# Note that this means no sound and graphics on Linux.
#
@@ -360,7 +341,6 @@
emulator-libqemu \
emulator-target-$(EMULATOR_TARGET_CPU) \
emulator-libjpeg \
- emulator-libelff \
emulator-common \
emulator-libext4_utils \
emulator-libsparse \
@@ -392,7 +372,6 @@
emulator64-libqemu \
emulator64-target-$(EMULATOR_TARGET_CPU) \
emulator64-libjpeg \
- emulator64-libelff \
emulator64-common \
emulator64-libext4_utils \
emulator64-libsparse \
diff --git a/android/cmdline-options.h b/android/cmdline-options.h
index 4e02923..1009af6 100644
--- a/android/cmdline-options.h
+++ b/android/cmdline-options.h
@@ -150,10 +150,6 @@
OPT_PARAM( nand_limits, "<nlimits>", "enforce NAND/Flash read/write thresholds" )
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK
-OPT_PARAM( memcheck, "<flags>", "enable memory access checking" )
-#endif // CONFIG_ANDROID_MEMCHECK
-
#ifdef CONFIG_STANDALONE_UI
OPT_PARAM( list_cores, "<host>", "list running core process" )
OPT_PARAM( attach_core, "<console socket>", "attach to a running core process" )
diff --git a/android/config/config.h b/android/config/config.h
index 30b941d..d29f7b8 100644
--- a/android/config/config.h
+++ b/android/config/config.h
@@ -13,4 +13,3 @@
#ifndef _WIN32
#define CONFIG_NAND_LIMITS 1
#endif
-#define CONFIG_ANDROID_MEMCHECK 1
diff --git a/android/help.c b/android/help.c
index 91528b2..0fb7f40 100644
--- a/android/help.c
+++ b/android/help.c
@@ -971,45 +971,6 @@
);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
-static void
-help_memcheck(stralloc_t* out)
-{
- PRINTF(
- " use '-memcheck <flags>' to start the emulator with memory access checking\n"
- " support.\n\n"
-
- " <flags> enables, or disables memory access checking, and also controls\n"
- " what events are going to be logged by the memory access checker.\n"
- " <flags> can be one of the following:\n"
- " 1 - Enables memory access checking with default logging (\"LIRW\"), or\n"
- " 0 - Disables memory access checking, or\n"
- " A combination (in no particular order) of the following:\n"
- " L - Logs memory leaks on process exit.\n"
- " I - Logs attempts to use invalid pointers in free, or realloc routines.\n"
- " R - Logs memory access violation on read operations.\n"
- " W - Logs memory access violation on write operations.\n"
- " N - Logs new process ID allocation.\n"
- " F - Logs guest's process forking.\n"
- " S - Logs guest's process starting.\n"
- " E - Logs guest's process exiting.\n"
- " C - Logs guest's thread creation (clone).\n"
- " B - Logs libc.so initialization in the guest system.\n"
- " M - Logs module mapping and unmapping in the guest system.\n"
- " A - Logs all emulator events. Equala to \"LIRWFSECANBM\" combination.\n"
- " e - Logs error messages, received from the guest system.\n"
- " d - Logs debug messages, received from the guest system.\n"
- " i - Logs information messages, received from the guest system.\n"
- " a - Logs all messages, received from the guest system.\n"
- " This is equal to \"edi\" combination.\n\n"
-
- " note that execution might be significantly slower when enabling memory access\n"
- " checking, this is a necessary requirement of the operations being performed\n"
- " to analyze memory allocations and memory access.\n\n"
- );
-}
-#endif // CONFIG_ANDROID_MEMCHECK
-
#ifdef CONFIG_STANDALONE_UI
static void
help_list_cores(stralloc_t* out)
diff --git a/android/main-common.c b/android/main-common.c
index 4221d72..990c44b 100644
--- a/android/main-common.c
+++ b/android/main-common.c
@@ -423,7 +423,6 @@
AConfig* node;
int i;
int max_part_width;
- char fromEnv;
*skinDirPath = avdInfo_getDynamicSkinPath(android_avdInfo);
if (*skinDirPath == NULL) {
diff --git a/android/main.c b/android/main.c
index 8ce827b..4f48291 100644
--- a/android/main.c
+++ b/android/main.c
@@ -1161,11 +1161,6 @@
hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
}
- if (opts->memcheck) {
- args[n++] = "-android-memcheck";
- args[n++] = opts->memcheck;
- }
-
if (opts->gpu) {
const char* gpu = opts->gpu;
if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
diff --git a/android/qemu/memcheck/memcheck.c b/android/qemu/memcheck/memcheck.c
deleted file mode 100644
index e52bc31..0000000
--- a/android/qemu/memcheck/memcheck.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of memory checking framework in the emulator.
- */
-
-#include "qemu/queue.h"
-#include "migration/qemu-file.h"
-#include "elff/elff_api.h"
-#include "android/qemu/memcheck/memcheck.h"
-#include "android/qemu/memcheck/memcheck_proc_management.h"
-#include "android/qemu/memcheck/memcheck_util.h"
-#include "android/qemu/memcheck/memcheck_logging.h"
-
-// =============================================================================
-// Global data
-// =============================================================================
-
-/* Controls what messages from the guest should be printed to emulator's
- * stdout. This variable holds a combinations of TRACE_LIBC_XXX flags. */
-uint32_t trace_flags = 0;
-
-/* Global flag, indicating whether or not memchecking has been enabled
- * for the current emulator session. 1 means that memchecking has been enabled,
- * 0 means that memchecking has not been enabled. */
-int memcheck_enabled = 0;
-
-/* Global flag, indicating whether or not __ld/__stx_mmu should be instrumented
- * for checking for access violations. If read / write access violation check
- * has been disabled by -memcheck flags, there is no need to instrument mmu
- * routines and waste performance.
- * 1 means that instrumenting is required, 0 means that instrumenting is not
- * required. */
-int memcheck_instrument_mmu = 0;
-
-/* Global flag, indicating whether or not memchecker is collecting call stack.
- * 1 - call stack is being collected, 0 means that stack is not being
- * collected. */
-int memcheck_watch_call_stack = 1;
-
-// =============================================================================
-// Static routines.
-// =============================================================================
-
-/* Prints invalid pointer access violation information.
- * Param:
- * proc - Process that caused access violation.
- * ptr - Pointer that caused access violation.
- * routine - If 1, access violation has occurred in 'free' routine.
- * If 2, access violation has occurred in 'realloc' routine.
- */
-static void
-av_invalid_pointer(ProcDesc* proc, target_ulong ptr, int routine)
-{
- if (trace_flags & TRACE_CHECK_INVALID_PTR_ENABLED) {
- printf("memcheck: Access violation is detected in process %s[pid=%u]:\n"
- " INVALID POINTER " TARGET_FMT_lx " is used in '%s' operation.\n"
- " Allocation descriptor for this pointer has not been found in the\n"
- " allocation map for the process. Most likely, this is an attempt\n"
- " to %s a pointer that has been freed.\n",
- proc->image_path,
- proc->pid,
- ptr,
- routine == 1 ? "free" : "realloc",
- routine == 1 ? "free" : "reallocate");
- }
-}
-
-/* Prints read / write access violation information.
- * Param:
- * proc - Process that caused access violation.
- * desc - Allocation descriptor for the violation.
- * addr - Address at which vilation has occurred.
- * data_size - Size of data accessed at the 'addr'.
- * val - If access violation has occurred at write operation, this parameter
- * contains value that's being written to 'addr'. For read violation this
- * parameter is not used.
- * retaddr - Code address (in TB) where access violation has occurred.
- * is_read - If 1, access violation has occurred when memory at 'addr' has been
- * read. If 0, access violation has occurred when memory was written.
- */
-static void
-av_access_violation(ProcDesc* proc,
- MallocDescEx* desc,
- target_ulong addr,
- uint32_t data_size,
- uint64_t val,
- target_ulong retaddr,
- int is_read)
-{
- target_ulong vaddr;
- Elf_AddressInfo elff_info;
- ELFF_HANDLE elff_handle = NULL;
-
- desc->malloc_desc.av_count++;
- if ((is_read && !(trace_flags & TRACE_CHECK_READ_VIOLATION_ENABLED)) ||
- (!is_read && !(trace_flags & TRACE_CHECK_WRITE_VIOLATION_ENABLED))) {
- return;
- }
-
- /* Convert host address to guest address. */
- vaddr = memcheck_tpc_to_gpc(retaddr);
- printf("memcheck: Access violation is detected in process %s[pid=%u]:\n",
- proc->image_path, proc->pid);
-
- /* Obtain routine, filename / line info for the address. */
- const MMRangeDesc* rdesc = procdesc_get_range_desc(proc, vaddr);
- if (rdesc != NULL) {
- int elff_res;
- printf(" In module %s at address " TARGET_FMT_lx "\n", rdesc->path, vaddr);
- elff_res =
- memcheck_get_address_info(vaddr, rdesc, &elff_info, &elff_handle);
- if (elff_res == 0) {
- printf(" In routine %s in %s/%s:%u\n",
- elff_info.routine_name, elff_info.dir_name,
- elff_info.file_name, elff_info.line_number);
- if (elff_info.inline_stack != NULL) {
- const Elf_InlineInfo* inl = elff_info.inline_stack;
- int index = 0;
- for (; inl[index].routine_name != NULL; index++) {
- char align[64];
- size_t set_align = 4 + index * 2;
- if (set_align >= sizeof(align)) {
- set_align = sizeof(align) -1;
- }
- memset(align, ' ', set_align);
- align[set_align] = '\0';
- printf("%s", align);
- if (inl[index].inlined_in_file == NULL) {
- printf("inlined to %s in unknown location\n",
- inl[index].routine_name);
- } else {
- printf("inlined to %s in %s/%s:%u\n",
- inl[index].routine_name,
- inl[index].inlined_in_file_dir,
- inl[index].inlined_in_file,
- inl[index].inlined_at_line);
- }
- }
- }
- elff_free_pc_address_info(elff_handle, &elff_info);
- elff_close(elff_handle);
- } else if (elff_res == 1) {
- printf(" Unable to obtain routine information. Symbols file is not found.\n");
- } else {
- printf(" Unable to obtain routine information.\n"
- " Symbols file doesn't contain debugging information for address "
- TARGET_FMT_lx ".\n",
- mmrangedesc_get_module_offset(rdesc, vaddr));
- }
- } else {
- printf(" In unknown module at address " TARGET_FMT_lx "\n", vaddr);
- }
-
- printf(" Process attempts to %s %u bytes %s address " TARGET_FMT_lx "\n",
- is_read ? "read" : "write", data_size,
- is_read ? "from" : "to", addr);
- printf(" Accessed range belongs to the %s guarding area of allocated block.\n",
- addr < (target_ulong)mallocdesc_get_user_ptr(&desc->malloc_desc) ?
- "prefix" : "suffix");
- printf(" Allocation descriptor for this violation:\n");
- memcheck_dump_malloc_desc(desc, 1, 0);
-}
-
-/* Validates access to a guest address.
- * Param:
- * addr - Virtual address in the guest space where memory is accessed.
- * data_size - Size of the accessed data.
- * proc_ptr - Upon exit from this routine contains pointer to the process
- * descriptor for the current process, or NULL, if no such descriptor has
- * been found.
- * desc_ptr - Upon exit from this routine contains pointer to the allocation
- * descriptor matching given address range, or NULL, if allocation
- * descriptor for the validated memory range has not been found.
- * Return:
- * 0 if access to the given guest address range doesn't violate anything, or
- * 1 if given guest address range doesn't match any entry in the current
- * process allocation descriptors map, or
- * -1 if a violation has been detected.
- */
-static int
-memcheck_common_access_validation(target_ulong addr,
- uint32_t data_size,
- ProcDesc** proc_ptr,
- MallocDescEx** desc_ptr)
-{
- MallocDescEx* desc;
- target_ulong validating_range_end;
- target_ulong user_range_end;
-
- ProcDesc* proc = get_current_process();
- *proc_ptr = proc;
- if (proc == NULL) {
- *desc_ptr = NULL;
- return 1;
- }
-
- desc = procdesc_find_malloc_for_range(proc, addr, data_size);
- *desc_ptr = desc;
- if (desc == NULL) {
- return 1;
- }
-
- /* Verify that validating address range doesn't start before the address
- * available to the user. */
- if (addr < mallocdesc_get_user_ptr(&desc->malloc_desc)) {
- // Stepped on the prefix guarding area.
- return -1;
- }
-
- validating_range_end = addr + data_size;
- user_range_end = mallocdesc_get_user_alloc_end(&desc->malloc_desc);
-
- /* Verify that validating address range ends inside the user block.
- * We may step on the suffix guarding area because of alignment issue.
- * For example, the application code reads last byte in the allocated block
- * with something like this:
- *
- * char last_byte_value = *(char*)last_byte_address;
- *
- * and this code got compiled into something like this:
- *
- * mov eax, [last_byte_address];
- * mov [last_byte_value], al;
- *
- * In this case we will catch a read from the suffix area, even though
- * there were no errors in the code. So, in order to prevent such "false
- * negative" alarms, lets "forgive" this violation.
- * There is one bad thing about this "forgivness" though, as it may very
- * well be, that in real life some of these "out of bound" bytes will cross
- * page boundaries, marching into a page that has not been mapped to the
- * process.
- */
- if (validating_range_end <= user_range_end) {
- // Validating address range is fully contained inside the user block.
- return 0;
- }
-
- /* Lets see if this AV is caused by an alignment issue.*/
- if ((validating_range_end - user_range_end) < data_size) {
- /* Could be an alignment. */
- return 0;
- }
-
- return -1;
-}
-
-/* Checks if process has allocation descriptors for pages defined by a buffer.
- * Param:
- * addr - Starting address of a buffer.
- * buf_size - Buffer size.
- * Return:
- * 1 if process has allocations descriptors for pages defined by a buffer, or
- * 0 if pages containing given buffer don't have any memory allocations in
- * them.
- */
-static inline int
-procdesc_contains_allocs(ProcDesc* proc, target_ulong addr, uint32_t buf_size) {
- if (proc != NULL) {
- // Beginning of the page containing last byte in range.
- const target_ulong end_page = (addr + buf_size - 1) & TARGET_PAGE_MASK;
- // Adjust beginning of the range to the beginning of the page.
- addr &= TARGET_PAGE_MASK;
- // Total size of range to check for descriptors.
- buf_size = end_page - addr + TARGET_PAGE_SIZE + 1;
- return procdesc_find_malloc_for_range(proc, addr, buf_size) ? 1 : 0;
- } else {
- return 0;
- }
-}
-
-// =============================================================================
-// Memchecker API.
-// =============================================================================
-
-void
-memcheck_init(const char* tracing_flags)
-{
- if (*tracing_flags == '0') {
- // Memchecker is disabled.
- return;
- } else if (*tracing_flags == '1') {
- // Set default tracing.
- trace_flags = TRACE_CHECK_LEAK_ENABLED |
- TRACE_CHECK_READ_VIOLATION_ENABLED |
- TRACE_CHECK_INVALID_PTR_ENABLED |
- TRACE_CHECK_WRITE_VIOLATION_ENABLED;
- }
-
- // Parse -memcheck option params, converting them into tracing flags.
- while (*tracing_flags) {
- switch (*tracing_flags) {
- case 'A':
- // Enable all emulator's tracing messages.
- trace_flags |= TRACE_ALL_ENABLED;
- break;
- case 'F':
- // Enable fork() tracing.
- trace_flags |= TRACE_PROC_FORK_ENABLED;
- break;
- case 'S':
- // Enable guest process staring tracing.
- trace_flags |= TRACE_PROC_START_ENABLED;
- break;
- case 'E':
- // Enable guest process exiting tracing.
- trace_flags |= TRACE_PROC_EXIT_ENABLED;
- break;
- case 'C':
- // Enable clone() tracing.
- trace_flags |= TRACE_PROC_CLONE_ENABLED;
- break;
- case 'N':
- // Enable new PID allocation tracing.
- trace_flags |= TRACE_PROC_NEW_PID_ENABLED;
- break;
- case 'B':
- // Enable libc.so initialization tracing.
- trace_flags |= TRACE_PROC_LIBC_INIT_ENABLED;
- break;
- case 'L':
- // Enable memory leaks tracing.
- trace_flags |= TRACE_CHECK_LEAK_ENABLED;
- break;
- case 'I':
- // Enable invalid free / realloc pointer tracing.
- trace_flags |= TRACE_CHECK_INVALID_PTR_ENABLED;
- break;
- case 'R':
- // Enable reading violations tracing.
- trace_flags |= TRACE_CHECK_READ_VIOLATION_ENABLED;
- break;
- case 'W':
- // Enable writing violations tracing.
- trace_flags |= TRACE_CHECK_WRITE_VIOLATION_ENABLED;
- break;
- case 'M':
- // Enable module mapping tracing.
- trace_flags |= TRACE_PROC_MMAP_ENABLED;
- break;
- default:
- break;
- }
- if (trace_flags == TRACE_ALL_ENABLED) {
- break;
- }
- tracing_flags++;
- }
-
- /* Lets see if we need to instrument MMU, injecting memory access checking.
- * We instrument MMU only if we monitor read, or write memory access. */
- if (trace_flags & (TRACE_CHECK_READ_VIOLATION_ENABLED |
- TRACE_CHECK_WRITE_VIOLATION_ENABLED)) {
- memcheck_instrument_mmu = 1;
- } else {
- memcheck_instrument_mmu = 0;
- }
-
- memcheck_init_proc_management();
-
- /* Lets check env. variables needed for memory checking. */
- if (getenv("ANDROID_PROJECT_OUT") == NULL) {
- printf("memcheck: Missing ANDROID_PROJECT_OUT environment variable, that is used\n"
- "to calculate path to symbol files.\n");
- }
-
- // Always set this flag at the very end of the initialization!
- memcheck_enabled = 1;
-}
-
-void
-memcheck_guest_libc_initialized(uint32_t pid)
-{
- ProcDesc* proc = get_process_from_pid(pid);
- if (proc == NULL) {
- ME("memcheck: Unable to obtain process for libc_init pid=%u", pid);
- return;
- }
- proc->flags |= PROC_FLAG_LIBC_INITIALIZED;
-
- /* When process initializes its own libc.so instance, it means that now
- * it has fresh heap. So, at this point we must get rid of all entries
- * (inherited and transition) that were collected in this process'
- * allocation descriptors map. */
- procdesc_empty_alloc_map(proc);
- T(PROC_LIBC_INIT, "memcheck: libc.so has been initialized for %s[pid=%u]\n",
- proc->image_path, proc->pid);
-}
-
-void
-memcheck_guest_alloc(target_ulong guest_address)
-{
- MallocDescEx desc;
- MallocDescEx replaced;
- RBTMapResult insert_res;
- ProcDesc* proc;
- ThreadDesc* thread;
- uint32_t indx;
-
- // Copy allocation descriptor from guest to emulator.
- memcheck_get_malloc_descriptor(&desc.malloc_desc, guest_address);
- desc.flags = 0;
- desc.call_stack = NULL;
- desc.call_stack_count = 0;
-
- proc = get_process_from_pid(desc.malloc_desc.allocator_pid);
- if (proc == NULL) {
- ME("memcheck: Unable to obtain process for allocation pid=%u",
- desc.malloc_desc.allocator_pid);
- memcheck_fail_alloc(guest_address);
- return;
- }
-
- if (!procdesc_is_executing(proc)) {
- desc.flags |= MDESC_FLAG_TRANSITION_ENTRY;
- }
-
- /* Copy thread's calling stack to the allocation descriptor. */
- thread = get_current_thread();
- desc.call_stack_count = thread->call_stack_count;
- if (desc.call_stack_count) {
- desc.call_stack = g_malloc(desc.call_stack_count * sizeof(target_ulong));
- if (desc.call_stack == NULL) {
- ME("memcheck: Unable to allocate %u bytes for the calling stack",
- desc.call_stack_count * sizeof(target_ulong));
- return;
- }
- }
-
- /* Thread's calling stack is in descending order (i.e. first entry in the
- * thread's stack is the most distant routine from the current one). On the
- * other hand, we keep calling stack entries in allocation descriptor in
- * assending order. */
- for (indx = 0; indx < thread->call_stack_count; indx++) {
- desc.call_stack[indx] =
- thread->call_stack[thread->call_stack_count - 1 - indx].call_address;
- }
-
- // Save malloc descriptor in the map.
- insert_res = procdesc_add_malloc(proc, &desc, &replaced);
- if (insert_res == RBT_MAP_RESULT_ENTRY_INSERTED) {
- // Invalidate TLB cache for the allocated block.
- if (memcheck_instrument_mmu) {
- invalidate_tlb_cache(desc.malloc_desc.ptr,
- mallocdesc_get_alloc_end(&desc.malloc_desc));
- }
- } else if (insert_res == RBT_MAP_RESULT_ENTRY_REPLACED) {
- /* We don't expect to have another entry in the map that matches
- * inserting entry. This is an error condition for us, indicating
- * that we somehow lost track of memory allocations. */
- ME("memcheck: Duplicate allocation blocks:");
- if (VERBOSE_CHECK(memcheck)) {
- printf(" New block:\n");
- memcheck_dump_malloc_desc(&desc, 1, 1);
- printf(" Replaced block:\n");
- memcheck_dump_malloc_desc(&replaced, 1, 1);
- }
- if (replaced.call_stack != NULL) {
- g_free(replaced.call_stack);
- }
- } else {
- ME("memcheck: Unable to insert an entry to the allocation map:");
- if (VERBOSE_CHECK(memcheck)) {
- memcheck_dump_malloc_desc(&desc, 1, 1);
- }
- memcheck_fail_alloc(guest_address);
- return;
- }
-}
-
-void
-memcheck_guest_free(target_ulong guest_address)
-{
- MallocFree desc;
- MallocDescEx pulled;
- int pull_res;
- ProcDesc* proc;
-
- // Copy free descriptor from guest to emulator.
- memcheck_get_free_descriptor(&desc, guest_address);
-
- proc = get_process_from_pid(desc.free_pid);
- if (proc == NULL) {
- ME("memcheck: Unable to obtain process for pid=%u on free",
- desc.free_pid);
- memcheck_fail_free(guest_address);
- return;
- }
-
- // Pull matching entry from the map.
- pull_res = procdesc_pull_malloc(proc, desc.ptr, &pulled);
- if (pull_res) {
- av_invalid_pointer(proc, desc.ptr, 1);
- memcheck_fail_free(guest_address);
- return;
- }
-
- // Make sure that ptr has expected value
- if (desc.ptr != mallocdesc_get_user_ptr(&pulled.malloc_desc)) {
- if (trace_flags & TRACE_CHECK_INVALID_PTR_ENABLED) {
- printf("memcheck: Access violation is detected in process %s[pid=%u]:\n",
- proc->image_path, proc->pid);
- printf(" INVALID POINTER 0x%08X is used in 'free' operation.\n"
- " This pointer is unexpected for 'free' operation, as allocation\n"
- " descriptor found for this pointer in the process' allocation map\n"
- " suggests that 0x%08X is the pointer to be used to free this block.\n"
- " Allocation descriptor matching the pointer:\n",
- desc.ptr,
- (uint32_t)mallocdesc_get_user_ptr(&pulled.malloc_desc));
- memcheck_dump_malloc_desc(&pulled, 1, 0);
- }
- }
- if (pulled.call_stack != NULL) {
- g_free(pulled.call_stack);
- }
-}
-
-void
-memcheck_guest_query_malloc(target_ulong guest_address)
-{
- MallocDescQuery qdesc;
- MallocDescEx* found;
- ProcDesc* proc;
-
- // Copy free descriptor from guest to emulator.
- memcheck_get_query_descriptor(&qdesc, guest_address);
-
- proc = get_process_from_pid(qdesc.query_pid);
- if (proc == NULL) {
- ME("memcheck: Unable to obtain process for pid=%u on query_%s",
- qdesc.query_pid, qdesc.routine == 1 ? "free" : "realloc");
- memcheck_fail_query(guest_address);
- return;
- }
-
- // Find allocation entry for the given address.
- found = procdesc_find_malloc(proc, qdesc.ptr);
- if (found == NULL) {
- av_invalid_pointer(proc, qdesc.ptr, qdesc.routine);
- memcheck_fail_query(guest_address);
- return;
- }
-
- // Copy allocation descriptor back to the guest's space.
- memcheck_set_malloc_descriptor(qdesc.desc, &found->malloc_desc);
-}
-
-void
-memcheck_guest_print_str(target_ulong str) {
- char str_copy[4096];
- memcheck_get_guest_string(str_copy, str, sizeof(str_copy));
- printf("%s", str_copy);
-}
-
-/* Validates read operations, detected in __ldx_mmu routine.
- * This routine is called from __ldx_mmu wrapper implemented in
- * softmmu_template.h on condition that loading is occurring from user memory.
- * Param:
- * addr - Virtual address in the guest space where memory is read.
- * data_size - Size of the read.
- * retaddr - Code address (in TB) that accesses memory.
- * Return:
- * 1 if TLB record for the accessed page should be invalidated in order to
- * ensure that subsequent attempts to access data in this page will cause
- * __ld/stx_mmu to be used. If memchecker is no longer interested in monitoring
- * access to this page, this routine returns 0.
- */
-int
-memcheck_validate_ld(target_ulong addr,
- uint32_t data_size,
- target_ulong retaddr)
-{
- ProcDesc* proc;
- MallocDescEx* desc;
-
- int res = memcheck_common_access_validation(addr, data_size, &proc, &desc);
- if (res == -1) {
- av_access_violation(proc, desc, addr, data_size, 0, retaddr, 1);
- return 1;
- }
-
- /* Even though descriptor for the given address range has not been found,
- * we need to make sure that pages containing the given address range
- * don't contain other descriptors. */
- return res ? procdesc_contains_allocs(proc, addr, data_size) : 0;
-}
-
-/* Validates write operations, detected in __stx_mmu routine.
- * This routine is called from __stx_mmu wrapper implemented in
- * softmmu_template.h on condition that storing is occurring from user memory.
- * Param:
- * addr - Virtual address in the guest space where memory is written.
- * data_size - Size of the write.
- * value - Value to be written. Note that we typecast all values to 64 bits,
- * since this will fit all data sizes.
- * retaddr - Code address (in TB) that accesses memory.
- * Return:
- * 1 if TLB record for the accessed page should be invalidated in order to
- * ensure that subsequent attempts to access data in this page will cause
- * __ld/stx_mmu to be used. If memchecker is no longer interested in monitoring
- * access to this page, this routine returns 0.
- */
-int
-memcheck_validate_st(target_ulong addr,
- uint32_t data_size,
- uint64_t value,
- target_ulong retaddr)
-{
- MallocDescEx* desc;
- ProcDesc* proc;
-
- int res = memcheck_common_access_validation(addr, data_size, &proc, &desc);
- if (res == -1) {
- av_access_violation(proc, desc, addr, data_size, value, retaddr, 0);
- return 1;
- }
-
- /* Even though descriptor for the given address range has not been found,
- * we need to make sure that pages containing the given address range
- * don't contain other descriptors. */
- return res ? procdesc_contains_allocs(proc, addr, data_size) : 0;
-}
-
-/* Checks if given address range in the context of the current process is under
- * surveillance.
- * Param:
- * addr - Starting address of a range.
- * size - Range size.
- * Return:
- * boolean: 1 if address range contains memory that require access violation
- * detection, or 0 if given address range is in no interest to the memchecker.
- */
-int
-memcheck_is_checked(target_ulong addr, uint32_t size) {
- return procdesc_contains_allocs(get_current_process(), addr, size) ? 1 : 0;
-}
diff --git a/android/qemu/memcheck/memcheck.h b/android/qemu/memcheck/memcheck.h
deleted file mode 100644
index f983c7e..0000000
--- a/android/qemu/memcheck/memcheck.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of types, constants, and routines used by memory
- * checking framework.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_H
-
-#include "android/qemu/memcheck/memcheck_common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Initializes memory access checking framework.
- * This routine is called from emulator's main routine on condition,
- * that emulator has been started with -memcheck option.
- * Param:
- * tracing_flags - Parameters set for the -memcheck option. These parameters
- * contain abbreviation for memchecking tracing messages that should be enabled
- * for the emulator and guest systems.
- */
-void memcheck_init(const char* tracing_flags);
-
-// =============================================================================
-// Handlers for memory allocation events, generated by the guest system.
-// =============================================================================
-
-/* Libc.so has been initialized by a process in guest's system.
- * This routine is called in response to TRACE_DEV_REG_LIBC_INIT event that is
- * fired up by the guest system on /dev/qemu_trace mapped page.
- * Param:
- * pid - ID of the process in context of which libc.so has been initialized.
- */
-void memcheck_guest_libc_initialized(uint32_t pid);
-
-/* Guest system has allocated memory from heap.
- * This routine is called in response to TRACE_DEV_REG_MALLOC event that is
- * fired up by the guest system on /dev/qemu_trace mapped page.
- * Param:
- * guest_address - Virtual address of allocation descriptor (MallocDesc) that
- * contains information about allocated memory block. Note that this
- * descriptor is located in the guests's user memory. Note also that
- * emulator reports failure back to the guest by zeroing out libc_pid field
- * of the structure, addressed by this parameter.
- */
-void memcheck_guest_alloc(target_ulong guest_address);
-
-/* Guest system is freeing memory to heap.
- * This routine is called in response to TRACE_DEV_REG_FREE_PTR event,
- * fired up by the guest system on /dev/qemu_trace mapped page.
- * Param:
- * guest_address - Virtual address of free descriptor (MallocFree) that
- * contains information about memory block that's being freed. Note that
- * this descriptor is located in the guests's user memory. Note also that
- * emulator reports failure back to the guest by zeroing out libc_pid field
- * of the structure, addressed by this parameter.
- */
-void memcheck_guest_free(target_ulong guest_address);
-
-/* Guest system has queried information about an address in its virtual memory.
- * This routine is called in response to TRACE_DEV_REG_QUERY_MALLOC event,
- * fired up by the guest system on /dev/qemu_trace mapped page.
- * Param:
- * guest_address - Virtual address in the guest's space of the MallocDescQuery
- * structure, that describes the query and receives the response. Note
- * that emulator reports failure back to the guest by zeroing out libc_pid
- * field of the structure, addressed by this parameter.
- */
-void memcheck_guest_query_malloc(target_ulong guest_address);
-
-/* Prints a string to emulator's stdout.
- * This routine is called in response to TRACE_DEV_REG_PRINT_USER_STR event,
- * fired up by the guest system on /dev/qemu_trace mapped page.
- * Param:
- * str - Virtual address in the guest's space of the string to print.
- */
-void memcheck_guest_print_str(target_ulong str);
-
-// =============================================================================
-// Handlers for events, generated by the kernel.
-// =============================================================================
-
-/* Handles PID initialization event.
- * This routine is called in response to TRACE_DEV_REG_INIT_PID event, which
- * indicates that new process has been initialized (but not yet executed).
- * Param:
- * pid - ID of the process that is being initialized. This value will also be
- * used as main thread ID for the intializing process.
- */
-void memcheck_init_pid(uint32_t pid);
-
-/* Handles thread switch event.
- * This routine is called in response to TRACE_DEV_REG_SWITCH event, which
- * indicates that thread switch occurred in the guest system.
- * Param:
- * tid - ID of the thread that becomes active.
- */
-void memcheck_switch(uint32_t tid);
-
-/* Handles process forking / new process creation event.
- * This routine is called in response to TRACE_DEV_REG_FORK event, which
- * indicates that new process has been forked / created. It's assumed, that
- * process that is forking new process is the current process.
- * Param:
- * tgid - TODO: Clarify that!
- * new_pid - Process ID that's been assigned to the forked process.
- */
-void memcheck_fork(uint32_t tgid, uint32_t new_pid);
-
-/* Handles new thread creation event.
- * This routine is called in response to TRACE_DEV_REG_CLONE event, which
- * indicates that new thread has been created in context of the current process.
- * Param:
- * tgid - TODO: Clarify that!
- * new_tid - Thread ID that's been assigned to the new thread.
- */
-void memcheck_clone(uint32_t tgid, uint32_t new_tid);
-
-/* Sets process command line.
- * This routine is called in response to TRACE_DEV_REG_CMDLINE event, which
- * is used to grab first command line argument, and use it is image path to
- * the current process.
- * Param:
- * cmg_arg - Command line arguments.
- * cmdlen - Length of the command line arguments string.
- */
-void memcheck_set_cmd_line(const char* cmd_arg, unsigned cmdlen);
-
-/* Handles thread / process exiting event.
- * This routine is called in response to TRACE_DEV_REG_EXIT event, which
- * indicates that current thread is exiting. We consider that process is
- * exiting when last thread for that process is exiting.
- * Param:
- * exit_code - Thread exit code.
- */
-void memcheck_exit(uint32_t exit_code);
-
-/* Handles memory mapping of a module in guest address space.
- * This routine is called in response to TRACE_DEV_REG_EXECVE_VMSTART,
- * TRACE_DEV_REG_EXECVE_VMEND, TRACE_DEV_REG_EXECVE_OFFSET, and
- * TRACE_DEV_REG_MMAP_EXEPATH events, which indicate that a module has been
- * loaded and mapped on the guest system.
- * Param:
- * vstart - Guest address where mapping starts.
- * vend - Guest address where mapping ends.
- * exec_offset - Exec offset inside module mapping.
- * path - Path to the module that has been mapped.
- */
-void memcheck_mmap_exepath(target_ulong vstart,
- target_ulong vend,
- target_ulong exec_offset,
- const char* path);
-
-/* Handles memory unmapping of a module in guest address space.
- * This routine is called in response to TRACE_DEV_REG_UNMAP_START, and
- * TRACE_DEV_REG_UNMAP_END events, which indicate that a module has been
- * unmapped on the guest system.
- * Param:
- * vstart - Guest address where unmapping starts.
- * vend - Guest address where unmapping ends.
- */
-void memcheck_unmap(target_ulong vstart, target_ulong vend);
-
-/* Global flag, indicating whether or not memchecking has been enabled
- * for the current emulator session. If set to zero, indicates that memchecking
- * is not enabled. Value other than zero indicates that memchecking is enabled
- * for the current emulator session.
- */
-extern int memcheck_enabled;
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_H
diff --git a/android/qemu/memcheck/memcheck_api.h b/android/qemu/memcheck/memcheck_api.h
deleted file mode 100644
index 51d46e3..0000000
--- a/android/qemu/memcheck/memcheck_api.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of memchecker external variables and routines, used by
- * other qemu components.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_API_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_API_H
-
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_ANDROID_MEMCHECK
-#error CONFIG_ANDROID_MEMCHECK is not defined.
-#endif // CONFIG_ANDROID_MEMCHECK
-
-/* Global flag, indicating whether or not memchecking has been enabled
- * for the current emulator session. 1 means that memchecking has been
- * enabled, 0 means that memchecking has not been enabled. The variable
- * is declared in memchec/memcheck.c */
-extern int memcheck_enabled;
-
-/* Flags wether or not mmu instrumentation is enabled by memchecker.
- * 1 - enabled, 0 - is not enabled. */
-extern int memcheck_instrument_mmu;
-
-/* Global flag, indicating whether or not memchecker is collecting call stack.
- * 1 - call stack is being collected, 0 means that stack is not being
- * collected. The variable is declared in memchec/memcheck.c */
-extern int memcheck_watch_call_stack;
-
-/* Array of (tb_pc, guest_pc) pairs, big enough for all translations. This
- * array is used to obtain guest PC address from a translated PC address.
- * tcg_gen_code_common will fill it up when memchecker is enabled. The array is
- * declared in ./translate_all.c */
-extern void** gen_opc_tpc2gpc_ptr;
-
-/* Number of (tb_pc, guest_pc) pairs stored in gen_opc_tpc2gpc array.
- * The variable is declared in ./translate_all.c */
-extern unsigned int gen_opc_tpc2gpc_pairs;
-
-/* Checks if given address range in the context of the current process is
- * under surveillance by memchecker.
- * Param:
- * addr - Starting address of a range.
- * size - Range size.
- * Return:
- * boolean: 1 if address range contains memory that requires access
- * violation detection, or 0 if given address range is in no interest to
- * the memchecker. */
-int memcheck_is_checked(target_ulong addr, uint32_t size);
-
-/* Validates __ldx_mmu operations.
- * Param:
- * addr - Virtual address in the guest space where memory is read.
- * data_size - Size of the read.
- * retaddr - Code address (in TB) that accesses memory.
- * Return:
- * 1 Address should be invalidated in TLB cache, in order to ensure that
- * subsequent attempts to read from that page will launch __ld/__stx_mmu.
- * If this routine returns zero, no page invalidation is requried.
- */
-int memcheck_validate_ld(target_ulong addr,
- uint32_t data_size,
- target_ulong retaddr);
-
-/* Validates __stx_mmu operations.
- * Param:
- * addr - Virtual address in the guest space where memory is written.
- * data_size - Size of the write.
- * value - Value to be written. Note that we typecast all values to 64 bits,
- * since this will fit all data sizes.
- * retaddr - Code address (in TB) that accesses memory.
- * Return:
- * 1 Address should be invalidated in TLB cache, in order to ensure that
- * subsequent attempts to read from that page will launch __ld/__stx_mmu.
- * If this routine returns zero, no page invalidation is requried.
- */
-int memcheck_validate_st(target_ulong addr,
- uint32_t data_size,
- uint64_t value,
- target_ulong retaddr);
-
-/* Memchecker's handler for on_call callback.
- * Param:
- * pc - Guest address where call has been made.
- * ret - Guest address where called routine will return.
- */
-void memcheck_on_call(target_ulong pc, target_ulong ret);
-
-/* Memchecker's handler for on_ret callback.
- * Param:
- * pc - Guest address where routine has returned.
- */
-void memcheck_on_ret(target_ulong pc);
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_API_H
diff --git a/android/qemu/memcheck/memcheck_common.h b/android/qemu/memcheck/memcheck_common.h
deleted file mode 100644
index 6752076..0000000
--- a/android/qemu/memcheck/memcheck_common.h
+++ /dev/null
@@ -1,478 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of structures, routines, etc. that are commonly used
- * in memechecker framework.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_COMMON_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_COMMON_H
-
-#include "qemu-common.h"
-#include "cpu.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// =============================================================================
-// Events generated by the guest system.
-// =============================================================================
-
-/* Notifies the emulator that libc has been initialized for a process.
- * Event's value parameter is PID for the process in context of which libc has
- * been initialized.
- */
-#define TRACE_DEV_REG_LIBC_INIT 1536
-
-/* Notifies the emulator about new memory block being allocated.
- * Event's value parameter points to MallocDesc instance in the guest's address
- * space that contains allocated block information. Note that 'libc_pid' field
- * of the descriptor is used by emulator to report failure in handling this
- * event. In case of failure emulator will zero that filed before completing
- * this event.
- */
-#define TRACE_DEV_REG_MALLOC 1537
-
-/* Notifies the emulator about memory block being freed.
- * Event's value parameter points to MallocFree descriptor instance in the
- * guest's address space that contains information about block that's being
- * freed. Note that 'libc_pid' field of the descriptor is used by emulator to
- * report failure in handling this event. In case of failure emulator will zero
- * that filed before completing this event.
- */
-#define TRACE_DEV_REG_FREE_PTR 1538
-
-/* Queries the emulator about memory block information.
- * Event's value parameter points to MallocDescQuery descriptor instance in the
- * guest's address space that contains query parameters. Note that 'libc_pid'
- * field of the descriptor is used by emulator to report failure in handling
- * this event. In case of failure emulator will zero that filed before
- * completing this event.
- */
-#define TRACE_DEV_REG_QUERY_MALLOC 1539
-
-/* Queries the emulator to print a string to its stdout.
- * Event's value parameter points to zero-terminated string to be printed. Note
- * that this string is located in the guest's address space.
- */
-#define TRACE_DEV_REG_PRINT_USER_STR 1540
-
-// =============================================================================
-// Communication structures
-// =============================================================================
-
-/* Describes memory block allocated from the heap. This structure is passed
- * along with TRACE_DEV_REG_MALLOC event. This descriptor is used to inform
- * the emulator about new memory block being allocated from the heap. The entire
- * structure is initialized by the guest system before event is fired up. It is
- * important to remember that same structure (an exact copy) is also declared
- * in the libc's sources. So, every time a change is made to any of these
- * two declaration, another one must be also updated accordingly. */
-typedef struct MallocDesc {
- /* Poniter to the memory block actually allocated from the heap. Note that
- * this is not the pointer that is returned to the malloc's caller. Pointer
- * returned to the caller is calculated by adding value stored in this field
- * to the value stored in prefix_size field of this structure.
- */
- target_ulong ptr;
-
- /* Nuber of bytes requested by the malloc's caller. */
- uint32_t requested_bytes;
-
- /* Byte size of the prefix data. Actual pointer returned to the malloc's
- * caller is calculated by adding value stored in this field to the value
- * stored in in the ptr field of this structure.
- */
- uint32_t prefix_size;
-
- /* Byte size of the suffix data. */
- uint32_t suffix_size;
-
- /* Id of the process that initialized libc instance, in which allocation
- * has occurred. This field is used by the emulator to report errors in
- * the course of TRACE_DEV_REG_MALLOC event handling. In case of an error,
- * emulator sets this field to zero (invalid value for a process ID).
- */
- uint32_t libc_pid;
-
- /* Id of the process in context of which allocation has occurred.
- * Value in this field may differ from libc_pid value, if process that
- * is doing allocation has been forked from the process that initialized
- * libc instance.
- */
- uint32_t allocator_pid;
-
- /* Number of access violations detected on this allocation. */
- uint32_t av_count;
-} MallocDesc;
-/* Helpers for addressing field in MallocDesc structure, using which emulator
- * reports an error back to the guest.
- */
-#define ALLOC_RES_OFFSET ((uint32_t)(ptrdiff_t)&(((MallocDesc*)0)->libc_pid))
-#define ALLOC_RES_ADDRESS(p) (p + ALLOC_RES_OFFSET)
-
-/* Describes memory block info queried from emulator. This structure is passed
- * along with TRACE_DEV_REG_QUERY_MALLOC event. When handling free and realloc
- * calls, it is required that we have information about memory blocks that were
- * actually allocated in previous calls to malloc, memalign, or realloc. Since
- * we don't keep this information directlry in the allocated block, but rather
- * we keep it in the emulator, we need to query emulator for that information
- * with TRACE_DEV_REG_QUERY_MALLOC query. The entire structure is initialized
- * by the guest system before event is fired up It is important to remember that
- * same structure (an exact copy) is also declared in the libc's sources. So,
- * every time a change is made to any of these two declaration, another one
- * must be also updated accordingly.
- */
-typedef struct MallocDescQuery {
- /* Pointer for which information is queried. Note that this pointer doesn't
- * have to be exact pointer returned to malloc's caller, but can point
- * anywhere inside an allocated block, including guarding areas. Emulator
- * will respond with information about allocated block that contains this
- * pointer.
- */
- target_ulong ptr;
-
- /* Id of the process that initialized libc instance, in which this query
- * is called. This field is used by the emulator to report errors in
- * the course of TRACE_DEV_REG_QUERY_MALLOC event handling. In case of an
- * error, emulator sets this field to zero (invalid value for a process ID).
- */
- uint32_t libc_pid;
-
- /* Process ID in context of which query is made. */
- uint32_t query_pid;
-
- /* Code of the allocation routine, in context of which query has been made:
- * 1 - free
- * 2 - realloc
- */
- uint32_t routine;
-
- /* Address in guest's virtual space of memory allocation descriptor for the
- * queried pointer. Descriptor, addressed by this field is initialized by
- * the emulator in response to the query.
- */
- target_ulong desc;
-} MallocDescQuery;
-/* Helpers for addressing field in MallocDescQuery structure using which
- * emulator reports an error back to the guest.
- */
-#define QUERY_RES_OFFSET ((uint32_t)(ptrdiff_t)&(((MallocDescQuery*)0)->libc_pid))
-#define QUERY_RES_ADDRESS(p) (p + QUERY_RES_OFFSET)
-
-/* Describes memory block that is being freed back to the heap. This structure
- * is passed along with TRACE_DEV_REG_FREE_PTR event. The entire structure is
- * initialized by the guest system before event is fired up. It is important to
- * remember that same structure (an exact copy) is also declared in the libc's
- * sources. So, every time a change is made to any of these two declaration,
- * another one must be also updated accordingly.
- */
-typedef struct MallocFree {
- /* Pointer to be freed. */
- uint32_t ptr;
-
- /* Id of the process that initialized libc instance, in which this free
- * is called. This field is used by the emulator to report errors in
- * the course of TRACE_DEV_REG_FREE_PTR event handling. In case of an
- * error, emulator sets this field to zero (invalid value for a process ID).
- */
- uint32_t libc_pid;
-
- /* Process ID in context of which memory is being freed. */
- uint32_t free_pid;
-} MallocFree;
-/* Helpers for addressing field in MallocFree structure, using which emulator
- * reports an error back to the guest.
- */
-#define FREE_RES_OFFSET ((uint32_t)(ptrdiff_t)&(((MallocFree*)0)->libc_pid))
-#define FREE_RES_ADDRESS(p) (p + FREE_RES_OFFSET)
-
-/* Extends MallocDesc structure with additional information, used by memchecker.
- */
-typedef struct MallocDescEx {
- /* Allocation descriptor this structure extends. */
- MallocDesc malloc_desc;
-
- /* Call stack that lead to memory allocation. The array is arranged in
- * accending order, where entry at index 0 corresponds to the routine
- * that allocated memory. */
- target_ulong* call_stack;
-
- /* Number of entries in call_stack array. */
- uint32_t call_stack_count;
-
- /* Set of misc. flags. See MDESC_FLAG_XXX bellow. */
- uint32_t flags;
-} MallocDescEx;
-
-/* Indicates that memory has been allocated before process started execution.
- * After a process has been forked, but before it actually starts executing,
- * allocations can be made in context of that process PID. This flag marks such
- * allocations in the process' allocation descriptors map.
- */
-#define MDESC_FLAG_TRANSITION_ENTRY 0x00000001
-
-/* Indicates that memory block has been inherited from the parent process.
- * When a process is forked from its parent process, the forked process inherits
- * a copy of the parent process' heap. Thus, all allocations that were recorded
- * for the parent process must be also recorded for the forked process. This
- * flag marks entries in the forked process' allocation descriptors map that
- * were copied over from the parent process' allocation descriptors map.
- */
-#define MDESC_FLAG_INHERITED_ON_FORK 0x00000002
-
-/* Describes a memory mapping of an execution module in the guest system. */
-typedef struct MMRangeDesc {
- /* Starting address of mmapping of a module in the guest's address space. */
- target_ulong map_start;
-
- /* Ending address of mmapping of a module in the guest's address space. */
- target_ulong map_end;
-
- /* Mmapping's execution offset. */
- target_ulong exec_offset;
-
- /* Image path of the module that has been mapped with this mmapping. */
- char* path;
-} MMRangeDesc;
-
-/* Enumerates returned values for insert routines implemeted for red-black
- * tree maps.
- */
-typedef enum {
- /* New entry has been inserted into the map. */
- RBT_MAP_RESULT_ENTRY_INSERTED = 0,
-
- /* An entry, matching the new one already exists in the map. */
- RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS,
-
- /* An existing entry, matching the new one has been replaced
- * with the new entry.
- */
- RBT_MAP_RESULT_ENTRY_REPLACED,
-
- /* An error has occurred when inserting entry into the map. */
- RBT_MAP_RESULT_ERROR = -1,
-} RBTMapResult;
-
-/* Encapsulates an array of guest addresses, sorted in accending order. */
-typedef struct AddrArray {
- /* Array of addresses. */
- target_ulong* addr;
-
- /* Number of elements in the array. */
- int num;
-} AddrArray;
-
-// =============================================================================
-// Inlines
-// =============================================================================
-
-/* Gets pointer returned to malloc caller for the given allocation decriptor.
- * Param:
- * desc - Allocation descriptor.
- * Return:
- * Pointer to the allocated memory returned to the malloc caller.
- */
-static inline target_ulong
-mallocdesc_get_user_ptr(const MallocDesc* desc)
-{
- return desc->ptr + desc->prefix_size;
-}
-
-/* Gets total size of the allocated block for the given descriptor.
- * Param:
- * desc - Descriptor for the memory block, allocated in malloc handler.
- * Return:
- * Total size of memory block allocated in malloc handler.
- */
-static inline uint32_t
-mallocdesc_get_alloc_size(const MallocDesc* desc)
-{
- return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
-}
-
-/* Gets the end of the allocated block for the given descriptor.
- * Param:
- * desc - Descriptor for the memory block, allocated in malloc handler.
- * Return:
- * Pointer to the end of the allocated block (next byte past the block).
- */
-static inline target_ulong
-mallocdesc_get_alloc_end(const MallocDesc* desc)
-{
- return desc->ptr + mallocdesc_get_alloc_size(desc);
-}
-
-/* Gets the end of the allocated block available to the user for the given
- * descriptor.
- * Param:
- * desc - Descriptor for the memory block, allocated in malloc handler.
- * Return:
- * Pointer to the end of the allocated block available to the user (next byte
- * past the block - suffix guarding area).
- */
-static inline target_ulong
-mallocdesc_get_user_alloc_end(const MallocDesc* desc)
-{
- return mallocdesc_get_user_ptr(desc) + desc->requested_bytes;
-}
-
-/* Checks if allocation has been made before process started execution.
- * Param:
- * desc - Allocation descriptor to check.
- * Return:
- * boolean: 1 if allocation has been made before process started execution,
- * or 0 if allocation has been made after process started execution.
- */
-static inline int
-mallocdescex_is_transition_entry(const MallocDescEx* desc)
-{
- return (desc->flags & MDESC_FLAG_TRANSITION_ENTRY) != 0;
-}
-
-/* Checks if allocation block has been inherited on fork.
- * Param:
- * desc - Allocation descriptor to check.
- * Return:
- * boolean: 1 if allocation has been inherited on fork, or 0 if allocation
- * has been made by this process..
- */
-static inline int
-mallocdescex_is_inherited_on_fork(const MallocDescEx* desc)
-{
- return (desc->flags & MDESC_FLAG_INHERITED_ON_FORK) != 0;
-}
-
-/* Gets offset for the given address inside a mapped module.
- * Param:
- * address - Address to get offset for.
- * Return:
- * Offset of the given address inside a mapped module, represented with the
- * given mmaping range descriptor.
- */
-static inline target_ulong
-mmrangedesc_get_module_offset(const MMRangeDesc* rdesc, target_ulong address)
-{
- return address - rdesc->map_start + rdesc->exec_offset;
-}
-
-/* Checks if given address is contained in the given address array.
- * Return:
- * boolean: 1 if address is contained in the array, or zero if it's not.
- */
-static inline int
-addrarray_check(const AddrArray* addr_array, target_ulong addr)
-{
- if (addr_array->num != 0) {
- int m_min = 0;
- int m_max = addr_array->num - 1;
-
- /* May be odd for THUMB mode. */
- addr &= ~1;
- /* Since array is sorted we can do binary search here. */
- while (m_min <= m_max) {
- const int m = (m_min + m_max) >> 1;
- const target_ulong saved = addr_array->addr[m];
- if (addr == saved) {
- return 1;
- }
- if (addr < saved) {
- m_max = m - 1;
- } else {
- m_min = m + 1;
- }
- }
- }
- return 0;
-}
-
-/* Adds an address to the address array.
- * Return:
- * 1 - Address has been added to the array.
- * -1 - Address already exists in the array.
- * 0 - Unable to expand the array.
- */
-static inline int
-addrarray_add(AddrArray* addr_array, target_ulong addr)
-{
- target_ulong* new_arr;
- int m_min;
- int m_max;
-
- /* May be odd for THUMB mode. */
- addr &= ~1;
- if (addr_array->num == 0) {
- /* First element. */
- addr_array->addr = g_malloc(sizeof(target_ulong));
- assert(addr_array->addr != NULL);
- if (addr_array->addr == NULL) {
- return 0;
- }
- *addr_array->addr = addr;
- addr_array->num++;
- return 1;
- }
-
- /* Using binary search find the place where to insert new address. */
- m_min = 0;
- m_max = addr_array->num - 1;
- while (m_min <= m_max) {
- const int m = (m_min + m_max) >> 1;
- const target_ulong saved = addr_array->addr[m];
- if (addr == saved) {
- return -1;
- }
- if (addr < saved) {
- m_max = m - 1;
- } else {
- m_min = m + 1;
- }
- }
- if (m_max < 0) {
- m_max = 0;
- }
- /* Expand the array. */
- new_arr = g_malloc(sizeof(target_ulong) * (addr_array->num + 1));
- assert(new_arr != NULL);
- if (new_arr == NULL) {
- return 0;
- }
- /* Copy preceding elements to the new array. */
- if (m_max != 0) {
- memcpy(new_arr, addr_array->addr, m_max * sizeof(target_ulong));
- }
- if (addr > addr_array->addr[m_max]) {
- new_arr[m_max] = addr_array->addr[m_max];
- m_max++;
- }
- /* Insert new address. */
- new_arr[m_max] = addr;
- /* Copy remaining elements to the new array. */
- if (m_max < addr_array->num) {
- memcpy(new_arr + m_max + 1, addr_array->addr + m_max,
- (addr_array->num - m_max) * sizeof(target_ulong));
- }
- /* Swap arrays. */
- g_free(addr_array->addr);
- addr_array->addr = new_arr;
- addr_array->num++;
- return 1;
-}
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_COMMON_H
diff --git a/android/qemu/memcheck/memcheck_logging.h b/android/qemu/memcheck/memcheck_logging.h
deleted file mode 100644
index 4c78f7c..0000000
--- a/android/qemu/memcheck/memcheck_logging.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of logging macros used in memchecker framework.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_LOGGING_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_LOGGING_H
-
-#include "qemu-common.h"
-#include "android/utils/debug.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Prints debug message under the 'memcheck' tag. */
-#define MD(...) VERBOSE_PRINT(memcheck, __VA_ARGS__)
-
-/* Prints an error message under the 'memcheck' tag. */
-#define ME(...) \
- do { if (VERBOSE_CHECK(memcheck)) derror(__VA_ARGS__); } while (0)
-
-// =============================================================================
-// Tracing flags (see trace_flags declared in memcheck.c), and macros
-// =============================================================================
-
-/* Enables fork() tracing. */
-#define TRACE_PROC_FORK_ENABLED 0x00000001
-/* Enables clone() tracing. */
-#define TRACE_PROC_CLONE_ENABLED 0x00000002
-/* Enables new PID allocation tracing. */
-#define TRACE_PROC_NEW_PID_ENABLED 0x00000004
-/* Enables guest process starting tracing. */
-#define TRACE_PROC_START_ENABLED 0x00000008
-/* Enables guest process exiting tracing. */
-#define TRACE_PROC_EXIT_ENABLED 0x00000010
-/* Enables libc.so initialization tracing. */
-#define TRACE_PROC_LIBC_INIT_ENABLED 0x00000020
-/* Enables leaking tracing. */
-#define TRACE_CHECK_LEAK_ENABLED 0x00000040
-/* Enables invalid pointer access tracing. */
-#define TRACE_CHECK_INVALID_PTR_ENABLED 0x00000080
-/* Enables reading violations tracing. */
-#define TRACE_CHECK_READ_VIOLATION_ENABLED 0x00000100
-/* Enables writing violations tracing. */
-#define TRACE_CHECK_WRITE_VIOLATION_ENABLED 0x00000200
-/* Enables module mapping tracing. */
-#define TRACE_PROC_MMAP_ENABLED 0x00000400
-/* All tracing flags combined. */
-#define TRACE_ALL_ENABLED (TRACE_PROC_FORK_ENABLED | \
- TRACE_PROC_CLONE_ENABLED | \
- TRACE_PROC_NEW_PID_ENABLED | \
- TRACE_PROC_START_ENABLED | \
- TRACE_PROC_LIBC_INIT_ENABLED | \
- TRACE_PROC_EXIT_ENABLED | \
- TRACE_CHECK_INVALID_PTR_ENABLED | \
- TRACE_CHECK_READ_VIOLATION_ENABLED | \
- TRACE_CHECK_WRITE_VIOLATION_ENABLED | \
- TRACE_PROC_MMAP_ENABLED | \
- TRACE_CHECK_LEAK_ENABLED)
-
-/* Prints a trace to the stdout. */
-#define T(level, ...) \
- do { \
- if (trace_flags & TRACE_##level##_ENABLED) { \
- printf(__VA_ARGS__); \
- } \
- } while (0)
-
-/* Set of tracing flags (declared in memchek.c). */
-extern uint32_t trace_flags;
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_LOGGING_H
diff --git a/android/qemu/memcheck/memcheck_malloc_map.c b/android/qemu/memcheck/memcheck_malloc_map.c
deleted file mode 100644
index 0fcd577..0000000
--- a/android/qemu/memcheck/memcheck_malloc_map.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of routines that implement a red-black tree of
- * memory blocks allocated by the guest system.
- */
-
-#include "android/qemu/memcheck/memcheck_malloc_map.h"
-#include "android/qemu/memcheck/memcheck_util.h"
-#include "android/qemu/memcheck/memcheck_logging.h"
-
-/* Global flag, indicating whether or not __ld/__stx_mmu should be instrumented
- * for checking for access violations. If read / write access violation check.
- * Defined in memcheck.c
- */
-extern int memcheck_instrument_mmu;
-
-/* Allocation descriptor stored in the map. */
-typedef struct AllocMapEntry {
- /* R-B tree entry. */
- RB_ENTRY(AllocMapEntry) rb_entry;
-
- /* Allocation descriptor for this entry. */
- MallocDescEx desc;
-} AllocMapEntry;
-
-// =============================================================================
-// Inlines
-// =============================================================================
-
-/* Gets address of the beginning of an allocation block for the given entry in
- * the map.
- * Param:
- * adesc - Entry in the allocation descriptors map.
- * Return:
- * Address of the beginning of an allocation block for the given entry in the
- * map.
- */
-static inline target_ulong
-allocmapentry_alloc_begins(const AllocMapEntry* adesc)
-{
- return adesc->desc.malloc_desc.ptr;
-}
-
-/* Gets address of the end of an allocation block for the given entry in
- * the map.
- * Param:
- * adesc - Entry in the allocation descriptors map.
- * Return:
- * Address of the end of an allocation block for the given entry in the map.
- */
-static inline target_ulong
-allocmapentry_alloc_ends(const AllocMapEntry* adesc)
-{
- return mallocdesc_get_alloc_end(&adesc->desc.malloc_desc);
-}
-
-// =============================================================================
-// R-B Tree implementation
-// =============================================================================
-
-/* Compare routine for the allocation descriptors map.
- * Param:
- * d1 - First map entry to compare.
- * d2 - Second map entry to compare.
- * Return:
- * 0 - Descriptors are equal. Note that descriptors are considered to be
- * equal iff memory blocks they describe intersect in any part.
- * 1 - d1 is greater than d2
- * -1 - d1 is less than d2.
- */
-static inline int
-cmp_rb(AllocMapEntry* d1, AllocMapEntry* d2)
-{
- const target_ulong start1 = allocmapentry_alloc_begins(d1);
- const target_ulong start2 = allocmapentry_alloc_begins(d2);
-
- if (start1 < start2) {
- return (allocmapentry_alloc_ends(d1) - 1) < start2 ? -1 : 0;
- }
- return (allocmapentry_alloc_ends(d2) - 1) < start1 ? 1 : 0;
-}
-
-/* Expands RB macros here. */
-RB_GENERATE(AllocMap, AllocMapEntry, rb_entry, cmp_rb);
-
-// =============================================================================
-// Static routines
-// =============================================================================
-
-/* Inserts new (or replaces existing) entry into allocation descriptors map.
- * See comments on allocmap_insert routine in the header file for details
- * about this routine.
- */
-static RBTMapResult
-allocmap_insert_desc(AllocMap* map,
- AllocMapEntry* adesc,
- MallocDescEx* replaced)
-{
- AllocMapEntry* existing = AllocMap_RB_INSERT(map, adesc);
- if (existing == NULL) {
- return RBT_MAP_RESULT_ENTRY_INSERTED;
- }
-
- // Matching entry exists. Lets see if we need to replace it.
- if (replaced == NULL) {
- return RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS;
- }
-
- /* Copy existing entry to the provided buffer and replace it
- * with the new one. */
- memcpy(replaced, &existing->desc, sizeof(MallocDescEx));
- AllocMap_RB_REMOVE(map, existing);
- g_free(existing);
- AllocMap_RB_INSERT(map, adesc);
- return RBT_MAP_RESULT_ENTRY_REPLACED;
-}
-
-/* Finds an entry in the allocation descriptors map that matches the given
- * address range.
- * Param:
- * map - Allocation descriptors map where to search for an entry.
- * address - Virtual address in the guest's user space to find matching
- * entry for.
- * Return:
- * Address of an allocation descriptors map entry that matches the given
- * address, or NULL if no such entry has been found.
- */
-static inline AllocMapEntry*
-allocmap_find_entry(const AllocMap* map,
- target_ulong address,
- uint32_t block_size)
-{
- AllocMapEntry adesc;
- adesc.desc.malloc_desc.ptr = address;
- adesc.desc.malloc_desc.requested_bytes = block_size;
- adesc.desc.malloc_desc.prefix_size = 0;
- adesc.desc.malloc_desc.suffix_size = 0;
- return AllocMap_RB_FIND((AllocMap*)map, &adesc);
-}
-
-// =============================================================================
-// Map API
-// =============================================================================
-
-void
-allocmap_init(AllocMap* map)
-{
- RB_INIT(map);
-}
-
-RBTMapResult
-allocmap_insert(AllocMap* map, const MallocDescEx* desc, MallocDescEx* replaced)
-{
- RBTMapResult ret;
-
- // Allocate and initialize new map entry.
- AllocMapEntry* adesc = g_malloc(sizeof(AllocMapEntry));
- if (adesc == NULL) {
- ME("memcheck: Unable to allocate new AllocMapEntry on insert.");
- return RBT_MAP_RESULT_ERROR;
- }
- memcpy(&adesc->desc, desc, sizeof(MallocDescEx));
-
- // Insert new entry into the map.
- ret = allocmap_insert_desc(map, adesc, replaced);
- if (ret == RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS ||
- ret == RBT_MAP_RESULT_ERROR) {
- /* Another descriptor already exists for this block, or an error
- * occurred. We have to tree new descriptor, as it wasn't inserted. */
- g_free(adesc);
- }
- return ret;
-}
-
-MallocDescEx*
-allocmap_find(const AllocMap* map, target_ulong address, uint32_t block_size)
-{
- AllocMapEntry* adesc = allocmap_find_entry(map, address, block_size);
- return adesc != NULL ? &adesc->desc : NULL;
-}
-
-int
-allocmap_pull(AllocMap* map, target_ulong address, MallocDescEx* pulled)
-{
- AllocMapEntry* adesc = allocmap_find_entry(map, address, 1);
- if (adesc != NULL) {
- memcpy(pulled, &adesc->desc, sizeof(MallocDescEx));
- AllocMap_RB_REMOVE(map, adesc);
- g_free(adesc);
- return 0;
- } else {
- return -1;
- }
-}
-
-int
-allocmap_pull_first(AllocMap* map, MallocDescEx* pulled)
-{
- AllocMapEntry* first = RB_MIN(AllocMap, map);
- if (first != NULL) {
- memcpy(pulled, &first->desc, sizeof(MallocDescEx));
- AllocMap_RB_REMOVE(map, first);
- g_free(first);
- return 0;
- } else {
- return -1;
- }
-}
-
-int
-allocmap_copy(AllocMap* to,
- const AllocMap* from,
- uint32_t set_flags,
- uint32_t clear_flags)
-{
- AllocMapEntry* entry;
- RB_FOREACH(entry, AllocMap, (AllocMap*)from) {
- RBTMapResult ins_res;
- AllocMapEntry* new_entry =
- (AllocMapEntry*)g_malloc(sizeof(AllocMapEntry));
- if (new_entry == NULL) {
- ME("memcheck: Unable to allocate new AllocMapEntry on copy.");
- return -1;
- }
- memcpy(new_entry, entry, sizeof(AllocMapEntry));
- new_entry->desc.flags &= ~clear_flags;
- new_entry->desc.flags |= set_flags;
- if (entry->desc.call_stack_count) {
- new_entry->desc.call_stack =
- g_malloc(entry->desc.call_stack_count * sizeof(target_ulong));
- memcpy(new_entry->desc.call_stack, entry->desc.call_stack,
- entry->desc.call_stack_count * sizeof(target_ulong));
- } else {
- new_entry->desc.call_stack = NULL;
- }
- new_entry->desc.call_stack_count = entry->desc.call_stack_count;
- ins_res = allocmap_insert_desc(to, new_entry, NULL);
- if (ins_res == RBT_MAP_RESULT_ENTRY_INSERTED) {
- if (memcheck_instrument_mmu) {
- // Invalidate TLB cache for inserted entry.
- invalidate_tlb_cache(new_entry->desc.malloc_desc.ptr,
- mallocdesc_get_alloc_end(&new_entry->desc.malloc_desc));
- }
- } else {
- ME("memcheck: Unable to insert new map entry on copy. Insert returned %u",
- ins_res);
- if (new_entry->desc.call_stack != NULL) {
- g_free(new_entry->desc.call_stack);
- }
- g_free(new_entry);
- return -1;
- }
- }
-
- return 0;
-}
-
-int
-allocmap_empty(AllocMap* map)
-{
- MallocDescEx pulled;
- int removed = 0;
-
- while (!allocmap_pull_first(map, &pulled)) {
- removed++;
- if (pulled.call_stack != NULL) {
- g_free(pulled.call_stack);
- }
- }
-
- return removed;
-}
diff --git a/android/qemu/memcheck/memcheck_malloc_map.h b/android/qemu/memcheck/memcheck_malloc_map.h
deleted file mode 100644
index 5c16b56..0000000
--- a/android/qemu/memcheck/memcheck_malloc_map.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of structures and routines that implement a red-black
- * tree (a map) of memory blocks allocated by the guest system. The map is
- * organized in such a way, that each entry in the map describes a virtual
- * address range that belongs to a memory block allocated in the guest's space.
- * The range includes block's suffix and prefix, as well as block returned to
- * malloc's caller. Map considers two blocks to be equal if their address ranges
- * intersect in any part. Allocation descriptor maps are instantiated one per
- * each process running on the guest system.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_MALLOC_MAP_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_MALLOC_MAP_H
-
-#include "sys-tree.h"
-#include "android/qemu/memcheck/memcheck_common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Allocation descriptors map. */
-typedef struct AllocMap {
- /* Head of the map. */
- struct AllocMapEntry* rbh_root;
-} AllocMap;
-
-// =============================================================================
-// Map API
-// =============================================================================
-
-/* Initializes allocation descriptors map.
- * Param:
- * map - Allocation descriptors map to initialize.
- */
-void allocmap_init(AllocMap* map);
-
-/* Inserts new (or replaces existing) entry in the allocation descriptors map.
- * Insertion, or replacement is controlled by the value, passed to this routine
- * with 'replaced' parameter. If this parameter is NULL, insertion will fail if
- * a matching entry already exists in the map. If 'replaced' parameter is not
- * NULL, and a matching entry exists in the map, content of the existing entry
- * will be copied to the descriptor, addressed by 'replace' parameter, existing
- * entry will be removed from the map, and new entry will be inserted.
- * Param:
- * map - Allocation descriptors map where to insert new, or replace existing
- * entry.
- * desc - Allocation descriptor to insert to the map.
- * replaced - If not NULL, upon return from this routine contains descriptor
- * that has been replaced in the map with the new entry. Note that if this
- * routine returns with value other than RBT_MAP_RESULT_ENTRY_REPLACED,
- * content of the 'replaced' buffer is not defined, as no replacement has
- * actually occurred.
- * Return
- * See RBTMapResult for the return codes.
- */
-RBTMapResult allocmap_insert(AllocMap* map,
- const MallocDescEx* desc,
- MallocDescEx* replaced);
-
-/* Finds an entry in the allocation descriptors map that matches the given
- * address.
- * Param:
- * map - Allocation descriptors map where to search for an entry.
- * address - Virtual address in the guest's user space to find matching
- * entry for. Entry matches the address, if address is contained within
- * allocated memory range (including guarding areas), as defined by the
- * memory allocation descriptor for that entry.
- * block_size - Size of the block, beginning with 'address'.
- * Return:
- * Pointer to the allocation descriptor found in a map entry, or NULL if no
- * matching entry has been found in the map.
- */
-MallocDescEx* allocmap_find(const AllocMap* map,
- target_ulong address,
- uint32_t block_size);
-
-/* Pulls (finds and removes) an entry from the allocation descriptors map that
- * matches the given address.
- * Param:
- * map - Allocation descriptors map where to search for an entry.
- * address - Virtual address in the guest's user space to find matching
- * entry for. Entry matches the address, if address is contained within
- * allocated memory range (including guarding areas), as defined by the
- * memory allocation descriptor for that entry.
- * pulled - Upon successful return contains allocation descriptor data pulled
- * from the map.
- * Return:
- * Zero if an allocation descriptor that matches the given address has
- * been pulled, or 1 if no matching entry has been found in the map.
- */
-int allocmap_pull(AllocMap* map, target_ulong address, MallocDescEx* pulled);
-
-/* Pulls (removes) an entry from the head of the allocation descriptors map.
- * Param:
- * map - Allocation descriptors map where to pull an entry from.
- * pulled - Upon successful return contains allocation descriptor data pulled
- * from the head of the map.
- * Return:
- * Zero if an allocation descriptor has been pulled from the head of the map,
- * or 1 if map is empty.
- */
-int allocmap_pull_first(AllocMap* map, MallocDescEx* pulled);
-
-/* Copies content of one memory allocation descriptors map to another.
- * Param:
- * to - Map where to copy entries to.
- * from - Map where to copy entries from.
- * set_flags - Flags that should be set in the copied entry's 'flags' field.
- * celar_flags - Flags that should be cleared in the copied entry's 'flags'
- * field.
- * Return:
- * Zero on success, or -1 on error.
- */
-int allocmap_copy(AllocMap* to,
- const AllocMap* from,
- uint32_t set_flags,
- uint32_t clear_flags);
-
-/* Empties the map.
- * Param:
- * map - Map to empty.
- * Return:
- * Number of entries removed from the map.
- */
-int allocmap_empty(AllocMap* map);
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_MALLOC_MAP_H
diff --git a/android/qemu/memcheck/memcheck_mmrange_map.c b/android/qemu/memcheck/memcheck_mmrange_map.c
deleted file mode 100644
index 03f1fcf..0000000
--- a/android/qemu/memcheck/memcheck_mmrange_map.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of routines that implement a red-black tree of
- * memory mappings in the guest system.
- */
-
-#include "android/qemu/memcheck/memcheck_mmrange_map.h"
-#include "android/qemu/memcheck/memcheck_logging.h"
-
-/* Memory range descriptor stored in the map. */
-typedef struct MMRangeMapEntry {
- /* R-B tree entry. */
- RB_ENTRY(MMRangeMapEntry) rb_entry;
-
- /* Memory range descriptor for this entry. */
- MMRangeDesc desc;
-} MMRangeMapEntry;
-
-// =============================================================================
-// R-B Tree implementation
-// =============================================================================
-
-/* Compare routine for the map.
- * Param:
- * d1 - First map entry to compare.
- * d2 - Second map entry to compare.
- * Return:
- * 0 - Descriptors are equal. Note that descriptors are considered to be
- * equal iff memory blocks they describe intersect in any part.
- * 1 - d1 is greater than d2
- * -1 - d1 is less than d2.
- */
-static inline int
-cmp_rb(MMRangeMapEntry* d1, MMRangeMapEntry* d2)
-{
- const target_ulong start1 = d1->desc.map_start;
- const target_ulong start2 = d2->desc.map_start;
-
- if (start1 < start2) {
- return (d1->desc.map_end - 1) < start2 ? -1 : 0;
- }
- return (d2->desc.map_end - 1) < start1 ? 1 : 0;
-}
-
-/* Expands RB macros here. */
-RB_GENERATE(MMRangeMap, MMRangeMapEntry, rb_entry, cmp_rb);
-
-// =============================================================================
-// Static routines
-// =============================================================================
-
-/* Inserts new (or replaces existing) entry into the map.
- * See comments on mmrangemap_insert routine in the header file for details
- * about this routine.
- */
-static RBTMapResult
-mmrangemap_insert_desc(MMRangeMap* map,
- MMRangeMapEntry* rdesc,
- MMRangeDesc* replaced)
-{
- MMRangeMapEntry* existing = MMRangeMap_RB_INSERT(map, rdesc);
- if (existing == NULL) {
- return RBT_MAP_RESULT_ENTRY_INSERTED;
- }
-
- // Matching entry exists. Lets see if we need to replace it.
- if (replaced == NULL) {
- return RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS;
- }
-
- /* Copy existing entry to the provided buffer and replace it
- * with the new one. */
- memcpy(replaced, &existing->desc, sizeof(MMRangeDesc));
- MMRangeMap_RB_REMOVE(map, existing);
- g_free(existing);
- MMRangeMap_RB_INSERT(map, rdesc);
- return RBT_MAP_RESULT_ENTRY_REPLACED;
-}
-
-/* Finds an entry in the map that matches the given address range.
- * Param:
- * map - Map where to search for an entry.
- * start - Starting address of a mapping range.
- * end - Ending address of a mapping range.
- * Return:
- * Address of a map entry that matches the given range, or NULL if no
- * such entry has been found.
- */
-static inline MMRangeMapEntry*
-mmrangemap_find_entry(const MMRangeMap* map,
- target_ulong start,
- target_ulong end)
-{
- MMRangeMapEntry rdesc;
- rdesc.desc.map_start = start;
- rdesc.desc.map_end = end;
- return MMRangeMap_RB_FIND((MMRangeMap*)map, &rdesc);
-}
-
-// =============================================================================
-// Map API
-// =============================================================================
-
-void
-mmrangemap_init(MMRangeMap* map)
-{
- RB_INIT(map);
-}
-
-RBTMapResult
-mmrangemap_insert(MMRangeMap* map,
- const MMRangeDesc* desc,
- MMRangeDesc* replaced)
-{
- RBTMapResult ret;
-
- // Allocate and initialize new map entry.
- MMRangeMapEntry* rdesc = g_malloc(sizeof(MMRangeMapEntry));
- if (rdesc == NULL) {
- ME("memcheck: Unable to allocate new MMRangeMapEntry on insert.");
- return RBT_MAP_RESULT_ERROR;
- }
- memcpy(&rdesc->desc, desc, sizeof(MMRangeDesc));
-
- // Insert new entry into the map.
- ret = mmrangemap_insert_desc(map, rdesc, replaced);
- if (ret == RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS ||
- ret == RBT_MAP_RESULT_ERROR) {
- /* Another descriptor already exists for this block, or an error
- * occurred. We have to free new descriptor, as it wasn't inserted. */
- g_free(rdesc);
- }
- return ret;
-}
-
-MMRangeDesc*
-mmrangemap_find(const MMRangeMap* map, target_ulong start, target_ulong end)
-{
- MMRangeMapEntry* rdesc = mmrangemap_find_entry(map, start, end);
- return rdesc != NULL ? &rdesc->desc : NULL;
-}
-
-int
-mmrangemap_pull(MMRangeMap* map,
- target_ulong start,
- target_ulong end,
- MMRangeDesc* pulled)
-{
- MMRangeMapEntry* rdesc = mmrangemap_find_entry(map, start, end);
- if (rdesc != NULL) {
- memcpy(pulled, &rdesc->desc, sizeof(MMRangeDesc));
- MMRangeMap_RB_REMOVE(map, rdesc);
- g_free(rdesc);
- return 0;
- } else {
- return -1;
- }
-}
-
-int
-mmrangemap_pull_first(MMRangeMap* map, MMRangeDesc* pulled)
-{
- MMRangeMapEntry* first = RB_MIN(MMRangeMap, map);
- if (first != NULL) {
- memcpy(pulled, &first->desc, sizeof(MMRangeDesc));
- MMRangeMap_RB_REMOVE(map, first);
- g_free(first);
- return 0;
- } else {
- return -1;
- }
-}
-
-int
-mmrangemap_copy(MMRangeMap* to, const MMRangeMap* from)
-{
- MMRangeMapEntry* entry;
- RB_FOREACH(entry, MMRangeMap, (MMRangeMap*)from) {
- RBTMapResult ins_res;
- MMRangeMapEntry* new_entry =
- (MMRangeMapEntry*)g_malloc(sizeof(MMRangeMapEntry));
- if (new_entry == NULL) {
- ME("memcheck: Unable to allocate new MMRangeMapEntry on copy.");
- return -1;
- }
- memcpy(new_entry, entry, sizeof(MMRangeMapEntry));
- new_entry->desc.path = g_malloc(strlen(entry->desc.path) + 1);
- if (new_entry->desc.path == NULL) {
- ME("memcheck: Unable to allocate new path for MMRangeMapEntry on copy.");
- g_free(new_entry);
- return -1;
- }
- strcpy(new_entry->desc.path, entry->desc.path);
- ins_res = mmrangemap_insert_desc(to, new_entry, NULL);
- if (ins_res != RBT_MAP_RESULT_ENTRY_INSERTED) {
- ME("memcheck: Unable to insert new range map entry on copy. Insert returned %u",
- ins_res);
- g_free(new_entry->desc.path);
- g_free(new_entry);
- return -1;
- }
- }
-
- return 0;
-}
-
-int
-mmrangemap_empty(MMRangeMap* map)
-{
- MMRangeDesc pulled;
- int removed = 0;
-
- while (!mmrangemap_pull_first(map, &pulled)) {
- g_free(pulled.path);
- removed++;
- }
-
- return removed;
-}
diff --git a/android/qemu/memcheck/memcheck_mmrange_map.h b/android/qemu/memcheck/memcheck_mmrange_map.h
deleted file mode 100644
index ceebc30..0000000
--- a/android/qemu/memcheck/memcheck_mmrange_map.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of structures and routines that implement a red-black
- * tree (a map) of module memory mapping ranges in the guest system. The map is
- * organized in such a way, that each entry in the map describes a virtual
- * address range that belongs to a mapped execution module in the guest system.
- * Map considers two ranges to be equal if their address ranges intersect in
- * any part.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_MMRANGE_MAP_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_MMRANGE_MAP_H
-
-#include "sys-tree.h"
-#include "android/qemu/memcheck/memcheck_common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Memory mapping range map. */
-typedef struct MMRangeMap {
- /* Head of the map. */
- struct MMRangeMapEntry* rbh_root;
-} MMRangeMap;
-
-// =============================================================================
-// Map API
-// =============================================================================
-
-/* Initializes the map.
- * Param:
- * map - Map to initialize.
- */
-void mmrangemap_init(MMRangeMap* map);
-
-/* Inserts new (or replaces existing) entry in the map.
- * Insertion, or replacement is controlled by the value, passed to this routine
- * with 'replaced' parameter. If this parameter is NULL, insertion will fail if
- * a matching entry already exists in the map. If 'replaced' parameter is not
- * NULL, and a matching entry exists in the map, content of the existing entry
- * will be copied to the descriptor, addressed by 'replace' parameter, existing
- * entry will be removed from the map, and new entry will be inserted.
- * Param:
- * map - Map where to insert new, or replace existing entry.
- * desc - Descriptor to insert to the map.
- * replaced - If not NULL, upon return from this routine contains descriptor
- * that has been replaced in the map with the new entry. Note that if this
- * routine returns with value other than RBT_MAP_RESULT_ENTRY_REPLACED,
- * content of the 'replaced' buffer is not defined, as no replacement has
- * actually occurred.
- * Return
- * See RBTMapResult for the return codes.
- */
-RBTMapResult mmrangemap_insert(MMRangeMap* map,
- const MMRangeDesc* desc,
- MMRangeDesc* replaced);
-
-/* Finds an entry in the map that matches the given address.
- * Param:
- * map - Map where to search for an entry.
- * start - Starting address of a mapping range.
- * end - Ending address of a mapping range.
- * Return:
- * Pointer to the descriptor found in a map entry, or NULL if no matching
- * entry has been found in the map.
- */
-MMRangeDesc* mmrangemap_find(const MMRangeMap* map,
- target_ulong start,
- target_ulong end);
-
-/* Pulls (finds and removes) an entry from the map that matches the given
- * address.
- * Param:
- * map - Map where to search for an entry.
- * start - Starting address of a mapping range.
- * end - Ending address of a mapping range.
- * pulled - Upon successful return contains descriptor data pulled from the
- * map.
- * Return:
- * Zero if a descriptor that matches the given address has been pulled, or 1
- * if no matching entry has been found in the map.
- */
-int mmrangemap_pull(MMRangeMap* map,
- target_ulong start,
- target_ulong end,
- MMRangeDesc* pulled);
-
-/* Copies content of one memory map to another.
- * Param:
- * to - Map where to copy entries to.
- * from - Map where to copy entries from.
- * Return:
- * Zero on success, or -1 on error.
- */
-int mmrangemap_copy(MMRangeMap* to, const MMRangeMap* from);
-
-/* Empties the map.
- * Param:
- * map - Map to empty.
- * Return:
- * Number of entries removed from the map.
- */
-int mmrangemap_empty(MMRangeMap* map);
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_MMRANGE_MAP_H
diff --git a/android/qemu/memcheck/memcheck_proc_management.c b/android/qemu/memcheck/memcheck_proc_management.c
deleted file mode 100644
index 514f709..0000000
--- a/android/qemu/memcheck/memcheck_proc_management.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of routines related to process management in
- * memchecker framework.
- */
-
-#include "elff/elff_api.h"
-#include "android/qemu/memcheck/memcheck.h"
-#include "android/qemu/memcheck/memcheck_proc_management.h"
-#include "android/qemu/memcheck/memcheck_logging.h"
-#include "android/qemu/memcheck/memcheck_util.h"
-
-/* Current thread id.
- * This value is updated with each call to memcheck_switch, saving here
- * ID of the thread that becomes current. */
-static uint32_t current_tid = 0;
-
-/* Current thread descriptor.
- * This variable is used to cache current thread descriptor. This value gets
- * initialized on "as needed" basis, when descriptor for the current thread
- * is requested for the first time.
- * Note that every time memcheck_switch routine is called, this value gets
- * NULL'ed, since another thread becomes current. */
-static ThreadDesc* current_thread = NULL;
-
-/* Current process descriptor.
- * This variable is used to cache current process descriptor. This value gets
- * initialized on "as needed" basis, when descriptor for the current process
- * is requested for the first time.
- * Note that every time memcheck_switch routine is called, this value gets
- * NULL'ed, since new thread becomes current, thus process switch may have
- * occurred as well. */
-static ProcDesc* current_process = NULL;
-
-/* List of running processes. */
-static QLIST_HEAD(proc_list, ProcDesc) proc_list;
-
-/* List of running threads. */
-static QLIST_HEAD(thread_list, ThreadDesc) thread_list;
-
-// =============================================================================
-// Static routines
-// =============================================================================
-
-/* Creates and lists thread descriptor for a new thread.
- * This routine will allocate and initialize new thread descriptor. After that
- * this routine will insert the descriptor into the global list of running
- * threads, as well as thread list in the process descriptor of the process
- * in context of which this thread is created.
- * Param:
- * proc - Process descriptor of the process, in context of which new thread
- * is created.
- * tid - Thread ID of the thread that's being created.
- * Return:
- * New thread descriptor on success, or NULL on failure.
- */
-static ThreadDesc*
-create_new_thread(ProcDesc* proc, uint32_t tid)
-{
- ThreadDesc* new_thread = (ThreadDesc*)g_malloc(sizeof(ThreadDesc));
- if (new_thread == NULL) {
- ME("memcheck: Unable to allocate new thread descriptor.");
- return NULL;
- }
- new_thread->tid = tid;
- new_thread->process = proc;
- new_thread->call_stack = NULL;
- new_thread->call_stack_count = 0;
- new_thread->call_stack_max = 0;
- QLIST_INSERT_HEAD(&thread_list, new_thread, global_entry);
- QLIST_INSERT_HEAD(&proc->threads, new_thread, proc_entry);
- return new_thread;
-}
-
-/* Creates and lists process descriptor for a new process.
- * This routine will allocate and initialize new process descriptor. After that
- * this routine will create main thread descriptor for the process (with the
- * thread ID equal to the new process ID), and then new process descriptor will
- * be inserted into the global list of running processes.
- * Param:
- * pid - Process ID of the process that's being created.
- * parent_pid - Process ID of the parent process.
- * Return:
- * New process descriptor on success, or NULL on failure.
- */
-static ProcDesc*
-create_new_process(uint32_t pid, uint32_t parent_pid)
-{
- // Create and init new process descriptor.
- ProcDesc* new_proc = (ProcDesc*)g_malloc(sizeof(ProcDesc));
- if (new_proc == NULL) {
- ME("memcheck: Unable to allocate new process descriptor");
- return NULL;
- }
- QLIST_INIT(&new_proc->threads);
- allocmap_init(&new_proc->alloc_map);
- mmrangemap_init(&new_proc->mmrange_map);
- new_proc->pid = pid;
- new_proc->parent_pid = parent_pid;
- new_proc->image_path = NULL;
- new_proc->flags = 0;
-
- if (parent_pid != 0) {
- /* If new process has been forked, it inherits a copy of parent's
- * process heap, as well as parent's mmaping of loaded modules. So, on
- * fork we're required to copy parent's allocation descriptors map, as
- * well as parent's mmapping map to the new process. */
- int failed;
- ProcDesc* parent = get_process_from_pid(parent_pid);
- if (parent == NULL) {
- ME("memcheck: Unable to get parent process pid=%u for new process pid=%u",
- parent_pid, pid);
- g_free(new_proc);
- return NULL;
- }
-
- /* Copy parent's allocation map, setting "inherited" flag, and clearing
- * parent's "transition" flag in the copied entries. */
- failed = allocmap_copy(&new_proc->alloc_map, &parent->alloc_map,
- MDESC_FLAG_INHERITED_ON_FORK,
- MDESC_FLAG_TRANSITION_ENTRY);
- if (failed) {
- ME("memcheck: Unable to copy process' %s[pid=%u] allocation map to new process pid=%u",
- parent->image_path, parent_pid, pid);
- allocmap_empty(&new_proc->alloc_map);
- g_free(new_proc);
- return NULL;
- }
-
- // Copy parent's memory mappings map.
- failed = mmrangemap_copy(&new_proc->mmrange_map, &parent->mmrange_map);
- if (failed) {
- ME("memcheck: Unable to copy process' %s[pid=%u] mmrange map to new process pid=%u",
- parent->image_path, parent_pid, pid);
- mmrangemap_empty(&new_proc->mmrange_map);
- allocmap_empty(&new_proc->alloc_map);
- g_free(new_proc);
- return NULL;
- }
- }
-
- // Create and register main thread descriptor for new process.
- if(create_new_thread(new_proc, pid) == NULL) {
- mmrangemap_empty(&new_proc->mmrange_map);
- allocmap_empty(&new_proc->alloc_map);
- g_free(new_proc);
- return NULL;
- }
-
- // List new process.
- QLIST_INSERT_HEAD(&proc_list, new_proc, global_entry);
-
- return new_proc;
-}
-
-/* Finds thread descriptor for a thread id in the global list of running
- * threads.
- * Param:
- * tid - Thread ID to look up thread descriptor for.
- * Return:
- * Found thread descriptor, or NULL if thread descriptor has not been found.
- */
-static ThreadDesc*
-get_thread_from_tid(uint32_t tid)
-{
- ThreadDesc* thread;
-
- /* There is a pretty good chance that when this call is made, it's made
- * to get descriptor for the current thread. Lets see if it is so, so
- * we don't have to iterate through the entire list. */
- if (tid == current_tid && current_thread != NULL) {
- return current_thread;
- }
-
- QLIST_FOREACH(thread, &thread_list, global_entry) {
- if (tid == thread->tid) {
- if (tid == current_tid) {
- current_thread = thread;
- }
- return thread;
- }
- }
- return NULL;
-}
-
-/* Gets thread descriptor for the current thread.
- * Return:
- * Found thread descriptor, or NULL if thread descriptor has not been found.
- */
-ThreadDesc*
-get_current_thread(void)
-{
- // Lets see if current thread descriptor has been cached.
- if (current_thread == NULL) {
- /* Descriptor is not cached. Look it up in the list. Note that
- * get_thread_from_tid(current_tid) is not used here in order to
- * optimize this code for performance, as this routine is called from
- * the performance sensitive path. */
- ThreadDesc* thread;
- QLIST_FOREACH(thread, &thread_list, global_entry) {
- if (current_tid == thread->tid) {
- current_thread = thread;
- return current_thread;
- }
- }
- }
- return current_thread;
-}
-
-/* Finds process descriptor for a thread id.
- * Param:
- * tid - Thread ID to look up process descriptor for.
- * Return:
- * Process descriptor for the thread, or NULL, if process descriptor
- * has not been found.
- */
-static inline ProcDesc*
-get_process_from_tid(uint32_t tid)
-{
- const ThreadDesc* thread = get_thread_from_tid(tid);
- return (thread != NULL) ? thread->process : NULL;
-}
-
-/* Sets, or replaces process image path in process descriptor.
- * Generally, new process' image path is unknown untill we calculate it in
- * the handler for TRACE_DEV_REG_CMDLINE event. This routine is called from
- * TRACE_DEV_REG_CMDLINE event handler to set, or replace process image path.
- * Param:
- * proc - Descriptor of the process where to set, or replace image path.
- * image_path - Image path to the process, transmitted with
- * TRACE_DEV_REG_CMDLINE event.
- * set_flags_on_replace - Flags to be set when current image path for the
- * process has been actually replaced with the new one.
- * Return:
- * Zero on success, or -1 on failure.
- */
-static int
-procdesc_set_image_path(ProcDesc* proc,
- const char* image_path,
- uint32_t set_flags_on_replace)
-{
- if (image_path == NULL || proc == NULL) {
- return 0;
- }
-
- if (proc->image_path != NULL) {
- /* Process could have been forked, and inherited image path of the
- * parent process. However, it seems that "fork" in terms of TRACE_XXX
- * is not necessarly a strict "fork", but rather new process creation
- * in general. So, if that's the case we need to override image path
- * inherited from the parent process. */
- if (!strcmp(proc->image_path, image_path)) {
- // Paths are the same. Just bail out.
- return 0;
- }
- g_free(proc->image_path);
- proc->image_path = NULL;
- }
-
- // Save new image path into process' descriptor.
- proc->image_path = g_malloc(strlen(image_path) + 1);
- if (proc->image_path == NULL) {
- ME("memcheck: Unable to allocate %u bytes for image path %s to set it for pid=%u",
- strlen(image_path) + 1, image_path, proc->pid);
- return -1;
- }
- strcpy(proc->image_path, image_path);
- proc->flags |= set_flags_on_replace;
- return 0;
-}
-
-/* Frees thread descriptor. */
-static void
-threaddesc_free(ThreadDesc* thread)
-{
- uint32_t indx;
-
- if (thread == NULL) {
- return;
- }
-
- if (thread->call_stack != NULL) {
- for (indx = 0; indx < thread->call_stack_count; indx++) {
- if (thread->call_stack[indx].module_path != NULL) {
- g_free(thread->call_stack[indx].module_path);
- }
- }
- g_free(thread->call_stack);
- }
- g_free(thread);
-}
-
-// =============================================================================
-// Process management API
-// =============================================================================
-
-void
-memcheck_init_proc_management(void)
-{
- QLIST_INIT(&proc_list);
- QLIST_INIT(&thread_list);
-}
-
-ProcDesc*
-get_process_from_pid(uint32_t pid)
-{
- ProcDesc* proc;
-
- /* Chances are that pid addresses the current process. Lets check this,
- * so we don't have to iterate through the entire project list. */
- if (current_thread != NULL && current_thread->process->pid == pid) {
- current_process = current_thread->process;
- return current_process;
- }
-
- QLIST_FOREACH(proc, &proc_list, global_entry) {
- if (pid == proc->pid) {
- break;
- }
- }
- return proc;
-}
-
-ProcDesc*
-get_current_process(void)
-{
- if (current_process == NULL) {
- const ThreadDesc* cur_thread = get_current_thread();
- if (cur_thread != NULL) {
- current_process = cur_thread->process;
- }
- }
- return current_process;
-}
-
-void
-memcheck_on_call(target_ulong from, target_ulong ret)
-{
- const uint32_t grow_by = 32;
- const uint32_t max_stack = grow_by;
- ThreadDesc* thread = get_current_thread();
- if (thread == NULL) {
- return;
- }
-
- /* We're not saving call stack until process starts execution. */
- if (!procdesc_is_executing(thread->process)) {
- return;
- }
-
- const MMRangeDesc* rdesc = procdesc_get_range_desc(thread->process, from);
- if (rdesc == NULL) {
- ME("memcheck: Unable to find mapping for guest PC 0x%08X in process %s[pid=%u]",
- from, thread->process->image_path, thread->process->pid);
- return;
- }
-
- /* Limit calling stack size. There are cases when calling stack can be
- * quite deep due to recursion (up to 4000 entries). */
- if (thread->call_stack_count >= max_stack) {
-#if 0
- /* This happens quite often. */
- MD("memcheck: Thread stack for %s[pid=%u, tid=%u] is too big: %u",
- thread->process->image_path, thread->process->pid, thread->tid,
- thread->call_stack_count);
-#endif
- return;
- }
-
- if (thread->call_stack_count >= thread->call_stack_max) {
- /* Expand calling stack array buffer. */
- thread->call_stack_max += grow_by;
- ThreadCallStackEntry* new_array =
- g_malloc(thread->call_stack_max * sizeof(ThreadCallStackEntry));
- if (new_array == NULL) {
- ME("memcheck: Unable to allocate %u bytes for calling stack.",
- thread->call_stack_max * sizeof(ThreadCallStackEntry));
- thread->call_stack_max -= grow_by;
- return;
- }
- if (thread->call_stack_count != 0) {
- memcpy(new_array, thread->call_stack,
- thread->call_stack_count * sizeof(ThreadCallStackEntry));
- }
- if (thread->call_stack != NULL) {
- g_free(thread->call_stack);
- }
- thread->call_stack = new_array;
- }
- thread->call_stack[thread->call_stack_count].call_address = from;
- thread->call_stack[thread->call_stack_count].call_address_rel =
- mmrangedesc_get_module_offset(rdesc, from);
- thread->call_stack[thread->call_stack_count].ret_address = ret;
- thread->call_stack[thread->call_stack_count].ret_address_rel =
- mmrangedesc_get_module_offset(rdesc, ret);
- thread->call_stack[thread->call_stack_count].module_path =
- g_malloc(strlen(rdesc->path) + 1);
- if (thread->call_stack[thread->call_stack_count].module_path == NULL) {
- ME("memcheck: Unable to allocate %u bytes for module path in the thread calling stack.",
- strlen(rdesc->path) + 1);
- return;
- }
- strcpy(thread->call_stack[thread->call_stack_count].module_path,
- rdesc->path);
- thread->call_stack_count++;
-}
-
-void
-memcheck_on_ret(target_ulong ret)
-{
- ThreadDesc* thread = get_current_thread();
- if (thread == NULL) {
- return;
- }
-
- /* We're not saving call stack until process starts execution. */
- if (!procdesc_is_executing(thread->process)) {
- return;
- }
-
- if (thread->call_stack_count > 0) {
- int indx = (int)thread->call_stack_count - 1;
- for (; indx >= 0; indx--) {
- if (thread->call_stack[indx].ret_address == ret) {
- thread->call_stack_count = indx;
- return;
- }
- }
- }
-}
-
-// =============================================================================
-// Handlers for events, generated by the kernel.
-// =============================================================================
-
-void
-memcheck_init_pid(uint32_t new_pid)
-{
- create_new_process(new_pid, 0);
- T(PROC_NEW_PID, "memcheck: init_pid(pid=%u) in current thread tid=%u\n",
- new_pid, current_tid);
-}
-
-void
-memcheck_switch(uint32_t tid)
-{
- /* Since new thread became active, we have to invalidate cached
- * descriptors for current thread and process. */
- current_thread = NULL;
- current_process = NULL;
- current_tid = tid;
-}
-
-void
-memcheck_fork(uint32_t tgid, uint32_t new_pid)
-{
- ProcDesc* parent_proc;
- ProcDesc* new_proc;
-
- /* tgid may match new_pid, in which case current process is the
- * one that's being forked, otherwise tgid identifies process
- * that's being forked. */
- if (new_pid == tgid) {
- parent_proc = get_current_process();
- } else {
- parent_proc = get_process_from_tid(tgid);
- }
-
- if (parent_proc == NULL) {
- ME("memcheck: FORK(%u, %u): Unable to look up parent process. Current tid=%u",
- tgid, new_pid, current_tid);
- return;
- }
-
- if (parent_proc->pid != get_current_process()->pid) {
- MD("memcheck: FORK(%u, %u): parent %s[pid=%u] is not the current process %s[pid=%u]",
- tgid, new_pid, parent_proc->image_path, parent_proc->pid,
- get_current_process()->image_path, get_current_process()->pid);
- }
-
- new_proc = create_new_process(new_pid, parent_proc->pid);
- if (new_proc == NULL) {
- return;
- }
-
- /* Since we're possibly forking parent process, we need to inherit
- * parent's image path in the forked process. */
- procdesc_set_image_path(new_proc, parent_proc->image_path, 0);
-
- T(PROC_FORK, "memcheck: FORK(tgid=%u, new_pid=%u) by %s[pid=%u] (tid=%u)\n",
- tgid, new_pid, parent_proc->image_path, parent_proc->pid, current_tid);
-}
-
-void
-memcheck_clone(uint32_t tgid, uint32_t new_tid)
-{
- ProcDesc* parent_proc;
-
- /* tgid may match new_pid, in which case current process is the
- * one that creates thread, otherwise tgid identifies process
- * that creates thread. */
- if (new_tid == tgid) {
- parent_proc = get_current_process();
- } else {
- parent_proc = get_process_from_tid(tgid);
- }
-
- if (parent_proc == NULL) {
- ME("memcheck: CLONE(%u, %u) Unable to look up parent process. Current tid=%u",
- tgid, new_tid, current_tid);
- return;
- }
-
- if (parent_proc->pid != get_current_process()->pid) {
- ME("memcheck: CLONE(%u, %u): parent %s[pid=%u] is not the current process %s[pid=%u]",
- tgid, new_tid, parent_proc->image_path, parent_proc->pid,
- get_current_process()->image_path, get_current_process()->pid);
- }
-
- create_new_thread(parent_proc, new_tid);
-
- T(PROC_CLONE, "memcheck: CLONE(tgid=%u, new_tid=%u) by %s[pid=%u] (tid=%u)\n",
- tgid, new_tid, parent_proc->image_path, parent_proc->pid, current_tid);
-}
-
-void
-memcheck_set_cmd_line(const char* cmd_arg, unsigned cmdlen)
-{
- char parsed[4096];
- int n;
-
- ProcDesc* current_proc = get_current_process();
- if (current_proc == NULL) {
- ME("memcheck: CMDL(%s, %u): Unable to look up process for current tid=%3u",
- cmd_arg, cmdlen, current_tid);
- return;
- }
-
- /* Image path is the first agrument in cmd line. Note that due to
- * limitations of TRACE_XXX cmdlen can never exceed CLIENT_PAGE_SIZE */
- memcpy(parsed, cmd_arg, cmdlen);
-
- // Cut first argument off the entire command line.
- for (n = 0; n < cmdlen; n++) {
- if (parsed[n] == ' ') {
- break;
- }
- }
- parsed[n] = '\0';
-
- // Save process' image path into descriptor.
- procdesc_set_image_path(current_proc, parsed,
- PROC_FLAG_IMAGE_PATH_REPLACED);
- current_proc->flags |= PROC_FLAG_EXECUTING;
-
- /* At this point we need to discard memory mappings inherited from
- * the parent process, since this process has become "independent" from
- * its parent. */
- mmrangemap_empty(¤t_proc->mmrange_map);
- T(PROC_START, "memcheck: Executing process %s[pid=%u]\n",
- current_proc->image_path, current_proc->pid);
-}
-
-void
-memcheck_exit(uint32_t exit_code)
-{
- ProcDesc* proc;
- int leaks_reported = 0;
- MallocDescEx leaked_alloc;
-
- // Exiting thread descriptor.
- ThreadDesc* thread = get_current_thread();
- if (thread == NULL) {
- ME("memcheck: EXIT(%u): Unable to look up thread for current tid=%u",
- exit_code, current_tid);
- return;
- }
- proc = thread->process;
-
- // Since current thread is exiting, we need to NULL its cached descriptor.
- current_thread = NULL;
-
- // Unlist the thread from its process as well as global lists.
- QLIST_REMOVE(thread, proc_entry);
- QLIST_REMOVE(thread, global_entry);
- threaddesc_free(thread);
-
- /* Lets see if this was last process thread, which would indicate
- * process termination. */
- if (!QLIST_EMPTY(&proc->threads)) {
- return;
- }
-
- // Process is terminating. Report leaks and free resources.
- proc->flags |= PROC_FLAG_EXITING;
-
- /* Empty allocation descriptors map for the exiting process,
- * reporting leaking blocks in the process. */
- while (!allocmap_pull_first(&proc->alloc_map, &leaked_alloc)) {
- /* We should "forgive" blocks that were inherited from the
- * parent process on fork, or were allocated while process was
- * in "transition" state. */
- if (!mallocdescex_is_inherited_on_fork(&leaked_alloc) &&
- !mallocdescex_is_transition_entry(&leaked_alloc)) {
- if (!leaks_reported) {
- // First leak detected. Print report's header.
- T(CHECK_LEAK, "memcheck: Process %s[pid=%u] is exiting leaking allocated blocks:\n",
- proc->image_path, proc->pid);
- }
- if (trace_flags & TRACE_CHECK_LEAK_ENABLED) {
- // Dump leaked block information.
- printf(" Leaked block %u:\n", leaks_reported + 1);
- memcheck_dump_malloc_desc(&leaked_alloc, 0, 0);
- if (leaked_alloc.call_stack != NULL) {
- const int max_stack = 24;
- if (max_stack >= leaked_alloc.call_stack_count) {
- printf(" Call stack:\n");
- } else {
- printf(" Call stack (first %u of %u entries):\n",
- max_stack, leaked_alloc.call_stack_count);
- }
- uint32_t stk;
- for (stk = 0;
- stk < leaked_alloc.call_stack_count && stk < max_stack;
- stk++) {
- const MMRangeDesc* rdesc =
- procdesc_find_mapentry(proc,
- leaked_alloc.call_stack[stk]);
- if (rdesc != NULL) {
- Elf_AddressInfo elff_info;
- ELFF_HANDLE elff_handle = NULL;
- uint32_t rel =
- mmrangedesc_get_module_offset(rdesc,
- leaked_alloc.call_stack[stk]);
- printf(" Frame %u: PC=" TARGET_FMT_lx " (relative %llx) in module %s\n",
- stk, leaked_alloc.call_stack[stk], (long long)rel,
- rdesc->path);
- if (memcheck_get_address_info(leaked_alloc.call_stack[stk],
- rdesc, &elff_info,
- &elff_handle) == 0) {
- printf(" Routine %s @ %s/%s:%u\n",
- elff_info.routine_name,
- elff_info.dir_name,
- elff_info.file_name,
- elff_info.line_number);
- elff_free_pc_address_info(elff_handle,
- &elff_info);
- elff_close(elff_handle);
- }
- } else {
- printf(" Frame %u: PC=" TARGET_FMT_lx " in module <unknown>\n",
- stk, leaked_alloc.call_stack[stk]);
-
- }
- }
- }
- }
- leaks_reported++;
- }
- }
-
- if (leaks_reported) {
- T(CHECK_LEAK, "memcheck: Process %s[pid=%u] is leaking %u allocated blocks.\n",
- proc->image_path, proc->pid, leaks_reported);
- }
-
- T(PROC_EXIT, "memcheck: Exiting process %s[pid=%u] in thread %u. Memory leaks detected: %u\n",
- proc->image_path, proc->pid, current_tid, leaks_reported);
-
- /* Since current process is exiting, we need to NULL its cached descriptor,
- * and unlist it from the list of running processes. */
- current_process = NULL;
- QLIST_REMOVE(proc, global_entry);
-
- // Empty process' mmapings map.
- mmrangemap_empty(&proc->mmrange_map);
- if (proc->image_path != NULL) {
- g_free(proc->image_path);
- }
- g_free(proc);
-}
-
-void
-memcheck_mmap_exepath(target_ulong vstart,
- target_ulong vend,
- target_ulong exec_offset,
- const char* path)
-{
- MMRangeDesc desc;
- MMRangeDesc replaced;
- RBTMapResult ins_res;
-
- ProcDesc* proc = get_current_process();
- if (proc == NULL) {
- ME("memcheck: MMAP(0x%08X, 0x%08X, 0x%08X, %s) Unable to look up current process. Current tid=%u",
- vstart, vend, exec_offset, path, current_tid);
- return;
- }
-
- /* First, unmap an overlapped section */
- memcheck_unmap(vstart, vend);
-
- /* Add new mapping. */
- desc.map_start = vstart;
- desc.map_end = vend;
- desc.exec_offset = exec_offset;
- desc.path = g_malloc(strlen(path) + 1);
- if (desc.path == NULL) {
- ME("memcheck: MMAP(0x%08X, 0x%08X, 0x%08X, %s) Unable to allocate path for the entry.",
- vstart, vend, exec_offset, path);
- return;
- }
- strcpy(desc.path, path);
-
- ins_res = mmrangemap_insert(&proc->mmrange_map, &desc, &replaced);
- if (ins_res == RBT_MAP_RESULT_ERROR) {
- ME("memcheck: %s[pid=%u] unable to insert memory mapping entry: 0x%08X - 0x%08X",
- proc->image_path, proc->pid, vstart, vend);
- g_free(desc.path);
- return;
- }
-
- if (ins_res == RBT_MAP_RESULT_ENTRY_REPLACED) {
- MD("memcheck: %s[pid=%u] MMRANGE %s[0x%08X - 0x%08X] is replaced with %s[0x%08X - 0x%08X]",
- proc->image_path, proc->pid, replaced.path, replaced.map_start,
- replaced.map_end, desc.path, desc.map_start, desc.map_end);
- g_free(replaced.path);
- }
-
- T(PROC_MMAP, "memcheck: %s[pid=%u] %s is mapped: " TARGET_FMT_lx " - " TARGET_FMT_lx " + " TARGET_FMT_lx "\n",
- proc->image_path, proc->pid, path, vstart, vend, exec_offset);
-}
-
-void
-memcheck_unmap(target_ulong vstart, target_ulong vend)
-{
- MMRangeDesc desc;
- ProcDesc* proc = get_current_process();
- if (proc == NULL) {
- ME("memcheck: UNMAP(0x%08X, 0x%08X) Unable to look up current process. Current tid=%u",
- vstart, vend, current_tid);
- return;
- }
-
- if (mmrangemap_pull(&proc->mmrange_map, vstart, vend, &desc)) {
- return;
- }
-
- if (desc.map_start >= vstart && desc.map_end <= vend) {
- /* Entire mapping has been deleted. */
- T(PROC_MMAP, "memcheck: %s[pid=%u] %s is unmapped: [" TARGET_FMT_lx " - " TARGET_FMT_lx " + " TARGET_FMT_lx "]\n",
- proc->image_path, proc->pid, desc.path, vstart, vend, desc.exec_offset);
- g_free(desc.path);
- return;
- }
-
- /* This can be first stage of "remap" request, when part of the existing
- * mapping has been unmapped. If that's so, lets cut unmapped part from the
- * block that we just pulled, and add whatever's left back to the map. */
- T(PROC_MMAP, "memcheck: REMAP(" TARGET_FMT_lx ", " TARGET_FMT_lx " + " TARGET_FMT_lx ") -> (" TARGET_FMT_lx ", " TARGET_FMT_lx ")\n",
- desc.map_start, desc.map_end, desc.exec_offset, vstart, vend);
- if (desc.map_start == vstart) {
- /* We cut part from the beginning. Add the tail back. */
- desc.exec_offset += vend - desc.map_start;
- desc.map_start = vend;
- mmrangemap_insert(&proc->mmrange_map, &desc, NULL);
- } else if (desc.map_end == vend) {
- /* We cut part from the tail. Add the beginning back. */
- desc.map_end = vstart;
- mmrangemap_insert(&proc->mmrange_map, &desc, NULL);
- } else {
- /* We cut piece in the middle. */
- MMRangeDesc tail;
- tail.map_start = vend;
- tail.map_end = desc.map_end;
- tail.exec_offset = vend - desc.map_start + desc.exec_offset;
- tail.path = g_malloc(strlen(desc.path) + 1);
- strcpy(tail.path, desc.path);
- mmrangemap_insert(&proc->mmrange_map, &tail, NULL);
- desc.map_end = vstart;
- mmrangemap_insert(&proc->mmrange_map, &desc, NULL);
- }
-}
diff --git a/android/qemu/memcheck/memcheck_proc_management.h b/android/qemu/memcheck/memcheck_proc_management.h
deleted file mode 100644
index 2192ae9..0000000
--- a/android/qemu/memcheck/memcheck_proc_management.h
+++ /dev/null
@@ -1,321 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of structures, routines, etc. related to process
- * management in memchecker framework.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
-
-#include "qemu/queue.h"
-#include "android/qemu/memcheck/memcheck_common.h"
-#include "android/qemu/memcheck/memcheck_malloc_map.h"
-#include "android/qemu/memcheck/memcheck_mmrange_map.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// =============================================================================
-// Process management structures
-// =============================================================================
-
-/* Describes a process that is monitored by memchecker framework. */
-typedef struct ProcDesc {
- /* Map of memory blocks allocated in context of this process. */
- AllocMap alloc_map;
-
- /* Map of memory mapped modules loaded in context of this process. */
- MMRangeMap mmrange_map;
-
- /* Descriptor's entry in the global process list. */
- QLIST_ENTRY(ProcDesc) global_entry;
-
- /* List of threads running in context of this process. */
- QLIST_HEAD(threads, ThreadDesc) threads;
-
- /* Path to the process' image file. */
- char* image_path;
-
- /* Process id. */
- uint32_t pid;
-
- /* Parent process id. */
- uint32_t parent_pid;
-
- /* Misc. process flags. See PROC_FLAG_XXX */
- uint32_t flags;
-} ProcDesc;
-
-/* Process is executing. */
-#define PROC_FLAG_EXECUTING 0x00000001
-/* Process is exiting. */
-#define PROC_FLAG_EXITING 0x00000002
-/* ProcDesc->image_path has been replaced during process execution. */
-#define PROC_FLAG_IMAGE_PATH_REPLACED 0x00000004
-/* libc.so instance has been initialized for this process. */
-#define PROC_FLAG_LIBC_INITIALIZED 0x00000008
-
-/* Entry in the thread's calling stack array. */
-typedef struct ThreadCallStackEntry {
- /* Guest PC where call has been made. */
- target_ulong call_address;
- /* Guest PC where call has been made, relative to the beginning of the
- * mapped module that contains call_address. */
- target_ulong call_address_rel;
- /* Guest PC where call will return. */
- target_ulong ret_address;
- /* Guest PC where call will return, relative to the beginning of the
- * mapped module that contains ret_address. */
- target_ulong ret_address_rel;
- /* Path to the image file of the module containing call_address. */
- char* module_path;
-} ThreadCallStackEntry;
-
-/* Describes a thread that is monitored by memchecker framework. */
-typedef struct ThreadDesc {
- /* Descriptor's entry in the global thread list. */
- QLIST_ENTRY(ThreadDesc) global_entry;
-
- /* Descriptor's entry in the process' thread list. */
- QLIST_ENTRY(ThreadDesc) proc_entry;
-
- /* Descriptor of the process this thread belongs to. */
- ProcDesc* process;
-
- /* Calling stack for this thread. */
- ThreadCallStackEntry* call_stack;
-
- /* Number of entries in the call_stack array. */
- uint32_t call_stack_count;
-
- /* Maximum number of entries that can fit into call_stack buffer. */
- uint32_t call_stack_max;
-
- /* Thread id. */
- uint32_t tid;
-} ThreadDesc;
-
-// =============================================================================
-// Inlines
-// =============================================================================
-
-/* Checks if process has been forked, rather than created from a "fresh" PID.
- * Param:
- * proc - Descriptor for the process to check.
- * Return:
- * boolean: 1 if process has been forked, or 0 if it was
- * created from a "fresh" PID.
- */
-static inline int
-procdesc_is_forked(const ProcDesc* proc)
-{
- return proc->parent_pid != 0;
-}
-
-/* Checks if process is executing.
- * Param:
- * proc - Descriptor for the process to check.
- * Return:
- * boolean: 1 if process is executing, or 0 if it is not executing.
- */
-static inline int
-procdesc_is_executing(const ProcDesc* proc)
-{
- return (proc->flags & PROC_FLAG_EXECUTING) != 0;
-}
-
-/* Checks if process is exiting.
- * Param:
- * proc - Descriptor for the process to check.
- * Return:
- * boolean: 1 if process is exiting, or 0 if it is still alive.
- */
-static inline int
-procdesc_is_exiting(const ProcDesc* proc)
-{
- return (proc->flags & PROC_FLAG_EXITING) != 0;
-}
-
-/* Checks if process has initialized its libc.so instance.
- * Param:
- * proc - Descriptor for the process to check.
- * Return:
- * boolean: 1 if process has initialized its libc.so instance, or 0 otherwise.
- */
-static inline int
-procdesc_is_libc_initialized(const ProcDesc* proc)
-{
- return (proc->flags & PROC_FLAG_LIBC_INITIALIZED) != 0;
-}
-
-/* Checks if process image path has been replaced.
- * Param:
- * proc - Descriptor for the process to check.
- * Return:
- * boolean: 1 if process image path has been replaced,
- * or 0 if it was not replaced.
- */
-static inline int
-procdesc_is_image_path_replaced(const ProcDesc* proc)
-{
- return (proc->flags & PROC_FLAG_IMAGE_PATH_REPLACED) != 0;
-}
-
-// =============================================================================
-// Process management API
-// =============================================================================
-
-/* Gets thread descriptor for the current thread.
- * Return:
- * Found thread descriptor, or NULL if thread descriptor has not been found.
- */
-ThreadDesc* get_current_thread(void);
-
-/* Initializes process management API. */
-void memcheck_init_proc_management(void);
-
-/* Gets process descriptor for the current process.
- * Return:
- * Process descriptor for the current process, or NULL, if process descriptor
- * has not been found.
- */
-ProcDesc* get_current_process(void);
-
-/* Finds process descriptor for a process id.
- * Param:
- * pid - Process ID to look up process descriptor for.
- * Return:
- * Process descriptor for the PID, or NULL, if process descriptor
- * has not been found.
- */
-ProcDesc* get_process_from_pid(uint32_t pid);
-
-/* Inserts new (or replaces existing) entry in the allocation descriptors map
- * for the given process.
- * See allocmap_insert for more information on this routine, its parameters
- * and returning value.
- * Param:
- * proc - Process descriptor where to add new allocation entry info.
- */
-static inline RBTMapResult
-procdesc_add_malloc(ProcDesc* proc,
- const MallocDescEx* desc,
- MallocDescEx* replaced)
-{
- return allocmap_insert(&proc->alloc_map, desc, replaced);
-}
-
-/* Finds an entry in the allocation descriptors map for the given process,
- * matching given address range.
- * See allocmap_find for more information on this routine, its parameters
- * and returning value.
- * Param:
- * proc - Process descriptor where to find an allocation entry.
- */
-static inline MallocDescEx*
-procdesc_find_malloc_for_range(ProcDesc* proc,
- target_ulong address,
- uint32_t block_size)
-{
- return allocmap_find(&proc->alloc_map, address, block_size);
-}
-
-/* Finds an entry in the allocation descriptors map for the given process,
- * matching given address.
- * See allocmap_find for more information on this routine, its parameters
- * and returning value.
- * Param:
- * proc - Process descriptor where to find an allocation entry.
- */
-static inline MallocDescEx*
-procdesc_find_malloc(ProcDesc* proc, target_ulong address)
-{
- return procdesc_find_malloc_for_range(proc, address, 1);
-}
-
-/* Pulls (finds and removes) an entry from the allocation descriptors map for
- * the given process, matching given address.
- * See allocmap_pull for more information on this routine, its parameters
- * and returning value.
- * Param:
- * proc - Process descriptor where to pull an allocation entry from.
- */
-static inline int
-procdesc_pull_malloc(ProcDesc* proc, target_ulong address, MallocDescEx* pulled)
-{
- return allocmap_pull(&proc->alloc_map, address, pulled);
-}
-
-/* Empties allocation descriptors map for the process.
- * Param:
- * proc - Process to empty allocation map for.
- * Return:
- * Number of entries deleted from the allocation map.
- */
-static inline int
-procdesc_empty_alloc_map(ProcDesc* proc)
-{
- return allocmap_empty(&proc->alloc_map);
-}
-
-/* Finds mmapping entry for the given address in the given process.
- * Param:
- * proc - Descriptor of the process where to look for an entry.
- * addr - Address in the guest space for which to find an entry.
- * Return:
- * Mapped entry, or NULL if no mapping for teh given address exists in the
- * process address space.
- */
-static inline MMRangeDesc*
-procdesc_find_mapentry(const ProcDesc* proc, target_ulong addr)
-{
- return mmrangemap_find(&proc->mmrange_map, addr, addr + 1);
-}
-
-/* Gets module descriptor for the given address.
- * Param:
- * proc - Descriptor of the process where to look for a module.
- * addr - Address in the guest space for which to find a module descriptor.
- * Return:
- * module descriptor for the module containing the given address, or NULL if no
- * such module has been found in the process' map of mmaped modules.
- */
-static inline const MMRangeDesc*
-procdesc_get_range_desc(const ProcDesc* proc, target_ulong addr)
-{
- return procdesc_find_mapentry(proc, addr);
-}
-
-/* Gets name of the module mmaped in context of the given process for the
- * given address.
- * Param:
- * proc - Descriptor of the process where to look for a module.
- * addr - Address in the guest space for which to find a module.
- * Return:
- * Image path to the module containing the given address, or NULL if no such
- * module has been found in the process' map of mmaped modules.
- */
-static inline const char*
-procdesc_get_module_path(const ProcDesc* proc, target_ulong addr)
-{
- MMRangeDesc* rdesc = procdesc_find_mapentry(proc, addr);
- return rdesc != NULL ? rdesc->path : NULL;
-}
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
diff --git a/android/qemu/memcheck/memcheck_util.c b/android/qemu/memcheck/memcheck_util.c
deleted file mode 100644
index e7f8743..0000000
--- a/android/qemu/memcheck/memcheck_util.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of utility routines for memchecker framework.
- */
-
-#include "stdio.h"
-#include "qemu-common.h"
-#include "android/utils/path.h"
-#include "cpu.h"
-#include "exec/cpu-all.h"
-
-#include "android/qemu/memcheck/memcheck_util.h"
-#include "android/qemu/memcheck/memcheck_proc_management.h"
-#include "android/qemu/memcheck/memcheck_logging.h"
-
-#include "exec/softmmu_exec.h"
-
-/* Gets symblos file path for the given module.
- * Param:
- * module_path - Path to the module to get sympath for.
- * sym_path - Buffer, where to save path to the symbols file path for the givem
- * module. NOTE: This buffer must be big enough to contain the largest
- * path possible.
- * max_char - Character size of the buffer addressed by sym_path parameter.
- * Return:
- * 0 on success, or -1 if symbols file has not been found, or sym_path buffer
- * was too small to contain entire path.
- */
-static int
-get_sym_path(const char* module_path, char* sym_path, size_t max_char)
-{
- const char* sym_path_root = getenv("ANDROID_PROJECT_OUT");
- if (sym_path_root == NULL || strlen(sym_path_root) >= max_char) {
- return -1;
- }
-
- strcpy(sym_path, sym_path_root);
- max_char -= strlen(sym_path_root);
- if (sym_path[strlen(sym_path)-1] != PATH_SEP_C) {
- strcat(sym_path, PATH_SEP);
- max_char--;
- }
- if (strlen("symbols") >= max_char) {
- return -1;
- }
- strcat(sym_path, "symbols");
- max_char -= strlen("symbols");
- if (strlen(module_path) >= max_char) {
- return -1;
- }
- strcat(sym_path, module_path);
-
- /* Sometimes symbol file for a module is placed into a parent symbols
- * directory. Lets iterate through all parent sym dirs, until we find
- * sym file, or reached symbols root. */
- while (!path_exists(sym_path)) {
- /* Select module name. */
- char* name = strrchr(sym_path, PATH_SEP_C);
- assert(name != NULL);
- *name = '\0';
- /* Parent directory. */
- char* parent = strrchr(sym_path, PATH_SEP_C);
- assert(parent != NULL);
- *parent = '\0';
- if (strcmp(sym_path, sym_path_root) == 0) {
- return -1;
- }
- *parent = PATH_SEP_C;
- memmove(parent+1, name + 1, strlen(name + 1) + 1);
- }
-
- return 0;
-}
-
-// =============================================================================
-// Transfering data between guest and emulator address spaces.
-// =============================================================================
-
-void
-memcheck_get_guest_buffer(void* qemu_address,
- target_ulong guest_address,
- size_t buffer_size)
-{
- /* Byte-by-byte copying back and forth between guest's and emulator's memory
- * appears to be efficient enough (at least on small blocks used in
- * memchecker), so there is no real need to optimize it by aligning guest
- * buffer to 32 bits and use ld/stl_user instead of ld/stub_user to
- * read / write guest's memory. */
- while (buffer_size) {
- *(uint8_t*)qemu_address = cpu_ldub_user(cpu_single_env, guest_address);
- qemu_address = (uint8_t*)qemu_address + 1;
- guest_address++;
- buffer_size--;
- }
-}
-
-void
-memcheck_set_guest_buffer(target_ulong guest_address,
- const void* qemu_address,
- size_t buffer_size)
-{
- while (buffer_size) {
- cpu_stb_user(cpu_single_env, guest_address, *(uint8_t*)qemu_address);
- guest_address++;
- qemu_address = (uint8_t*)qemu_address + 1;
- buffer_size--;
- }
-}
-
-size_t
-memcheck_get_guest_string(char* qemu_str,
- target_ulong guest_str,
- size_t qemu_buffer_size)
-{
- size_t copied = 0;
-
- if (qemu_buffer_size > 1) {
- for (copied = 0; copied < qemu_buffer_size - 1; copied++) {
- qemu_str[copied] = cpu_ldub_user(cpu_single_env, guest_str + copied);
- if (qemu_str[copied] == '\0') {
- return copied;
- }
- }
- }
- qemu_str[copied] = '\0';
- return copied;
-}
-
-size_t
-memcheck_get_guest_kernel_string(char* qemu_str,
- target_ulong guest_str,
- size_t qemu_buffer_size)
-{
- size_t copied = 0;
-
- if (qemu_buffer_size > 1) {
- for (copied = 0; copied < qemu_buffer_size - 1; copied++) {
- qemu_str[copied] = cpu_ldub_kernel(cpu_single_env, guest_str + copied);
- if (qemu_str[copied] == '\0') {
- return copied;
- }
- }
- }
- qemu_str[copied] = '\0';
- return copied;
-}
-
-// =============================================================================
-// Helpers for transfering memory allocation information.
-// =============================================================================
-
-void
-memcheck_fail_alloc(target_ulong guest_address)
-{
- cpu_stl_user(cpu_single_env, ALLOC_RES_ADDRESS(guest_address), 0);
-}
-
-void
-memcheck_fail_free(target_ulong guest_address)
-{
- cpu_stl_user(cpu_single_env, FREE_RES_ADDRESS(guest_address), 0);
-}
-
-void
-memcheck_fail_query(target_ulong guest_address)
-{
- cpu_stl_user(cpu_single_env, QUERY_RES_ADDRESS(guest_address), 0);
-}
-
-// =============================================================================
-// Misc. utility routines.
-// =============================================================================
-
-void
-invalidate_tlb_cache(target_ulong start, target_ulong end)
-{
- target_ulong index = (start >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- const target_ulong to = ((end - 1) >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE-1);
- for (; index <= to; index++, start += TARGET_PAGE_SIZE) {
- target_ulong tlb_addr = cpu_single_env->tlb_table[1][index].addr_write;
- if ((start & TARGET_PAGE_MASK) ==
- (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- cpu_single_env->tlb_table[1][index].addr_write ^= TARGET_PAGE_MASK;
- }
- tlb_addr = cpu_single_env->tlb_table[1][index].addr_read;
- if ((start & TARGET_PAGE_MASK) ==
- (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- cpu_single_env->tlb_table[1][index].addr_read ^= TARGET_PAGE_MASK;
- }
- }
-}
-
-void
-memcheck_dump_malloc_desc(const MallocDescEx* desc_ex,
- int print_flags,
- int print_proc_info)
-{
- const MallocDesc* desc = &desc_ex->malloc_desc;
- printf(" User range: 0x%08X - 0x%08X, %u bytes\n",
- (uint32_t)mallocdesc_get_user_ptr(desc),
- (uint32_t)mallocdesc_get_user_ptr(desc) + desc->requested_bytes,
- desc->requested_bytes);
- printf(" Prefix guarding area: " TARGET_FMT_lx " - " TARGET_FMT_lx ", %u bytes\n",
- desc->ptr, desc->ptr + desc->prefix_size, desc->prefix_size);
- printf(" Suffix guarding area: " TARGET_FMT_lx " - " TARGET_FMT_lx ", %u bytes\n",
- mallocdesc_get_user_alloc_end(desc),
- mallocdesc_get_user_alloc_end(desc) + desc->suffix_size,
- desc->suffix_size);
- if (print_proc_info) {
- ProcDesc* proc = get_process_from_pid(desc->allocator_pid);
- if (proc != NULL) {
- printf(" Allocated by: %s[pid=%u]\n",
- proc->image_path, proc->pid);
- }
- }
- if (print_flags) {
- printf(" Flags: 0x%08X\n", desc_ex->flags);
- }
-}
-
-int
-memcheck_get_address_info(target_ulong abs_pc,
- const MMRangeDesc* rdesc,
- Elf_AddressInfo* info,
- ELFF_HANDLE* elff_handle)
-{
- char sym_path[MAX_PATH];
- ELFF_HANDLE handle;
-
- if (get_sym_path(rdesc->path, sym_path, MAX_PATH)) {
- return 1;
- }
-
- handle = elff_init(sym_path);
- if (handle == NULL) {
- return -1;
- }
-
- if (!elff_is_exec(handle)) {
- /* Debug info for shared library is created for the relative address. */
- target_ulong rel_pc = mmrangedesc_get_module_offset(rdesc, abs_pc);
- if (elff_get_pc_address_info(handle, rel_pc, info)) {
- elff_close(handle);
- return -1;
- }
- } else {
- /* Debug info for executables is created for the absoulte address. */
- if (elff_get_pc_address_info(handle, abs_pc, info)) {
- elff_close(handle);
- return -1;
- }
- }
-
- *elff_handle = handle;
- return 0;
-}
diff --git a/android/qemu/memcheck/memcheck_util.h b/android/qemu/memcheck/memcheck_util.h
deleted file mode 100644
index f69f427..0000000
--- a/android/qemu/memcheck/memcheck_util.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of utility routines for memchecker framework.
- */
-
-#ifndef ANDROID_QEMU_MEMCHECK_MEMCHECK_UTIL_H
-#define ANDROID_QEMU_MEMCHECK_MEMCHECK_UTIL_H
-
-#include "android/qemu/memcheck/memcheck_common.h"
-#include "elff/elff_api.h"
-#include "cpu.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// =============================================================================
-// Transfering data between guest and emulator address spaces.
-// =============================================================================
-
-/* Copies buffer residing in the guest's virtual address space to a buffer
- * in the emulator's address space.
- * Param:
- * guest_address - Address of the bufer in guest's virtual address space.
- * qemu_address - Address of the bufer in the emulator's address space.
- * buffer_size - Byte size of the guest's buffer.
- */
-void memcheck_get_guest_buffer(void* qemu_address,
- target_ulong guest_address,
- size_t buffer_size);
-
-/* Copies buffer residing in the emulator's address space to a buffer in the
- * guest's virtual address space.
- * Param:
- * qemu_address - Address of the bufer in the emulator's address space.
- * guest_address - Address of the bufer in guest's virtual address space.
- * buffer_size - Byte size of the emualtor's buffer.
- */
-void memcheck_set_guest_buffer(target_ulong guest_address,
- const void* qemu_address,
- size_t buffer_size);
-
-/* Copies zero-terminated string residing in the guest's virtual address space
- * to a string buffer in emulator's address space.
- * Param:
- * qemu_str - Address of the string bufer in the emulator's address space.
- * guest_str - Address of the string in guest's virtual address space.
- * qemu_buffer_size - Size of the emulator's string buffer.
- * Return
- * Length of the string that has been copied.
- */
-size_t memcheck_get_guest_string(char* qemu_str,
- target_ulong guest_str,
- size_t qemu_buffer_size);
-
-/* Copies zero-terminated string residing in the guest's kernel address space
- * to a string buffer in emulator's address space.
- * Param:
- * qemu_str - Address of the string bufer in the emulator's address space.
- * guest_str - Address of the string in guest's kernel address space.
- * qemu_buffer_size - Size of the emulator's string buffer.
- * Return
- * Length of the string that has been copied.
- */
-size_t memcheck_get_guest_kernel_string(char* qemu_str,
- target_ulong guest_str,
- size_t qemu_buffer_size);
-
-// =============================================================================
-// Helpers for transfering memory allocation information.
-// =============================================================================
-
-/* Copies memory allocation descriptor from the guest's address space to the
- * emulator's memory.
- * Param:
- * qemu_address - Descriptor address in the emulator's address space where to
- * copy descriptor.
- * guest_address - Descriptor address in the guest's address space.
- */
-static inline void
-memcheck_get_malloc_descriptor(MallocDesc* qemu_address,
- target_ulong guest_address)
-{
- memcheck_get_guest_buffer(qemu_address, guest_address, sizeof(MallocDesc));
-}
-
-/* Copies memory allocation descriptor from the emulator's memory to the guest's
- * address space.
- * Param:
- * guest_address - Descriptor address in the guest's address space.
- * qemu_address - Descriptor address in the emulator's address space where to
- * copy descriptor.
- */
-static inline void
-memcheck_set_malloc_descriptor(target_ulong guest_address,
- const MallocDesc* qemu_address)
-{
- memcheck_set_guest_buffer(guest_address, qemu_address, sizeof(MallocDesc));
-}
-
-/* Copies memory free descriptor from the guest's address space to the
- * emulator's memory.
- * Param:
- * qemu_address - Descriptor address in the emulator's address space where to
- * copy descriptor.
- * guest_address - Descriptor address in the guest's address space.
- */
-static inline void
-memcheck_get_free_descriptor(MallocFree* qemu_address,
- target_ulong guest_address)
-{
- memcheck_get_guest_buffer(qemu_address, guest_address, sizeof(MallocFree));
-}
-
-/* Copies memory allocation query descriptor from the guest's address space to
- * the emulator's memory.
- * Param:
- * guest_address - Descriptor address in the guest's address space.
- * qemu_address - Descriptor address in the emulator's address space where to
- * copy descriptor.
- */
-static inline void
-memcheck_get_query_descriptor(MallocDescQuery* qemu_address,
- target_ulong guest_address)
-{
- memcheck_get_guest_buffer(qemu_address, guest_address,
- sizeof(MallocDescQuery));
-}
-
-/* Fails allocation request (TRACE_DEV_REG_MALLOC event).
- * Allocation request failure is reported by zeroing 'libc_pid' filed in the
- * allocation descriptor in the guest's address space.
- * Param:
- * guest_address - Allocation descriptor address in the guest's address space,
- * where to record failure.
- */
-void memcheck_fail_alloc(target_ulong guest_address);
-
-/* Fails free request (TRACE_DEV_REG_FREE_PTR event).
- * Free request failure is reported by zeroing 'libc_pid' filed in the free
- * descriptor in the guest's address space.
- * Param:
- * guest_address - Free descriptor address in the guest's address space, where
- * to record failure.
- */
-void memcheck_fail_free(target_ulong guest_address);
-
-/* Fails memory allocation query request (TRACE_DEV_REG_QUERY_MALLOC event).
- * Query request failure is reported by zeroing 'libc_pid' filed in the query
- * descriptor in the guest's address space.
- * Param:
- * guest_address - Query descriptor address in the guest's address space, where
- * to record failure.
- */
-void memcheck_fail_query(target_ulong guest_address);
-
-// =============================================================================
-// Misc. utility routines.
-// =============================================================================
-
-/* Converts PC address in the translated block to a corresponded PC address in
- * the guest address space.
- * Param:
- * tb_pc - PC address in the translated block.
- * Return:
- * Corresponded PC address in the guest address space on success, or NULL if
- * conversion has failed.
- */
-static inline target_ulong
-memcheck_tpc_to_gpc(target_ulong tb_pc)
-{
- const TranslationBlock* tb = tb_find_pc(tb_pc);
- return tb != NULL ? tb_search_guest_pc_from_tb_pc(tb, tb_pc) : 0;
-}
-
-/* Invalidates TLB table pages that contain given memory range.
- * This routine is called after new entry is inserted into allocation map, so
- * every access to the allocated block will cause __ld/__stx_mmu to be called.
- * Param:
- * start - Beginning of the allocated block to invalidate pages for.
- * end - End of (past one byte after) the allocated block to invalidate pages
- * for.
- */
-void invalidate_tlb_cache(target_ulong start, target_ulong end);
-
-/* Gets routine, file path and line number information for a PC address in the
- * given module.
- * Param:
- * abs_pc - PC address.
- * rdesc - Mapped memory range descriptor for the module containing abs_pc.
- * info - Upon successful return will contain routine, file path and line
- * information for the given PC address in the given module.
- * NOTE: Pathnames, saved into this structure are contained in mapped
- * sections of the symbols file for the module addressed by module_path.
- * Thus, pathnames are accessible only while elff_handle returned from this
- * routine remains opened.
- * NOTE: each successful call to this routine requires the caller to call
- * elff_free_pc_address_info for Elf_AddressInfo structure.
- * elff_handle - Upon successful return will contain a handle to the ELFF API
- * that wraps symbols file for the module, addressed by module_path. The
- * handle must remain opened for as long as pathnames in the info structure
- * are accessed, and must be eventually closed via call to elff_close.
- * Return:
- * 0 on success, 1, if symbols file for the module has not been found, or -1 on
- * other failures. If a failure is returned from this routine content of info
- * and elff_handle parameters is undefined.
- */
-int memcheck_get_address_info(target_ulong abs_pc,
- const MMRangeDesc* rdesc,
- Elf_AddressInfo* info,
- ELFF_HANDLE* elff_handle);
-
-/* Dumps content of an allocation descriptor to stdout.
- * Param desc - Allocation descriptor to dump.
- * print_flags - If 1, flags field of the descriptor will be dumped to stdout.
- * If 0, flags filed will not be dumped.
- * print_proc_info - If 1, allocator's process information for the descriptor
- * will be dumped to stdout. If 0, allocator's process information will
- * not be dumped.
- */
-void memcheck_dump_malloc_desc(const MallocDescEx* desc,
- int print_flags,
- int print_proc_info);
-
-#ifdef __cplusplus
-}; /* end of extern "C" */
-#endif
-
-#endif // ANDROID_QEMU_MEMCHECK_MEMCHECK_UTIL_H
diff --git a/cputlb.c b/cputlb.c
index b59f158..84e382d 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -22,10 +22,6 @@
#include "exec/exec-all.h"
#include "exec/cputlb.h"
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck_api.h"
-#endif
-
/* statistics */
int tlb_flush_count;
@@ -299,38 +295,6 @@
} else {
te->addr_write = -1;
}
-
-#ifdef CONFIG_ANDROID_MEMCHECK
- /*
- * If we have memchecker running, we need to make sure that page, cached
- * into TLB as the result of this operation will comply with our requirement
- * to cause __ld/__stx_mmu being called for memory access on the pages
- * containing memory blocks that require access violation checks.
- *
- * We need to check with memory checker if we should invalidate this page
- * iff:
- * - Memchecking is enabled.
- * - Page that's been cached belongs to the user space.
- * - Request to cache this page didn't come from softmmu. We're covered
- * there, because after page was cached here we will invalidate it in
- * the __ld/__stx_mmu wrapper.
- * - Cached page belongs to RAM, not I/O area.
- * - Page is cached for read, or write access.
- */
-#if 0
- if (memcheck_instrument_mmu && mmu_idx == 1 &&
- (pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
- (prot & (PAGE_READ | PAGE_WRITE)) &&
- memcheck_is_checked(vaddr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) {
- if (prot & PAGE_READ) {
- te->addr_read ^= TARGET_PAGE_MASK;
- }
- if (prot & PAGE_WRITE) {
- te->addr_write ^= TARGET_PAGE_MASK;
- }
- }
-#endif
-#endif // CONFIG_ANDROID_MEMCHECK
}
/* NOTE: this function can trigger an exception */
diff --git a/distrib/elff/README.TXT b/distrib/elff/README.TXT
deleted file mode 100644
index 915787a..0000000
--- a/distrib/elff/README.TXT
+++ /dev/null
@@ -1,3 +0,0 @@
-This is a small library used to parse the symbol information inside of
-ELF binaries. It is used by the Android emulator "memcheck" feature to
-convert guest addresses into symbolic function names.
diff --git a/distrib/elff/elff/dwarf.h b/distrib/elff/elff/dwarf.h
deleted file mode 100644
index 7279321..0000000
--- a/distrib/elff/elff/dwarf.h
+++ /dev/null
@@ -1,1055 +0,0 @@
-/*
- Copyright (C) 2000,2001,2003,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
- Portions Copyright 2002,2007 Sun Microsystems, Inc. All rights reserved.
- Portions Copyright 2007-2009 David Anderson. All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of version 2.1 of the GNU Lesser General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it would be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- Further, this software is distributed without any warranty that it is
- free of the rightful claim of any third person regarding infringement
- or the like. Any license provided herein, whether implied or
- otherwise, applies only to this software file. Patent licenses, if
- any, provided herein do not apply to combinations of this program with
- other software, or any other product whatsoever.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, write the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
- USA.
-
- Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
- Mountain View, CA 94043, or:
-
- http://www.sgi.com
-
- For further information regarding this notice, see:
-
- http://oss.sgi.com/projects/GenInfo/NoticeExplan
-
-*/
-
-
-#ifndef __DWARF_H
-#define __DWARF_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- dwarf.h DWARF debugging information values
- $Revision: 1.41 $ $Date: 2006/04/17 00:09:56 $
-
- The comment "DWARF3" appears where there are
- new entries from DWARF3 as of 2004, "DWARF3f"
- where there are new entries as of the November 2005
- public review document and other comments apply
- where extension entries appear.
-
- Extensions part of DWARF4 are marked DWARF4.
-
- A few extension names have omitted the 'vendor id'
- (See chapter 7, "Vendor Extensibility"). Please
- always use a 'vendor id' string in extension names.
-
- Vendors should use a vendor string in names and
- whereever possible avoid duplicating values used by
- other vendor extensions
-
-*/
-
-
-#define DW_TAG_array_type 0x01
-#define DW_TAG_class_type 0x02
-#define DW_TAG_entry_point 0x03
-#define DW_TAG_enumeration_type 0x04
-#define DW_TAG_formal_parameter 0x05
-#define DW_TAG_imported_declaration 0x08
-#define DW_TAG_label 0x0a
-#define DW_TAG_lexical_block 0x0b
-#define DW_TAG_member 0x0d
-#define DW_TAG_pointer_type 0x0f
-#define DW_TAG_reference_type 0x10
-#define DW_TAG_compile_unit 0x11
-#define DW_TAG_string_type 0x12
-#define DW_TAG_structure_type 0x13
-#define DW_TAG_subroutine_type 0x15
-#define DW_TAG_typedef 0x16
-#define DW_TAG_union_type 0x17
-#define DW_TAG_unspecified_parameters 0x18
-#define DW_TAG_variant 0x19
-#define DW_TAG_common_block 0x1a
-#define DW_TAG_common_inclusion 0x1b
-#define DW_TAG_inheritance 0x1c
-#define DW_TAG_inlined_subroutine 0x1d
-#define DW_TAG_module 0x1e
-#define DW_TAG_ptr_to_member_type 0x1f
-#define DW_TAG_set_type 0x20
-#define DW_TAG_subrange_type 0x21
-#define DW_TAG_with_stmt 0x22
-#define DW_TAG_access_declaration 0x23
-#define DW_TAG_base_type 0x24
-#define DW_TAG_catch_block 0x25
-#define DW_TAG_const_type 0x26
-#define DW_TAG_constant 0x27
-#define DW_TAG_enumerator 0x28
-#define DW_TAG_file_type 0x29
-#define DW_TAG_friend 0x2a
-#define DW_TAG_namelist 0x2b
- /* Early releases of this header had the following
- misspelled with a trailing 's' */
-#define DW_TAG_namelist_item 0x2c /* DWARF3/2 spelling */
-#define DW_TAG_namelist_items 0x2c /* SGI misspelling/typo */
-#define DW_TAG_packed_type 0x2d
-#define DW_TAG_subprogram 0x2e
- /* The DWARF2 document had two spellings of the following
- two TAGs, DWARF3 specifies the longer spelling. */
-#define DW_TAG_template_type_parameter 0x2f /* DWARF3/2 spelling*/
-#define DW_TAG_template_type_param 0x2f /* DWARF2 spelling*/
-#define DW_TAG_template_value_parameter 0x30 /* DWARF3/2 spelling*/
-#define DW_TAG_template_value_param 0x30 /* DWARF2 spelling*/
-#define DW_TAG_thrown_type 0x31
-#define DW_TAG_try_block 0x32
-#define DW_TAG_variant_part 0x33
-#define DW_TAG_variable 0x34
-#define DW_TAG_volatile_type 0x35
-#define DW_TAG_dwarf_procedure 0x36 /* DWARF3 */
-#define DW_TAG_restrict_type 0x37 /* DWARF3 */
-#define DW_TAG_interface_type 0x38 /* DWARF3 */
-#define DW_TAG_namespace 0x39 /* DWARF3 */
-#define DW_TAG_imported_module 0x3a /* DWARF3 */
-#define DW_TAG_unspecified_type 0x3b /* DWARF3 */
-#define DW_TAG_partial_unit 0x3c /* DWARF3 */
-#define DW_TAG_imported_unit 0x3d /* DWARF3 */
- /* Do not use DW_TAG_mutable_type */
-#define DW_TAG_mutable_type 0x3e /* Withdrawn from DWARF3 by DWARF3f. */
-#define DW_TAG_condition 0x3f /* DWARF3f */
-#define DW_TAG_shared_type 0x40 /* DWARF3f */
-#define DW_TAG_type_unit 0x41 /* DWARF4 */
-#define DW_TAG_rvalue_reference_type 0x42 /* DWARF4 */
-#define DW_TAG_template_alias 0x43 /* DWARF4 */
-#define DW_TAG_lo_user 0x4080
-
-#define DW_TAG_MIPS_loop 0x4081
-
-/* HP extensions: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz */
-#define DW_TAG_HP_array_descriptor 0x4090 /* HP */
-
-/* GNU extensions. The first 3 missing the GNU_. */
-#define DW_TAG_format_label 0x4101 /* GNU. Fortran. */
-#define DW_TAG_function_template 0x4102 /* GNU. For C++ */
-#define DW_TAG_class_template 0x4103 /* GNU. For C++ */
-#define DW_TAG_GNU_BINCL 0x4104 /* GNU */
-#define DW_TAG_GNU_EINCL 0x4105 /* GNU */
-
-/* ALTIUM extensions */
- /* DSP-C/Starcore __circ qualifier */
-#define DW_TAG_ALTIUM_circ_type 0x5101 /* ALTIUM */
- /* Starcore __mwa_circ qualifier */
-#define DW_TAG_ALTIUM_mwa_circ_type 0x5102 /* ALTIUM */
- /* Starcore __rev_carry qualifier */
-#define DW_TAG_ALTIUM_rev_carry_type 0x5103 /* ALTIUM */
- /* M16 __rom qualifier */
-#define DW_TAG_ALTIUM_rom 0x5111 /* ALTIUM */
-
-/* The following 3 are extensions to support UPC */
-#define DW_TAG_upc_shared_type 0x8765 /* UPC */
-#define DW_TAG_upc_strict_type 0x8766 /* UPC */
-#define DW_TAG_upc_relaxed_type 0x8767 /* UPC */
-
-/* PGI (STMicroelectronics) extensions. */
-#define DW_TAG_PGI_kanji_type 0xa000 /* PGI */
-#define DW_TAG_PGI_interface_block 0xa020 /* PGI */
-/* The following are SUN extensions */
-#define DW_TAG_SUN_function_template 0x4201 /* SUN */
-#define DW_TAG_SUN_class_template 0x4202 /* SUN */
-#define DW_TAG_SUN_struct_template 0x4203 /* SUN */
-#define DW_TAG_SUN_union_template 0x4204 /* SUN */
-#define DW_TAG_SUN_indirect_inheritance 0x4205 /* SUN */
-#define DW_TAG_SUN_codeflags 0x4206 /* SUN */
-#define DW_TAG_SUN_memop_info 0x4207 /* SUN */
-#define DW_TAG_SUN_omp_child_func 0x4208 /* SUN */
-#define DW_TAG_SUN_rtti_descriptor 0x4209 /* SUN */
-#define DW_TAG_SUN_dtor_info 0x420a /* SUN */
-#define DW_TAG_SUN_dtor 0x420b /* SUN */
-#define DW_TAG_SUN_f90_interface 0x420c /* SUN */
-#define DW_TAG_SUN_fortran_vax_structure 0x420d /* SUN */
-#define DW_TAG_SUN_hi 0x42ff /* SUN */
-
-
-#define DW_TAG_hi_user 0xffff
-
-#define DW_children_no 0
-#define DW_children_yes 1
-
-
-
-#define DW_FORM_addr 0x01
-#define DW_FORM_block2 0x03
-#define DW_FORM_block4 0x04
-#define DW_FORM_data2 0x05
-#define DW_FORM_data4 0x06
-#define DW_FORM_data8 0x07
-#define DW_FORM_string 0x08
-#define DW_FORM_block 0x09
-#define DW_FORM_block1 0x0a
-#define DW_FORM_data1 0x0b
-#define DW_FORM_flag 0x0c
-#define DW_FORM_sdata 0x0d
-#define DW_FORM_strp 0x0e
-#define DW_FORM_udata 0x0f
-#define DW_FORM_ref_addr 0x10
-#define DW_FORM_ref1 0x11
-#define DW_FORM_ref2 0x12
-#define DW_FORM_ref4 0x13
-#define DW_FORM_ref8 0x14
-#define DW_FORM_ref_udata 0x15
-#define DW_FORM_indirect 0x16
-#define DW_FORM_sec_offset 0x17 /* DWARF4 */
-#define DW_FORM_exprloc 0x18 /* DWARF4 */
-#define DW_FORM_flag_present 0x19 /* DWARF4 */
-#define DW_FORM_ref_sig8 0x20 /* DWARF4 */
-
-#define DW_AT_sibling 0x01
-#define DW_AT_location 0x02
-#define DW_AT_name 0x03
-#define DW_AT_ordering 0x09
-#define DW_AT_subscr_data 0x0a
-#define DW_AT_byte_size 0x0b
-#define DW_AT_bit_offset 0x0c
-#define DW_AT_bit_size 0x0d
-#define DW_AT_element_list 0x0f
-#define DW_AT_stmt_list 0x10
-#define DW_AT_low_pc 0x11
-#define DW_AT_high_pc 0x12
-#define DW_AT_language 0x13
-#define DW_AT_member 0x14
-#define DW_AT_discr 0x15
-#define DW_AT_discr_value 0x16
-#define DW_AT_visibility 0x17
-#define DW_AT_import 0x18
-#define DW_AT_string_length 0x19
-#define DW_AT_common_reference 0x1a
-#define DW_AT_comp_dir 0x1b
-#define DW_AT_const_value 0x1c
-#define DW_AT_containing_type 0x1d
-#define DW_AT_default_value 0x1e
-#define DW_AT_inline 0x20
-#define DW_AT_is_optional 0x21
-#define DW_AT_lower_bound 0x22
-#define DW_AT_producer 0x25
-#define DW_AT_prototyped 0x27
-#define DW_AT_return_addr 0x2a
-#define DW_AT_start_scope 0x2c
-#define DW_AT_bit_stride 0x2e /* DWARF3 name */
-#define DW_AT_stride_size 0x2e /* DWARF2 name */
-#define DW_AT_upper_bound 0x2f
-#define DW_AT_abstract_origin 0x31
-#define DW_AT_accessibility 0x32
-#define DW_AT_address_class 0x33
-#define DW_AT_artificial 0x34
-#define DW_AT_base_types 0x35
-#define DW_AT_calling_convention 0x36
-#define DW_AT_count 0x37
-#define DW_AT_data_member_location 0x38
-#define DW_AT_decl_column 0x39
-#define DW_AT_decl_file 0x3a
-#define DW_AT_decl_line 0x3b
-#define DW_AT_declaration 0x3c
-#define DW_AT_discr_list 0x3d
-#define DW_AT_encoding 0x3e
-#define DW_AT_external 0x3f
-#define DW_AT_frame_base 0x40
-#define DW_AT_friend 0x41
-#define DW_AT_identifier_case 0x42
-#define DW_AT_macro_info 0x43
-#define DW_AT_namelist_item 0x44
-#define DW_AT_priority 0x45
-#define DW_AT_segment 0x46
-#define DW_AT_specification 0x47
-#define DW_AT_static_link 0x48
-#define DW_AT_type 0x49
-#define DW_AT_use_location 0x4a
-#define DW_AT_variable_parameter 0x4b
-#define DW_AT_virtuality 0x4c
-#define DW_AT_vtable_elem_location 0x4d
-#define DW_AT_allocated 0x4e /* DWARF3 */
-#define DW_AT_associated 0x4f /* DWARF3 */
-#define DW_AT_data_location 0x50 /* DWARF3 */
-#define DW_AT_byte_stride 0x51 /* DWARF3f */
-#define DW_AT_stride 0x51 /* DWARF3 (do not use) */
-#define DW_AT_entry_pc 0x52 /* DWARF3 */
-#define DW_AT_use_UTF8 0x53 /* DWARF3 */
-#define DW_AT_extension 0x54 /* DWARF3 */
-#define DW_AT_ranges 0x55 /* DWARF3 */
-#define DW_AT_trampoline 0x56 /* DWARF3 */
-#define DW_AT_call_column 0x57 /* DWARF3 */
-#define DW_AT_call_file 0x58 /* DWARF3 */
-#define DW_AT_call_line 0x59 /* DWARF3 */
-#define DW_AT_description 0x5a /* DWARF3 */
-#define DW_AT_binary_scale 0x5b /* DWARF3f */
-#define DW_AT_decimal_scale 0x5c /* DWARF3f */
-#define DW_AT_small 0x5d /* DWARF3f */
-#define DW_AT_decimal_sign 0x5e /* DWARF3f */
-#define DW_AT_digit_count 0x5f /* DWARF3f */
-#define DW_AT_picture_string 0x60 /* DWARF3f */
-#define DW_AT_mutable 0x61 /* DWARF3f */
-#define DW_AT_threads_scaled 0x62 /* DWARF3f */
-#define DW_AT_explicit 0x63 /* DWARF3f */
-#define DW_AT_object_pointer 0x64 /* DWARF3f */
-#define DW_AT_endianity 0x65 /* DWARF3f */
-#define DW_AT_elemental 0x66 /* DWARF3f */
-#define DW_AT_pure 0x67 /* DWARF3f */
-#define DW_AT_recursive 0x68 /* DWARF3f */
-#define DW_AT_signature 0x69 /* DWARF4 */
-#define DW_AT_main_subprogram 0x6a /* DWARF4 */
-#define DW_AT_data_bit_offset 0x6b /* DWARF4 */
-#define DW_AT_const_expr 0x6c /* DWARF4 */
-#define DW_AT_enum_class 0x6d /* DWARF4 */
-#define DW_AT_linkage_name 0x6e /* DWARF4 */
-
-/* In extensions, we attempt to include the vendor extension
- in the name even when the vendor leaves it out. */
-
-/* HP extensions. */
-#define DW_AT_HP_block_index 0x2000 /* HP */
-
-/* Follows extension so dwarfdump prints the most-likely-useful name. */
-#define DW_AT_lo_user 0x2000
-
-#define DW_AT_MIPS_fde 0x2001 /* MIPS/SGI */
-#define DW_AT_MIPS_loop_begin 0x2002 /* MIPS/SGI */
-#define DW_AT_MIPS_tail_loop_begin 0x2003 /* MIPS/SGI */
-#define DW_AT_MIPS_epilog_begin 0x2004 /* MIPS/SGI */
-#define DW_AT_MIPS_loop_unroll_factor 0x2005 /* MIPS/SGI */
-#define DW_AT_MIPS_software_pipeline_depth 0x2006 /* MIPS/SGI */
-#define DW_AT_MIPS_linkage_name 0x2007 /* MIPS/SGI, GNU, and others.*/
-#define DW_AT_MIPS_stride 0x2008 /* MIPS/SGI */
-#define DW_AT_MIPS_abstract_name 0x2009 /* MIPS/SGI */
-#define DW_AT_MIPS_clone_origin 0x200a /* MIPS/SGI */
-#define DW_AT_MIPS_has_inlines 0x200b /* MIPS/SGI */
-#define DW_AT_MIPS_stride_byte 0x200c /* MIPS/SGI */
-#define DW_AT_MIPS_stride_elem 0x200d /* MIPS/SGI */
-#define DW_AT_MIPS_ptr_dopetype 0x200e /* MIPS/SGI */
-#define DW_AT_MIPS_allocatable_dopetype 0x200f /* MIPS/SGI */
-#define DW_AT_MIPS_assumed_shape_dopetype 0x2010 /* MIPS/SGI */
-#define DW_AT_MIPS_assumed_size 0x2011 /* MIPS/SGI */
-
-/* HP extensions. */
-#define DW_AT_HP_unmodifiable 0x2001 /* conflict: MIPS */
-#define DW_AT_HP_actuals_stmt_list 0x2010 /* conflict: MIPS */
-#define DW_AT_HP_proc_per_section 0x2011 /* conflict: MIPS */
-#define DW_AT_HP_raw_data_ptr 0x2012 /* HP */
-#define DW_AT_HP_pass_by_reference 0x2013 /* HP */
-#define DW_AT_HP_opt_level 0x2014 /* HP */
-#define DW_AT_HP_prof_version_id 0x2015 /* HP */
-#define DW_AT_HP_opt_flags 0x2016 /* HP */
-#define DW_AT_HP_cold_region_low_pc 0x2017 /* HP */
-#define DW_AT_HP_cold_region_high_pc 0x2018 /* HP */
-#define DW_AT_HP_all_variables_modifiable 0x2019 /* HP */
-#define DW_AT_HP_linkage_name 0x201a /* HP */
-#define DW_AT_HP_prof_flags 0x201b /* HP */
-
-#define DW_AT_CPQ_discontig_ranges 0x2001 /* COMPAQ/HP */
-#define DW_AT_CPQ_semantic_events 0x2002 /* COMPAQ/HP */
-#define DW_AT_CPQ_split_lifetimes_var 0x2003 /* COMPAQ/HP */
-#define DW_AT_CPQ_split_lifetimes_rtn 0x2004 /* COMPAQ/HP */
-#define DW_AT_CPQ_prologue_length 0x2005 /* COMPAQ/HP */
-
-#define DW_AT_INTEL_other_endian 0x2026 /* Intel, 1 if byte swapped. */
-
-/* GNU extensions. */
-#define DW_AT_sf_names 0x2101 /* GNU */
-#define DW_AT_src_info 0x2102 /* GNU */
-#define DW_AT_mac_info 0x2103 /* GNU */
-#define DW_AT_src_coords 0x2104 /* GNU */
-#define DW_AT_body_begin 0x2105 /* GNU */
-#define DW_AT_body_end 0x2106 /* GNU */
-#define DW_AT_GNU_vector 0x2107 /* GNU */
-
-/* ALTIUM extension: ALTIUM Compliant location lists (flag) */
-#define DW_AT_ALTIUM_loclist 0x2300 /* ALTIUM */
-
-/* Sun extensions */
-#define DW_AT_SUN_template 0x2201 /* SUN */
-#define DW_AT_VMS_rtnbeg_pd_address 0x2201 /* VMS */
-#define DW_AT_SUN_alignment 0x2202 /* SUN */
-#define DW_AT_SUN_vtable 0x2203 /* SUN */
-#define DW_AT_SUN_count_guarantee 0x2204 /* SUN */
-#define DW_AT_SUN_command_line 0x2205 /* SUN */
-#define DW_AT_SUN_vbase 0x2206 /* SUN */
-#define DW_AT_SUN_compile_options 0x2207 /* SUN */
-#define DW_AT_SUN_language 0x2208 /* SUN */
-#define DW_AT_SUN_browser_file 0x2209 /* SUN */
-#define DW_AT_SUN_vtable_abi 0x2210 /* SUN */
-#define DW_AT_SUN_func_offsets 0x2211 /* SUN */
-#define DW_AT_SUN_cf_kind 0x2212 /* SUN */
-#define DW_AT_SUN_vtable_index 0x2213 /* SUN */
-#define DW_AT_SUN_omp_tpriv_addr 0x2214 /* SUN */
-#define DW_AT_SUN_omp_child_func 0x2215 /* SUN */
-#define DW_AT_SUN_func_offset 0x2216 /* SUN */
-#define DW_AT_SUN_memop_type_ref 0x2217 /* SUN */
-#define DW_AT_SUN_profile_id 0x2218 /* SUN */
-#define DW_AT_SUN_memop_signature 0x2219 /* SUN */
-#define DW_AT_SUN_obj_dir 0x2220 /* SUN */
-#define DW_AT_SUN_obj_file 0x2221 /* SUN */
-#define DW_AT_SUN_original_name 0x2222 /* SUN */
-#define DW_AT_SUN_hwcprof_signature 0x2223 /* SUN */
-#define DW_AT_SUN_amd64_parmdump 0x2224 /* SUN */
-#define DW_AT_SUN_part_link_name 0x2225 /* SUN */
-#define DW_AT_SUN_link_name 0x2226 /* SUN */
-#define DW_AT_SUN_pass_with_const 0x2227 /* SUN */
-#define DW_AT_SUN_return_with_const 0x2228 /* SUN */
-#define DW_AT_SUN_import_by_name 0x2229 /* SUN */
-#define DW_AT_SUN_f90_pointer 0x222a /* SUN */
-#define DW_AT_SUN_pass_by_ref 0x222b /* SUN */
-#define DW_AT_SUN_f90_allocatable 0x222c /* SUN */
-#define DW_AT_SUN_f90_assumed_shape_array 0x222d /* SUN */
-#define DW_AT_SUN_c_vla 0x222e /* SUN */
-#define DW_AT_SUN_return_value_ptr 0x2230 /* SUN */
-#define DW_AT_SUN_dtor_start 0x2231 /* SUN */
-#define DW_AT_SUN_dtor_length 0x2232 /* SUN */
-#define DW_AT_SUN_dtor_state_initial 0x2233 /* SUN */
-#define DW_AT_SUN_dtor_state_final 0x2234 /* SUN */
-#define DW_AT_SUN_dtor_state_deltas 0x2235 /* SUN */
-#define DW_AT_SUN_import_by_lname 0x2236 /* SUN */
-#define DW_AT_SUN_f90_use_only 0x2237 /* SUN */
-#define DW_AT_SUN_namelist_spec 0x2238 /* SUN */
-#define DW_AT_SUN_is_omp_child_func 0x2239 /* SUN */
-#define DW_AT_SUN_fortran_main_alias 0x223a /* SUN */
-#define DW_AT_SUN_fortran_based 0x223b /* SUN */
-
-/* UPC extension */
-#define DW_AT_upc_threads_scaled 0x3210 /* UPC */
-
-/* PGI (STMicroelectronics) extensions. */
-#define DW_AT_PGI_lbase 0x3a00 /* PGI. Block, constant, reference. This attribute is an ASTPLAB extension used to describe the array local base. */
-#define DW_AT_PGI_soffset 0x3a01 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the section offset, or the offset to the first element in the dimension. */
-#define DW_AT_PGI_lstride 0x3a02 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the linear stride or the distance between elements in the dimension. */
-
-/* Apple Extensions for closures */
-#define DW_AT_APPLE_closure 0x3fe4 /* Apple */
-/* Apple Extensions for Objective-C runtime info */
-#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */
-#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */
-
-
-#define DW_AT_hi_user 0x3fff
-
-#define DW_OP_addr 0x03
-#define DW_OP_deref 0x06
-#define DW_OP_const1u 0x08
-#define DW_OP_const1s 0x09
-#define DW_OP_const2u 0x0a
-#define DW_OP_const2s 0x0b
-#define DW_OP_const4u 0x0c
-#define DW_OP_const4s 0x0d
-#define DW_OP_const8u 0x0e
-#define DW_OP_const8s 0x0f
-#define DW_OP_constu 0x10
-#define DW_OP_consts 0x11
-#define DW_OP_dup 0x12
-#define DW_OP_drop 0x13
-#define DW_OP_over 0x14
-#define DW_OP_pick 0x15
-#define DW_OP_swap 0x16
-#define DW_OP_rot 0x17
-#define DW_OP_xderef 0x18
-#define DW_OP_abs 0x19
-#define DW_OP_and 0x1a
-#define DW_OP_div 0x1b
-#define DW_OP_minus 0x1c
-#define DW_OP_mod 0x1d
-#define DW_OP_mul 0x1e
-#define DW_OP_neg 0x1f
-#define DW_OP_not 0x20
-#define DW_OP_or 0x21
-#define DW_OP_plus 0x22
-#define DW_OP_plus_uconst 0x23
-#define DW_OP_shl 0x24
-#define DW_OP_shr 0x25
-#define DW_OP_shra 0x26
-#define DW_OP_xor 0x27
-#define DW_OP_bra 0x28
-#define DW_OP_eq 0x29
-#define DW_OP_ge 0x2a
-#define DW_OP_gt 0x2b
-#define DW_OP_le 0x2c
-#define DW_OP_lt 0x2d
-#define DW_OP_ne 0x2e
-#define DW_OP_skip 0x2f
-#define DW_OP_lit0 0x30
-#define DW_OP_lit1 0x31
-#define DW_OP_lit2 0x32
-#define DW_OP_lit3 0x33
-#define DW_OP_lit4 0x34
-#define DW_OP_lit5 0x35
-#define DW_OP_lit6 0x36
-#define DW_OP_lit7 0x37
-#define DW_OP_lit8 0x38
-#define DW_OP_lit9 0x39
-#define DW_OP_lit10 0x3a
-#define DW_OP_lit11 0x3b
-#define DW_OP_lit12 0x3c
-#define DW_OP_lit13 0x3d
-#define DW_OP_lit14 0x3e
-#define DW_OP_lit15 0x3f
-#define DW_OP_lit16 0x40
-#define DW_OP_lit17 0x41
-#define DW_OP_lit18 0x42
-#define DW_OP_lit19 0x43
-#define DW_OP_lit20 0x44
-#define DW_OP_lit21 0x45
-#define DW_OP_lit22 0x46
-#define DW_OP_lit23 0x47
-#define DW_OP_lit24 0x48
-#define DW_OP_lit25 0x49
-#define DW_OP_lit26 0x4a
-#define DW_OP_lit27 0x4b
-#define DW_OP_lit28 0x4c
-#define DW_OP_lit29 0x4d
-#define DW_OP_lit30 0x4e
-#define DW_OP_lit31 0x4f
-#define DW_OP_reg0 0x50
-#define DW_OP_reg1 0x51
-#define DW_OP_reg2 0x52
-#define DW_OP_reg3 0x53
-#define DW_OP_reg4 0x54
-#define DW_OP_reg5 0x55
-#define DW_OP_reg6 0x56
-#define DW_OP_reg7 0x57
-#define DW_OP_reg8 0x58
-#define DW_OP_reg9 0x59
-#define DW_OP_reg10 0x5a
-#define DW_OP_reg11 0x5b
-#define DW_OP_reg12 0x5c
-#define DW_OP_reg13 0x5d
-#define DW_OP_reg14 0x5e
-#define DW_OP_reg15 0x5f
-#define DW_OP_reg16 0x60
-#define DW_OP_reg17 0x61
-#define DW_OP_reg18 0x62
-#define DW_OP_reg19 0x63
-#define DW_OP_reg20 0x64
-#define DW_OP_reg21 0x65
-#define DW_OP_reg22 0x66
-#define DW_OP_reg23 0x67
-#define DW_OP_reg24 0x68
-#define DW_OP_reg25 0x69
-#define DW_OP_reg26 0x6a
-#define DW_OP_reg27 0x6b
-#define DW_OP_reg28 0x6c
-#define DW_OP_reg29 0x6d
-#define DW_OP_reg30 0x6e
-#define DW_OP_reg31 0x6f
-#define DW_OP_breg0 0x70
-#define DW_OP_breg1 0x71
-#define DW_OP_breg2 0x72
-#define DW_OP_breg3 0x73
-#define DW_OP_breg4 0x74
-#define DW_OP_breg5 0x75
-#define DW_OP_breg6 0x76
-#define DW_OP_breg7 0x77
-#define DW_OP_breg8 0x78
-#define DW_OP_breg9 0x79
-#define DW_OP_breg10 0x7a
-#define DW_OP_breg11 0x7b
-#define DW_OP_breg12 0x7c
-#define DW_OP_breg13 0x7d
-#define DW_OP_breg14 0x7e
-#define DW_OP_breg15 0x7f
-#define DW_OP_breg16 0x80
-#define DW_OP_breg17 0x81
-#define DW_OP_breg18 0x82
-#define DW_OP_breg19 0x83
-#define DW_OP_breg20 0x84
-#define DW_OP_breg21 0x85
-#define DW_OP_breg22 0x86
-#define DW_OP_breg23 0x87
-#define DW_OP_breg24 0x88
-#define DW_OP_breg25 0x89
-#define DW_OP_breg26 0x8a
-#define DW_OP_breg27 0x8b
-#define DW_OP_breg28 0x8c
-#define DW_OP_breg29 0x8d
-#define DW_OP_breg30 0x8e
-#define DW_OP_breg31 0x8f
-#define DW_OP_regx 0x90
-#define DW_OP_fbreg 0x91
-#define DW_OP_bregx 0x92
-#define DW_OP_piece 0x93
-#define DW_OP_deref_size 0x94
-#define DW_OP_xderef_size 0x95
-#define DW_OP_nop 0x96
-#define DW_OP_push_object_address 0x97 /* DWARF3 */
-#define DW_OP_call2 0x98 /* DWARF3 */
-#define DW_OP_call4 0x99 /* DWARF3 */
-#define DW_OP_call_ref 0x9a /* DWARF3 */
-#define DW_OP_form_tls_address 0x9b /* DWARF3f */
-#define DW_OP_call_frame_cfa 0x9c /* DWARF3f */
-#define DW_OP_bit_piece 0x9d /* DWARF3f */
-#define DW_OP_implicit_value 0x9e /* DWARF4 */
-#define DW_OP_stack_value 0x9f /* DWARF4 */
-
-
- /* GNU extensions. */
-#define DW_OP_GNU_push_tls_address 0xe0 /* GNU */
-
-/* Follows extension so dwarfdump prints the most-likely-useful name. */
-#define DW_OP_lo_user 0xe0
-
- /* HP extensions. */
-#define DW_OP_HP_unknown 0xe0 /* HP conflict: GNU */
-#define DW_OP_HP_is_value 0xe1 /* HP */
-#define DW_OP_HP_fltconst4 0xe2 /* HP */
-#define DW_OP_HP_fltconst8 0xe3 /* HP */
-#define DW_OP_HP_mod_range 0xe4 /* HP */
-#define DW_OP_HP_unmod_range 0xe5 /* HP */
-#define DW_OP_HP_tls 0xe6 /* HP */
-
-#define DW_OP_INTEL_bit_piece 0xe8 /* Intel: made obsolete by DW_OP_bit_piece above. */
-
-
- /* Apple extension. */
-#define DW_OP_APPLE_uninit 0xf0 /* Apple */
-
-#define DW_OP_hi_user 0xff
-
-#define DW_ATE_address 0x1
-#define DW_ATE_boolean 0x2
-#define DW_ATE_complex_float 0x3
-#define DW_ATE_float 0x4
-#define DW_ATE_signed 0x5
-#define DW_ATE_signed_char 0x6
-#define DW_ATE_unsigned 0x7
-#define DW_ATE_unsigned_char 0x8
-#define DW_ATE_imaginary_float 0x9 /* DWARF3 */
-#define DW_ATE_packed_decimal 0xa /* DWARF3f */
-#define DW_ATE_numeric_string 0xb /* DWARF3f */
-#define DW_ATE_edited 0xc /* DWARF3f */
-#define DW_ATE_signed_fixed 0xd /* DWARF3f */
-#define DW_ATE_unsigned_fixed 0xe /* DWARF3f */
-#define DW_ATE_decimal_float 0xf /* DWARF3f */
-
-
-/* ALTIUM extensions. x80, x81 */
-#define DW_ATE_ALTIUM_fract 0x80 /* ALTIUM __fract type */
-
-/* Follows extension so dwarfdump prints the most-likely-useful name. */
-#define DW_ATE_lo_user 0x80
-
-/* Shown here to help dwarfdump build script. */
-#define DW_ATE_ALTIUM_accum 0x81 /* ALTIUM __accum type */
-
-/* HP Floating point extensions. */
-#define DW_ATE_HP_float80 0x80 /* (80 bit). HP */
-
-
-#define DW_ATE_HP_complex_float80 0x81 /* Complex (80 bit). HP */
-#define DW_ATE_HP_float128 0x82 /* (128 bit). HP */
-#define DW_ATE_HP_complex_float128 0x83 /* Complex (128 bit). HP */
-#define DW_ATE_HP_floathpintel 0x84 /* (82 bit IA64). HP */
-#define DW_ATE_HP_imaginary_float80 0x85 /* HP */
-#define DW_ATE_HP_imaginary_float128 0x86 /* HP */
-
-/* Sun extensions */
-#define DW_ATE_SUN_interval_float 0x91
-#define DW_ATE_SUN_imaginary_float 0x92 /* Obsolete: See DW_ATE_imaginary_float */
-
-#define DW_ATE_hi_user 0xff
-
-
-/* Decimal Sign codes. */
-#define DW_DS_unsigned 0x01 /* DWARF3f */
-#define DW_DS_leading_overpunch 0x02 /* DWARF3f */
-#define DW_DS_trailing_overpunch 0x03 /* DWARF3f */
-#define DW_DS_leading_separate 0x04 /* DWARF3f */
-
-#define DW_DS_trailing_separate 0x05 /* DWARF3f */
-
-/* Endian code name. */
-#define DW_END_default 0x00 /* DWARF3f */
-#define DW_END_big 0x01 /* DWARF3f */
-#define DW_END_little 0x02 /* DWARF3f */
-
-#define DW_END_lo_user 0x40 /* DWARF3f */
-#define DW_END_hi_user 0xff /* DWARF3f */
-
-/* For use with DW_TAG_SUN_codeflags
- * If DW_TAG_SUN_codeflags is accepted as a dwarf standard, then
- * standard dwarf ATCF entries start at 0x01
- */
-#define DW_ATCF_lo_user 0x40 /* SUN */
-#define DW_ATCF_SUN_mop_bitfield 0x41 /* SUN */
-#define DW_ATCF_SUN_mop_spill 0x42 /* SUN */
-#define DW_ATCF_SUN_mop_scopy 0x43 /* SUN */
-#define DW_ATCF_SUN_func_start 0x44 /* SUN */
-#define DW_ATCF_SUN_end_ctors 0x45 /* SUN */
-#define DW_ATCF_SUN_branch_target 0x46 /* SUN */
-#define DW_ATCF_SUN_mop_stack_probe 0x47 /* SUN */
-#define DW_ATCF_SUN_func_epilog 0x48 /* SUN */
-#define DW_ATCF_hi_user 0xff /* SUN */
-
-/* Accessibility code name. */
-#define DW_ACCESS_public 0x01
-#define DW_ACCESS_protected 0x02
-#define DW_ACCESS_private 0x03
-
-/* Visibility code name. */
-#define DW_VIS_local 0x01
-#define DW_VIS_exported 0x02
-#define DW_VIS_qualified 0x03
-
-/* Virtuality code name. */
-#define DW_VIRTUALITY_none 0x00
-#define DW_VIRTUALITY_virtual 0x01
-#define DW_VIRTUALITY_pure_virtual 0x02
-
-#define DW_LANG_C89 0x0001
-#define DW_LANG_C 0x0002
-#define DW_LANG_Ada83 0x0003
-#define DW_LANG_C_plus_plus 0x0004
-#define DW_LANG_Cobol74 0x0005
-#define DW_LANG_Cobol85 0x0006
-#define DW_LANG_Fortran77 0x0007
-#define DW_LANG_Fortran90 0x0008
-#define DW_LANG_Pascal83 0x0009
-#define DW_LANG_Modula2 0x000a
-#define DW_LANG_Java 0x000b /* DWARF3 */
-#define DW_LANG_C99 0x000c /* DWARF3 */
-#define DW_LANG_Ada95 0x000d /* DWARF3 */
-#define DW_LANG_Fortran95 0x000e /* DWARF3 */
-#define DW_LANG_PLI 0x000f /* DWARF3 */
-#define DW_LANG_ObjC 0x0010 /* DWARF3f */
-#define DW_LANG_ObjC_plus_plus 0x0011 /* DWARF3f */
-#define DW_LANG_UPC 0x0012 /* DWARF3f */
-#define DW_LANG_D 0x0013 /* DWARF3f */
-#define DW_LANG_Python 0x0014 /* DWARF4 */
-#define DW_LANG_lo_user 0x8000
-#define DW_LANG_Mips_Assembler 0x8001 /* MIPS */
-#define DW_LANG_Upc 0x8765 /* UPC, use
- DW_LANG_UPC instead. */
-/* ALTIUM extension */
-#define DW_LANG_ALTIUM_Assembler 0x9101 /* ALTIUM */
-
-/* Sun extensions */
-#define DW_LANG_SUN_Assembler 0x9001 /* SUN */
-
-#define DW_LANG_hi_user 0xffff
-
-/* Identifier case name. */
-#define DW_ID_case_sensitive 0x00
-#define DW_ID_up_case 0x01
-#define DW_ID_down_case 0x02
-#define DW_ID_case_insensitive 0x03
-
-/* Calling Convention Name. */
-#define DW_CC_normal 0x01
-#define DW_CC_program 0x02
-#define DW_CC_nocall 0x03
-#define DW_CC_lo_user 0x40
-
-/* ALTIUM extensions. */
-/* Function is an interrupt handler, return address on system stack. */
-#define DW_CC_ALTIUM_interrupt 0x65 /* ALTIUM*/
-
-/* Near function model, return address on system stack. */
-#define DW_CC_ALTIUM_near_system_stack 0x66 /*ALTIUM */
-
-/* Near function model, return address on user stack. */
-#define DW_CC_ALTIUM_near_user_stack 0x67 /* ALTIUM */
-
-/* Huge function model, return address on user stack. */
-#define DW_CC_ALTIUM_huge_user_stack 0x68 /* ALTIUM */
-
-
-#define DW_CC_hi_user 0xff
-
-/* Inline Code Name. */
-#define DW_INL_not_inlined 0x00
-#define DW_INL_inlined 0x01
-#define DW_INL_declared_not_inlined 0x02
-#define DW_INL_declared_inlined 0x03
-
-/* Ordering Name. */
-#define DW_ORD_row_major 0x00
-#define DW_ORD_col_major 0x01
-
-/* Discriminant Descriptor Name. */
-#define DW_DSC_label 0x00
-#define DW_DSC_range 0x01
-
-/* Line number standard opcode name. */
-#define DW_LNS_copy 0x01
-#define DW_LNS_advance_pc 0x02
-#define DW_LNS_advance_line 0x03
-#define DW_LNS_set_file 0x04
-#define DW_LNS_set_column 0x05
-#define DW_LNS_negate_stmt 0x06
-#define DW_LNS_set_basic_block 0x07
-#define DW_LNS_const_add_pc 0x08
-#define DW_LNS_fixed_advance_pc 0x09
-#define DW_LNS_set_prologue_end 0x0a /* DWARF3 */
-#define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */
-#define DW_LNS_set_isa 0x0c /* DWARF3 */
-
-/* Line number extended opcode name. */
-#define DW_LNE_end_sequence 0x01
-#define DW_LNE_set_address 0x02
-#define DW_LNE_define_file 0x03
-#define DW_LNE_set_discriminator 0x04 /* DWARF4 */
-
-/* HP extensions. */
-#define DW_LNE_HP_negate_is_UV_update 0x11 /* 17 HP */
-#define DW_LNE_HP_push_context 0x12 /* 18 HP */
-#define DW_LNE_HP_pop_context 0x13 /* 19 HP */
-#define DW_LNE_HP_set_file_line_column 0x14 /* 20 HP */
-#define DW_LNE_HP_set_routine_name 0x15 /* 21 HP */
-#define DW_LNE_HP_set_sequence 0x16 /* 22 HP */
-#define DW_LNE_HP_negate_post_semantics 0x17 /* 23 HP */
-#define DW_LNE_HP_negate_function_exit 0x18 /* 24 HP */
-#define DW_LNE_HP_negate_front_end_logical 0x19 /* 25 HP */
-#define DW_LNE_HP_define_proc 0x20 /* 32 HP */
-
-#define DW_LNE_lo_user 0x80 /* DWARF3 */
-#define DW_LNE_hi_user 0xff /* DWARF3 */
-
-/* Macro information. */
-#define DW_MACINFO_define 0x01
-#define DW_MACINFO_undef 0x02
-#define DW_MACINFO_start_file 0x03
-#define DW_MACINFO_end_file 0x04
-#define DW_MACINFO_vendor_ext 0xff
-
-/* CFA operator compaction (a space saving measure, see
- the DWARF standard) means DW_CFA_extended and DW_CFA_nop
- have the same value here. */
-#define DW_CFA_advance_loc 0x40
-#define DW_CFA_offset 0x80
-#define DW_CFA_restore 0xc0
-#define DW_CFA_extended 0
-
-#define DW_CFA_nop 0x00
-#define DW_CFA_set_loc 0x01
-#define DW_CFA_advance_loc1 0x02
-#define DW_CFA_advance_loc2 0x03
-#define DW_CFA_advance_loc4 0x04
-#define DW_CFA_offset_extended 0x05
-#define DW_CFA_restore_extended 0x06
-#define DW_CFA_undefined 0x07
-#define DW_CFA_same_value 0x08
-#define DW_CFA_register 0x09
-#define DW_CFA_remember_state 0x0a
-#define DW_CFA_restore_state 0x0b
-#define DW_CFA_def_cfa 0x0c
-#define DW_CFA_def_cfa_register 0x0d
-#define DW_CFA_def_cfa_offset 0x0e
-#define DW_CFA_def_cfa_expression 0x0f /* DWARF3 */
-#define DW_CFA_expression 0x10 /* DWARF3 */
-#define DW_CFA_offset_extended_sf 0x11 /* DWARF3 */
-#define DW_CFA_def_cfa_sf 0x12 /* DWARF3 */
-#define DW_CFA_def_cfa_offset_sf 0x13 /* DWARF3 */
-#define DW_CFA_val_offset 0x14 /* DWARF3f */
-#define DW_CFA_val_offset_sf 0x15 /* DWARF3f */
-#define DW_CFA_val_expression 0x16 /* DWARF3f */
-
-#define DW_CFA_lo_user 0x1c
-#define DW_CFA_low_user 0x1c /* Incorrect spelling, do not use. */
-
-/* SGI/MIPS extension. */
-#define DW_CFA_MIPS_advance_loc8 0x1d /* MIPS */
-
-/* GNU extensions. */
-#define DW_CFA_GNU_window_save 0x2d /* GNU */
-#define DW_CFA_GNU_args_size 0x2e /* GNU */
-#define DW_CFA_GNU_negative_offset_extended 0x2f /* GNU */
-
-#define DW_CFA_high_user 0x3f
-
-/* GNU exception header encoding. See the Generic
- Elf Specification of the Linux Standard Base (LSB).
- http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
- The upper 4 bits indicate how the value is to be applied.
- The lower 4 bits indicate the format of the data.
-*/
-#define DW_EH_PE_absptr 0x00 /* GNU */
-#define DW_EH_PE_uleb128 0x01 /* GNU */
-#define DW_EH_PE_udata2 0x02 /* GNU */
-#define DW_EH_PE_udata4 0x03 /* GNU */
-#define DW_EH_PE_udata8 0x04 /* GNU */
-#define DW_EH_PE_sleb128 0x09 /* GNU */
-#define DW_EH_PE_sdata2 0x0A /* GNU */
-#define DW_EH_PE_sdata4 0x0B /* GNU */
-#define DW_EH_PE_sdata8 0x0C /* GNU */
-
-#define DW_EH_PE_pcrel 0x10 /* GNU */
-#define DW_EH_PE_textrel 0x20 /* GNU */
-#define DW_EH_PE_datarel 0x30 /* GNU */
-#define DW_EH_PE_funcrel 0x40 /* GNU */
-#define DW_EH_PE_aligned 0x50 /* GNU */
-
-#define DW_EH_PE_omit 0xff /* GNU. Means no value present. */
-
-
-/* Mapping from machine registers and pseudo-regs into the .debug_frame table.
- DW_FRAME entries are machine specific. These describe
- MIPS/SGI R3000, R4K, R4400 and all later MIPS/SGI IRIX machines.
- They describe a mapping from hardware register number to
- the number used in the table to identify that register.
-
- The CFA (Canonical Frame Address) described in DWARF is called
- the Virtual Frame Pointer on MIPS/SGI machines.
-
- The DW_FRAME* names here are MIPS/SGI specfic.
- Libdwarf interfaces defined in 2008 make the FRAME definitions
- here (and the fixed table sizes they imply) obsolete.
- They are left here for compatibility.
-
-*/
-/* Column used for CFA. Assumes reg 0 never appears as
- a register in DWARF info. */
-#define DW_FRAME_CFA_COL 0
-
-#define DW_FRAME_REG1 1 /* integer reg 1 */
-#define DW_FRAME_REG2 2 /* integer reg 2 */
-#define DW_FRAME_REG3 3 /* integer reg 3 */
-#define DW_FRAME_REG4 4 /* integer reg 4 */
-#define DW_FRAME_REG5 5 /* integer reg 5 */
-#define DW_FRAME_REG6 6 /* integer reg 6 */
-#define DW_FRAME_REG7 7 /* integer reg 7 */
-#define DW_FRAME_REG8 8 /* integer reg 8 */
-#define DW_FRAME_REG9 9 /* integer reg 9 */
-#define DW_FRAME_REG10 10 /* integer reg 10 */
-#define DW_FRAME_REG11 11 /* integer reg 11 */
-#define DW_FRAME_REG12 12 /* integer reg 12 */
-#define DW_FRAME_REG13 13 /* integer reg 13 */
-#define DW_FRAME_REG14 14 /* integer reg 14 */
-#define DW_FRAME_REG15 15 /* integer reg 15 */
-#define DW_FRAME_REG16 16 /* integer reg 16 */
-#define DW_FRAME_REG17 17 /* integer reg 17 */
-#define DW_FRAME_REG18 18 /* integer reg 18 */
-#define DW_FRAME_REG19 19 /* integer reg 19 */
-#define DW_FRAME_REG20 20 /* integer reg 20 */
-#define DW_FRAME_REG21 21 /* integer reg 21 */
-#define DW_FRAME_REG22 22 /* integer reg 22 */
-#define DW_FRAME_REG23 23 /* integer reg 23 */
-#define DW_FRAME_REG24 24 /* integer reg 24 */
-#define DW_FRAME_REG25 25 /* integer reg 25 */
-#define DW_FRAME_REG26 26 /* integer reg 26 */
-#define DW_FRAME_REG27 27 /* integer reg 27 */
-#define DW_FRAME_REG28 28 /* integer reg 28 */
-#define DW_FRAME_REG29 29 /* integer reg 29 */
-#define DW_FRAME_REG30 30 /* integer reg 30 */
-#define DW_FRAME_REG31 31 /* integer reg 31, aka ra */
-
- /* MIPS1, 2 have only some of these 64-bit registers.
- ** MIPS1 save/restore takes 2 instructions per 64-bit reg, and
- ** in that case, the register is considered stored after the second
- ** swc1.
- */
-#define DW_FRAME_FREG0 32 /* 64-bit floating point reg 0 */
-#define DW_FRAME_FREG1 33 /* 64-bit floating point reg 1 */
-#define DW_FRAME_FREG2 34 /* 64-bit floating point reg 2 */
-#define DW_FRAME_FREG3 35 /* 64-bit floating point reg 3 */
-#define DW_FRAME_FREG4 36 /* 64-bit floating point reg 4 */
-#define DW_FRAME_FREG5 37 /* 64-bit floating point reg 5 */
-#define DW_FRAME_FREG6 38 /* 64-bit floating point reg 6 */
-#define DW_FRAME_FREG7 39 /* 64-bit floating point reg 7 */
-#define DW_FRAME_FREG8 40 /* 64-bit floating point reg 8 */
-#define DW_FRAME_FREG9 41 /* 64-bit floating point reg 9 */
-#define DW_FRAME_FREG10 42 /* 64-bit floating point reg 10 */
-#define DW_FRAME_FREG11 43 /* 64-bit floating point reg 11 */
-#define DW_FRAME_FREG12 44 /* 64-bit floating point reg 12 */
-#define DW_FRAME_FREG13 45 /* 64-bit floating point reg 13 */
-#define DW_FRAME_FREG14 46 /* 64-bit floating point reg 14 */
-#define DW_FRAME_FREG15 47 /* 64-bit floating point reg 15 */
-#define DW_FRAME_FREG16 48 /* 64-bit floating point reg 16 */
-#define DW_FRAME_FREG17 49 /* 64-bit floating point reg 17 */
-#define DW_FRAME_FREG18 50 /* 64-bit floating point reg 18 */
-#define DW_FRAME_FREG19 51 /* 64-bit floating point reg 19 */
-#define DW_FRAME_FREG20 52 /* 64-bit floating point reg 20 */
-#define DW_FRAME_FREG21 53 /* 64-bit floating point reg 21 */
-#define DW_FRAME_FREG22 54 /* 64-bit floating point reg 22 */
-#define DW_FRAME_FREG23 55 /* 64-bit floating point reg 23 */
-#define DW_FRAME_FREG24 56 /* 64-bit floating point reg 24 */
-#define DW_FRAME_FREG25 57 /* 64-bit floating point reg 25 */
-#define DW_FRAME_FREG26 58 /* 64-bit floating point reg 26 */
-#define DW_FRAME_FREG27 59 /* 64-bit floating point reg 27 */
-#define DW_FRAME_FREG28 60 /* 64-bit floating point reg 28 */
-#define DW_FRAME_FREG29 61 /* 64-bit floating point reg 29 */
-#define DW_FRAME_FREG30 62 /* 64-bit floating point reg 30 */
-#define DW_FRAME_FREG31 63 /* 64-bit floating point reg 31 */
-
-/* ***IMPORTANT NOTE, TARGET DEPENDENCY ****
- The following 4 #defines are dependent on
- the target cpu(s) that you apply libdwarf to.
- Ensure that DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL
- do not conflict with the range [0-DW_FRAME_STATIC_LINK].
- The value 63 works for MIPS cpus at least up to the R16000.
-
- For a cpu with more than 63 real registers
- DW_FRAME_HIGHEST_NORMAL_REGISTER
- must be increased for things to work properly!
- Also ensure that DW_FRAME_UNDEFINED_VAL DW_FRAME_SAME_VAL
- are not in the range [0-DW_FRAME_STATIC_LINK]
-
- Having DW_FRAME_HIGHEST_NORMAL_REGISTER be higher than
- is strictly needed is safe.
-
-*/
-
-#ifndef DW_FRAME_HIGHEST_NORMAL_REGISTER
-#define DW_FRAME_HIGHEST_NORMAL_REGISTER 63
-#endif
-/* This is the number of columns in the Frame Table.
- This constant should
- be kept in sync with DW_REG_TABLE_SIZE defined in libdwarf.h
- It must also be large enough to be beyond the highest
- compiler-defined-register (meaning DW_FRAME_RA_COL DW_FRAME_STATIC_LINK
- in the MIPS/IRIX case */
-#ifndef DW_FRAME_LAST_REG_NUM
-#define DW_FRAME_LAST_REG_NUM (DW_FRAME_HIGHEST_NORMAL_REGISTER + 3)
-#endif
-
-
-/* Column recording ra (return addrress from a function call).
- This is common to many architectures, but as a 'simple register'
- is not necessarily adequate for all architectures.
- For MIPS/IRIX this register number is actually recorded on disk
- in the .debug_frame section.
- */
-#define DW_FRAME_RA_COL (DW_FRAME_HIGHEST_NORMAL_REGISTER + 1)
-
-/* Column recording static link applicable to up-level
- addressing, as in IRIX mp code, pascal, etc.
- This is common to many architectures but
- is not necessarily adequate for all architectures.
- For MIPS/IRIX this register number is actually recorded on disk
- in the .debug_frame section.
-*/
-#define DW_FRAME_STATIC_LINK (DW_FRAME_HIGHEST_NORMAL_REGISTER + 2)
-
-
-
-/*
- DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL are
- never on disk, just generated by libdwarf. See libdwarf.h
- for their values.
-*/
-
-
-
-#define DW_CHILDREN_no 0x00
-#define DW_CHILDREN_yes 0x01
-
-#define DW_ADDR_none 0
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __DWARF_H */
diff --git a/distrib/elff/elff/dwarf_cu.cc b/distrib/elff/elff/dwarf_cu.cc
deleted file mode 100644
index a3d4c52..0000000
--- a/distrib/elff/elff/dwarf_cu.cc
+++ /dev/null
@@ -1,758 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of a class DwarfCU, that encapsulates a compilation
- * unit in the .debug_info section of the mapped ELF file.
- */
-
-#include "string.h"
-#include "stdio.h"
-#include "elff/elf_file.h"
-#include "elff/dwarf_cu.h"
-#include "elff/dwarf_utils.h"
-
-DwarfCU::DwarfCU(ElfFile* elf)
- : elf_file_(elf),
- cu_die_(NULL),
- prev_cu_(NULL) {
-}
-
-DwarfCU::~DwarfCU() {
- if (cu_die_ != NULL) {
- delete cu_die_;
- }
- abbrs_.empty();
-}
-
-DwarfCU* DwarfCU::create_instance(ElfFile* elf, const void* hdr) {
- DwarfCU* ret;
-
- /* 64-bit DWARF CU has first 4 bytes in its header set to 0xFFFFFFFF. */
- if (*reinterpret_cast<const Elf_Word*>(hdr) == 0xFFFFFFFF) {
- ret = new(elf) DwarfCUImpl<Dwarf64_CUHdr, Dwarf64_Off>
- (elf, reinterpret_cast<const Dwarf64_CUHdr*>(hdr));
- } else {
- ret = new(elf) DwarfCUImpl<Dwarf32_CUHdr, Dwarf32_Off>
- (elf, reinterpret_cast<const Dwarf32_CUHdr*>(hdr));
- }
- assert(ret != NULL);
- if (ret == NULL) {
- _set_errno(ENOMEM);
- }
- return ret;
-}
-
-const Elf_Byte* DwarfCU::process_attrib(const Elf_Byte* prop,
- Dwarf_Form form,
- Dwarf_Value* attr_value) const {
- assert(form != 0);
- Dwarf_Value tmp_val;
- Dwarf_Value leb128;
-
- attr_value->type = DWARF_VALUE_UNKNOWN;
- attr_value->encoded_size = 0;
- attr_value->u64 = 0;
-
- switch (form) {
- /* Property is a block of data, contained in .debug_info section. Block
- * size is encoded with 1 byte value, and block data immediately follows
- * block size. */
- case DW_FORM_block1:
- attr_value->type = DWARF_VALUE_BLOCK;
- attr_value->block.block_size = *prop;
- attr_value->block.block_ptr = prop + 1;
- attr_value->encoded_size =
- static_cast<Elf_Word>(attr_value->block.block_size + 1);
- break;
-
- /* Property is a block of data, contained in .debug_info section. Block
- * size is encoded with 2 bytes value, and block data immediately follows
- * block size. */
- case DW_FORM_block2:
- attr_value->type = DWARF_VALUE_BLOCK;
- attr_value->block.block_size =
- elf_file_->pull_val(reinterpret_cast<const Elf_Half*>(prop));
- attr_value->block.block_ptr = prop + 2;
- attr_value->encoded_size =
- static_cast<Elf_Word>(attr_value->block.block_size + 2);
- break;
-
- /* Property is a block of data, contained in .debug_info section. Block
- * size is encoded with 4 bytes value, and block data immediately follows
- * block size. */
- case DW_FORM_block4:
- attr_value->type = DWARF_VALUE_BLOCK;
- attr_value->block.block_size =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- attr_value->block.block_ptr = prop + 4;
- attr_value->encoded_size =
- static_cast<Elf_Word>(attr_value->block.block_size + 4);
- break;
-
- /* Property is a block of data, contained in .debug_info section. Block
- * size is encoded with unsigned LEB128 value, and block data immediately
- * follows block size. */
- case DW_FORM_block:
- reinterpret_cast<const Dwarf_Leb128*>(prop)->process_unsigned(&leb128);
- attr_value->type = DWARF_VALUE_BLOCK;
- attr_value->block.block_size = leb128.u32;
- attr_value->block.block_ptr = prop + leb128.encoded_size;
- attr_value->encoded_size =
- static_cast<Elf_Word>(attr_value->block.block_size +
- leb128.encoded_size);
- break;
-
- /* Property is unsigned 1 byte value. */
- case DW_FORM_flag:
- case DW_FORM_data1:
- case DW_FORM_ref1:
- attr_value->type = DWARF_VALUE_U8;
- attr_value->u8 = *prop;
- attr_value->encoded_size = 1;
- break;
-
- /* Property is unsigned 2 bytes value. */
- case DW_FORM_data2:
- case DW_FORM_ref2:
- attr_value->type = DWARF_VALUE_U16;
- attr_value->u16 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Half*>(prop));
- attr_value->encoded_size = 2;
- break;
-
- /* Property is unsigned 4 bytes value. */
- case DW_FORM_data4:
- case DW_FORM_ref4:
- attr_value->type = DWARF_VALUE_U32;
- attr_value->u32 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- attr_value->encoded_size = 4;
- break;
-
- /* Property is unsigned 8 bytes value. */
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- attr_value->type = DWARF_VALUE_U64;
- attr_value->u64 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Xword*>(prop));
- attr_value->encoded_size = 8;
- break;
-
- /* Property is signed LEB128 value. */
- case DW_FORM_sdata:
- reinterpret_cast<const Dwarf_Leb128*>(prop)->process_signed(attr_value);
- break;
-
- /* Property is unsigned LEB128 value. */
- case DW_FORM_ref_udata:
- case DW_FORM_udata:
- reinterpret_cast<const Dwarf_Leb128*>(prop)->process_unsigned(attr_value);
- break;
-
- /* Property is a string contained directly in .debug_info section. */
- case DW_FORM_string:
- attr_value->type = DWARF_VALUE_STR;
- attr_value->str = reinterpret_cast<const char*>(prop);
- attr_value->encoded_size = strlen(attr_value->str) + 1;
- break;
-
- /* Property is an offset of a string contained in .debug_str section.
- * We will process the reference here, converting it into the actual
- * string value. */
- case DW_FORM_strp:
- attr_value->type = DWARF_VALUE_STR;
- if (elf_file_->is_DWARF_64()) {
- Elf_Xword str_offset =
- elf_file_->pull_val(reinterpret_cast<const Elf_Xword*>(prop));
- attr_value->str = elf_file_->get_debug_str(str_offset);
- attr_value->encoded_size = 8;
- } else {
- Elf_Word str_offset =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- attr_value->str = elf_file_->get_debug_str(str_offset);
- attr_value->encoded_size = 4;
- }
- break;
-
- /* Property is an address. */
- case DW_FORM_addr:
- if (addr_sizeof_ == 4) {
- attr_value->type = DWARF_VALUE_PTR32;
- attr_value->u32 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- } else {
- attr_value->type = DWARF_VALUE_PTR64;
- attr_value->u64 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Xword*>(prop));
- }
- attr_value->encoded_size = addr_sizeof_;
- break;
-
- /* Reference from the beginning of .debug_info section. */
- case DW_FORM_ref_addr:
- /* DWARF3+ requires that encoding size of this property must be 4 bytes
- * in 32-bit DWARF, and 8 bytes in 64-bit DWARF, while DWARF2- requires
- * encoding size to be equal to CU's pointer size. */
- if (is_DWARF3_or_higher()) {
- if (elf_file_->is_DWARF_64()) {
- attr_value->type = DWARF_VALUE_U64;
- attr_value->u64 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Xword*>(prop));
- attr_value->encoded_size = 4;
- } else {
- attr_value->type = DWARF_VALUE_U32;
- attr_value->u32 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- attr_value->encoded_size = 8;
- }
- } else {
- if (addr_sizeof_ == 4) {
- attr_value->type = DWARF_VALUE_U32;
- attr_value->u32 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- } else {
- attr_value->type = DWARF_VALUE_U64;
- attr_value->u64 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Xword*>(prop));
- }
- attr_value->encoded_size = addr_sizeof_;
- }
- break;
-
- /* Reference to a section, other than .debug_info, or .debug_str */
- case DW_FORM_sec_offset:
- if (elf_file_->is_DWARF_64()) {
- attr_value->type = DWARF_VALUE_U64;
- attr_value->u64 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Xword*>(prop));
- attr_value->encoded_size = 4;
- } else {
- attr_value->type = DWARF_VALUE_U32;
- attr_value->u32 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- attr_value->encoded_size = 8;
- }
- break;
-
- /* This is a replacement for DW_FORM_flag, which doesn't consume memory
- * in .debug_info section, and only by the fact of its existence it is
- * equal to DW_FORM_flag with value set to 1. */
- case DW_FORM_flag_present:
- attr_value->type = DWARF_VALUE_U8;
- attr_value->u8 = 1;
- attr_value->encoded_size = 0;
- break;
-
- /* Encodes the actual form to be used. */
- case DW_FORM_indirect:
- // Starts with ULEB128
- prop = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>
- (prop)->process_unsigned(&tmp_val));
- /* ULEB128 encodes the actual form to be used to process this entry. */
- process_attrib(prop, tmp_val.u16, attr_value);
- attr_value->encoded_size += tmp_val.encoded_size;
- break;
-
- /* This form is defined for DWARF4, and has no documentation whatsoever. */
- case DW_FORM_exprloc:
- default:
- attr_value->type = DWARF_VALUE_U32;
- attr_value->u32 =
- elf_file_->pull_val(reinterpret_cast<const Elf_Word*>(prop));
- attr_value->encoded_size = 4;
- break;
- }
-
- return prop + attr_value->encoded_size;
-}
-
-void DwarfCU::dump() const {
- printf("\n\n>>>>>>>>>>>>>>> CU %p (version %u, address size %u)\n",
- cu_die_->die(), static_cast<Elf_Word>(version_),
- static_cast<Elf_Word>(addr_sizeof_));
- printf(">>>>> Build dir path: %s\n", comp_dir_path());
- printf(">>>>> Build file path: %s\n", rel_cu_path());
- if (cu_die_ != NULL) {
- cu_die_->dump(false);
- }
-}
-
-//=============================================================================
-// DwarfCUImpl implementation
-//=============================================================================
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::DwarfCUImpl(ElfFile* elf,
- const Dwarf_CUHdr* hdr)
- : DwarfCU(elf),
- cu_header_(hdr) {
- /* Cache CU's DIE abbreviation descriptor in the array. This MUST be done
- * BEFORE first call to array's cache_to() method. */
- const Dwarf_Abbr_DIE* cu_abbr_die = reinterpret_cast<const Dwarf_Abbr_DIE*>
- (INC_CPTR(elf->get_debug_abbrev_data(),
- elf->pull_val(hdr->abbrev_offset)));
- abbrs_.add(cu_abbr_die);
-
- cu_size_ = elf->pull_val(hdr->size_hdr.size);
- version_ = elf->pull_val(hdr->version);
- addr_sizeof_ = hdr->address_size;
- memset(&stmtl_header_, 0, sizeof(stmtl_header_));
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-bool DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::parse(
- const DwarfParseContext* parse_context,
- const void** next_cu_die) {
- /* Start parsing with the DIE for this CU. */
- if (process_DIE(parse_context, get_DIE(), NULL) == NULL) {
- return false;
- }
-
- /* CU area size (thus, next CU header offset) in .debug_info section equals
- * to CU size, plus number of bytes, required to encode CU size in CU header
- * (4 for 32-bit CU, and 12 for 64-bit CU. */
- *next_cu_die =
- INC_CPTR(cu_header_, cu_size_ + ELFF_FIELD_OFFSET(Dwarf_CUHdr, version));
-
- return true;
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-const Elf_Byte* DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::process_DIE(
- const DwarfParseContext* parse_context,
- const Dwarf_DIE* die,
- DIEObject* parent_obj) {
- while (is_attrib_ptr_valid(die) && !die->is_separator()) {
- Dwarf_AbbrNum abbr_num;
- Dwarf_Tag die_tag;
- Elf_Word sibling_off = 0;
-
- /* Get DIE's abbreviation number, and advance to DIE's properties. */
- const Elf_Byte* die_attr = die->process(&abbr_num);
-
- /* Get abbreviation for the current DIE. */
- const Dwarf_Abbr_DIE* die_abbr = abbrs_.cache_to(abbr_num);
- if (die_abbr == NULL) {
- return NULL;
- }
-
- /* Get base DIE properties, and advance to the DIE's
- * attribute descriptors. */
- const Dwarf_Abbr_AT* at_abbr = die_abbr->process(NULL, &die_tag);
-
- /* Instantiate DIE object for this DIE, and get list of properties,
- * that should be collected while processing that DIE. */
- DIEObject* die_obj =
- create_die_object(parse_context, die, parent_obj, die_tag);
- if (die_obj == NULL && errno != 0) {
- return NULL;
- }
-
- if (die_obj != NULL) {
- if (parent_obj != NULL) {
- /* Update list of parent's children. */
- die_obj->link_sibling(parent_obj->last_child());
- parent_obj->link_child(die_obj);
- } else {
- /* NULL parent object is allowed only for CU DIE itself. */
- assert(cu_die_ == NULL && die_tag == DW_TAG_compile_unit);
- if (cu_die_ == NULL && die_tag != DW_TAG_compile_unit) {
- _set_errno(EINVAL);
- return NULL;
- }
- cu_die_ = die_obj;
- /* This CU DIE object will be used as a parent for all DIE
- * objects, created in this method. */
- parent_obj = cu_die_;
- }
- }
-
- // Loop through all DIE properties.
- while (elf_file_->is_valid_abbr_ptr(at_abbr, sizeof(Dwarf_Abbr_AT)) &&
- !at_abbr->is_separator()) {
- Dwarf_At at_value;
- Dwarf_Form at_form;
- Dwarf_Value attr_value;
-
- // Obtain next property value.
- at_abbr = at_abbr->process(&at_value, &at_form);
- die_attr = process_attrib(die_attr, at_form, &attr_value);
-
- if (at_value == DW_AT_sibling) {
- /* DW_AT_sibling means that next DIE is a child of the one that's
- * being currently processed. We need to cache value of this property
- * in order to correctly calculate next sibling of this DIE after
- * child's DIE has been processed. */
- assert(sibling_off == 0);
- sibling_off = attr_value.u32;
- }
- }
-
- /* Next DIE immediately follows last property for the current DIE. */
- die = reinterpret_cast<const Dwarf_DIE*>(die_attr);
- if (sibling_off != 0) {
- // Process child DIE.
- process_DIE(parse_context, die, die_obj != NULL ? die_obj : parent_obj);
- // Next sibling DIE offset is relative to this CU's header beginning.
- die = INC_CPTR_T(Dwarf_DIE, cu_header_, sibling_off);
- }
- }
-
- return INC_CPTR_T(Elf_Byte, die, 1);
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-DIEObject* DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::create_die_object(
- const DwarfParseContext* parse_context,
- const Dwarf_DIE* die,
- DIEObject* parent,
- Dwarf_Tag tag) {
- DIEObject* ret = NULL;
-
- /* We will always create a DIE object for CU DIE. */
- if (tag == DW_TAG_compile_unit || collect_die(parse_context, tag)) {
- ret = new(elf_file_) DIEObject(die, this, parent);
- assert(ret != NULL);
- if (ret == NULL) {
- _set_errno(ENOMEM);
- }
- } else {
- _set_errno(0);
- }
- return ret;
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-bool DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::init_stmtl() {
- if (stmtl_header_.unit_length != 0) {
- return true;
- }
-
- assert(cu_die_ != NULL);
- if (cu_die_ == NULL) {
- _set_errno(EINVAL);
- return false;
- }
-
- DIEAttrib stmtl;
- if (!cu_die()->get_attrib(DW_AT_stmt_list, &stmtl)) {
- _set_errno(EINVAL);
- return false;
- }
-
- const void* stmtl_start =
- INC_CPTR(elf_file()->get_debug_line_data(), stmtl.value()->u32);
- if (*reinterpret_cast<const Elf_Word*>(stmtl_start) == 0xFFFFFFFF) {
- cache_stmtl<Dwarf64_STMTLHdr>(reinterpret_cast<const Dwarf64_STMTLHdr*>(stmtl_start));
- } else {
- cache_stmtl<Dwarf32_STMTLHdr>(reinterpret_cast<const Dwarf32_STMTLHdr*>(stmtl_start));
- }
-
- return true;
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-bool DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::get_pc_address_file_info(
- Elf_Xword address,
- Dwarf_AddressInfo* info) {
- /* Make sure STMTL header is cached. */
- if (!init_stmtl()) {
- return false;
- }
- /* Flags address match, that should trigger return next time
- * source line gets adjusted. */
- bool found = false;
- /* Create new state machine. */
- DwarfStateMachine state(stmtl_header_.default_is_stmt != 0);
-
- /* Start the "Line Number Program" */
- const Elf_Byte* go = stmtl_header_.start;
- while (go < stmtl_header_.end) {
- const Elf_Byte op = *go;
- go++;
-
- if (op == 0) {
- /* This is an extended opcode. */
- Dwarf_Value op_size;
-
- /* First ULEB128 contains opcode size, (excluding ULEB128 itself). */
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_unsigned(&op_size));
- /* Next is the extended opcode. */
- const Elf_Byte* ex_op_ptr = go;
- switch (*ex_op_ptr) {
- case DW_LNE_end_sequence:
- state.end_sequence_ = true;
- state.reset(stmtl_header_.default_is_stmt != 0);
- found = false;
- break;
-
- case DW_LNE_set_address: {
- Elf_Xword prev_address = state.address_;
- if (is_CU_address_64()) {
- state.address_ =
- elf_file()->pull_val(reinterpret_cast<const Elf_Xword*>(ex_op_ptr + 1));
- } else {
- state.address_ =
- elf_file()->pull_val(reinterpret_cast<const Elf_Word*>(ex_op_ptr + 1));
- }
- if (prev_address != 0 &&
- address >= prev_address && address < state.address_) {
- return set_source_info(&state, info);
- } else if (address == state.address_) {
- found = true;
- }
- break;
- }
-
- case DW_LNE_define_file: {
- /* Parameters start with the directly encoded zero-terminated
- * file name. */
- state.set_file_info_ = INC_CPTR_T(Dwarf_STMTL_FileDesc, ex_op_ptr, 1);
- assert(state.set_file_info_ != NULL);
- if (state.set_file_info_ != NULL) {
- ex_op_ptr = reinterpret_cast<const Elf_Byte*>(state.set_file_info_->process(NULL));
- }
- break;
- }
-
- case DW_LNE_set_discriminator: {
- Dwarf_Value discr_val;
- /* One parameter: discriminator's ULEB128 value. */
- reinterpret_cast<const Dwarf_Leb128*>(ex_op_ptr + 1)->process_unsigned(&discr_val);
- state.discriminator_ = discr_val.u32;
- break;
- }
-
- default:
- assert(0);
- return false;
- }
- go += op_size.u32;
- } else if (op < stmtl_header_.opcode_base) {
- /* This is a standard opcode. */
- switch (op) {
- case DW_LNS_copy:
- /* No parameters. */
- state.basic_block_ = false;
- state.prologue_end_ = false;
- state.epilogue_begin_ = false;
- break;
-
- case DW_LNS_advance_pc: {
- /* One parameter: ULEB128 value to add to the current address value
- * in the state machine. */
- Dwarf_Value addr_add;
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_unsigned(&addr_add));
- Elf_Xword prev_address = state.address_;
- state.address_ += addr_add.u64;
- if (prev_address != 0 &&
- address >= prev_address && address < state.address_) {
- return set_source_info(&state, info);
- } else if (address == state.address_) {
- found = true;
- }
- break;
- }
-
- case DW_LNS_advance_line: {
- /* One parameter: signed LEB128 value to add to the current line
- * number in the state machine. */
- Dwarf_Value line_add;
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_signed(&line_add));
- state.line_ += line_add.s32;
- if (found) {
- return set_source_info(&state, info);
- }
- break;
- }
-
- case DW_LNS_set_file: {
- /* One parameter: ULEB128 value encoding current file number. */
- Dwarf_Value file_num;
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_unsigned(&file_num));
- state.file_ = file_num.u32;
- /* This operation should discard previously saved file information. */
- state.set_file_info_ = NULL;
- break;
- }
-
- case DW_LNS_set_column: {
- /* One parameter: ULEB128 value encoding current column number. */
- Dwarf_Value column_num;
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_unsigned(&column_num));
- state.column_ = column_num.u32;
- break;
- }
-
- case DW_LNS_negate_stmt:
- /* No parameters. */
- state.is_stmt_ = !state.is_stmt_;
- break;
-
- case DW_LNS_set_basic_block:
- /* No parameters. */
- state.basic_block_ = true;
- break;
-
- case DW_LNS_const_add_pc: {
- Elf_Xword prev_address = state.address_;
- /* No parameters. This operation does the same thing, as special
- * opcode 255 would do to the current address. */
- Elf_Word adjusted =
- static_cast<Elf_Word>(255) - stmtl_header_.opcode_base;
- state.address_ += (adjusted / stmtl_header_.line_range) *
- stmtl_header_.min_instruction_len;
- if (prev_address != 0 &&
- address >= prev_address && address < state.address_) {
- return set_source_info(&state, info);
- } else if (address == state.address_) {
- found = true;
- }
- break;
- }
-
- case DW_LNS_fixed_advance_pc: {
- Elf_Xword prev_address = state.address_;
- /* One parameter: directly encoded 16-bit value to add to the
- * current address. */
- state.address_ +=
- elf_file()->pull_val(reinterpret_cast<const Elf_Half*>(go));
- if (prev_address != 0 &&
- address >= prev_address && address < state.address_) {
- return set_source_info(&state, info);
- } else if (address == state.address_) {
- found = true;
- }
- go += sizeof(Elf_Half);
- break;
- }
-
- case DW_LNS_set_prologue_end:
- /* No parameters. */
- state.prologue_end_ = true;
- break;
-
- case DW_LNS_set_epilogue_begin:
- /* No parameters. */
- state.epilogue_begin_ = true;
- break;
-
- case DW_LNS_set_isa: {
- /* One parameter: ISA value encoded as ULEB128. */
- Dwarf_Value isa_val;
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_unsigned(&isa_val));
- state.isa_ = isa_val.u32;
- break;
- }
-
- default:
- /* Unknown opcode. Just skip it. */
- for (Elf_Byte uleb = 0;
- uleb < stmtl_header_.standard_opcode_lengths[op - 1]; uleb++) {
- Dwarf_Value tmp;
- go = reinterpret_cast<const Elf_Byte*>
- (reinterpret_cast<const Dwarf_Leb128*>(go)->process_unsigned(&tmp));
- }
- break;
- }
- } else {
- Elf_Xword prev_address = state.address_;
- /* This is a special opcode. */
- const Elf_Word adjusted = op - stmtl_header_.opcode_base;
- /* Advance address. */
- state.address_ += (adjusted / stmtl_header_.line_range) *
- stmtl_header_.min_instruction_len;
- if (prev_address != 0 &&
- address >= prev_address && address < state.address_) {
- return set_source_info(&state, info);
- }
- /* Advance line. */
- state.line_ += stmtl_header_.line_base +
- (adjusted % stmtl_header_.line_range);
- if (state.address_ == address) {
- return set_source_info(&state, info);
- }
- /* Do the woodoo. */
- state.basic_block_ = false;
- state.prologue_end_ = false;
- state.epilogue_begin_ = false;
- }
- }
-
- return false;
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-const Dwarf_STMTL_FileDesc* DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::get_stmt_file_info(
- Elf_Word index) {
- /* Index must be 1-based. */
- if (index == 0) {
- return NULL;
- }
-
- const Dwarf_STMTL_FileDesc* cur_desc = stmtl_header_.file_infos;
- while (index != 1 && !cur_desc->is_last_entry()) {
- cur_desc = cur_desc->process(NULL);
- index--;
- }
- assert(!cur_desc->is_last_entry());
- return cur_desc->is_last_entry() ? NULL : cur_desc;
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-const char* DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::get_stmt_dir_name(
- Elf_Word dir_index) {
- if (dir_index == 0) {
- /* Requested is current compilation directory. */
- return comp_dir_path();
- }
- if (dir_index > stmtl_header_.inc_dir_num) {
- return NULL;
- }
-
- const char* cur_dir = stmtl_header_.include_directories;
- while (dir_index != 1) {
- cur_dir += strlen(cur_dir) + 1;
- dir_index--;
- }
- return cur_dir;
-}
-
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-bool DwarfCUImpl<Dwarf_CUHdr, Dwarf_Off>::set_source_info(
- const DwarfStateMachine* state,
- Dwarf_AddressInfo* info) {
- info->line_number = state->line_;
- const Dwarf_STMTL_FileDesc* file_info = state->set_file_info_;
- if (file_info == NULL) {
- file_info = get_stmt_file_info(state->file_);
- if (file_info == NULL) {
- info->file_name = rel_cu_path();
- info->dir_name = comp_dir_path();
- return true;
- }
- }
- info->file_name = file_info->get_file_name();
- const Elf_Word dir_index = file_info->get_dir_index();
- info->dir_name = get_stmt_dir_name(dir_index);
- return true;
-}
-
diff --git a/distrib/elff/elff/dwarf_cu.h b/distrib/elff/elff/dwarf_cu.h
deleted file mode 100644
index 425ecd9..0000000
--- a/distrib/elff/elff/dwarf_cu.h
+++ /dev/null
@@ -1,513 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declaration of a class DwarfCU, that encapsulates a compilation
- * unit in the .debug_info section of the mapped ELF file.
- */
-
-#ifndef ELFF_DWARF_CU_H_
-#define ELFF_DWARF_CU_H_
-
-#include "elff/dwarf_defs.h"
-#include "elff/dwarf_die.h"
-
-/* Address information descriptor. */
-typedef struct Dwarf_AddressInfo {
- /* Routine DIE containing the address. */
- const DIEObject* die_obj;
-
- /* Source file name for the address. */
- const char* file_name;
-
- /* Source file directory path for the address. */
- const char* dir_name;
-
- /* Source file line number for the address. */
- Elf_Word line_number;
-} Dwarf_AddressInfo;
-
-/* STMTL header cached by compilation unit. This header is contained in
- * the .debug_line section of the ELF file. */
-typedef struct Dwarf_STMTL_Hdr {
- /* The size in bytes of the line number information for this compilation
- * unit, not including the unit_length field itself. */
- Elf_Xword unit_length;
-
- /* A version number. This number is specific to the line number information
- * and is independent of the DWARF version number. */
- Elf_Half version;
-
- /* The number of bytes following the header_length field to the beginning of
- * the first byte of the line number program itself. In the 32-bit DWARF
- * format, this is a 4-byte unsigned length; in the 64-bit DWARF format,
- * this field is an 8-byte unsigned length. */
- Elf_Xword header_length;
-
- /* The size in bytes of the smallest target machine instruction. Line number
- * program opcodes that alter the address register first multiply their
- * operands by this value. */
- Elf_Byte min_instruction_len;
-
- /* The initial value of the is_stmt register. */
- Elf_Byte default_is_stmt;
-
- /* This parameter affects the meaning of the special opcodes. */
- Elf_Sbyte line_base;
-
- /* This parameter affects the meaning of the special opcodes. */
- Elf_Byte line_range;
-
- /* The number assigned to the first special opcode. */
- Elf_Byte opcode_base;
-
- /* Points to standard_opcode_lengths array in the actual STMTL header in
- * the mapped .debug_line section. */
- const Elf_Byte* standard_opcode_lengths;
-
- /* Pointer to the beginning of the list of include directories in the mapped
- * .debug_line section. */
- const char* include_directories;
-
- /* Number of include directories in the list that begins with
- * include_directories. */
- Elf_Word inc_dir_num;
-
- /* Pointer to the beginning of the list of file information in the mapped
- * .debug_line section. Each entry in this list begins with zero-terminated
- * file name, followed by ULEB128 encoding directory index for the file,
- * followed by ULEB128 encoding last modification time, followed by ULEB128
- * encoding length of file in bytes. */
- const Dwarf_STMTL_FileDesc* file_infos;
-
- /* Start of the "Line Number Program" in the mapped .debug_line section. */
- const Elf_Byte* start;
-
- /* End of the "Line Number Program" in the mapped .debug_line section. */
- const Elf_Byte* end;
-} Dwarf_STMTL_Hdr;
-
-/* Encapsulates architecture-independent functionality of a
- * compilation unit.
- */
-class DwarfCU : public DwarfAllocBase {
-friend class ElfFile;
- public:
- /* Constructs DwarfCU instance.
- * Param:
- * elf - Instance of ElfFile containing this compilation unit.
- */
- explicit DwarfCU(ElfFile* elf);
-
- /* Destructs DwarfCU instance. */
- virtual ~DwarfCU();
-
- /* Creates DwarfCUImpl instance, depending on DWARF format.
- * Param:
- * elf - Instance of ElfFile containing this compilation unit.
- * hdr - Pointer to compilation unit header inside mapped .debug_info
- * section of the ELF file. Actual data addressed by this pointer
- * must be Dwarf32_CUHdr for 32 bit DWARFs, or Dwarf64_CUHdr for
- * 64 bit DWARFs.
- * Return:
- * Created DwarfCUImpl instance (typecasted back to DwarfCU) on success,
- * or NULL on failure.
- */
- static DwarfCU* create_instance(ElfFile* elf, const void* hdr);
-
- /* Process a DIE attribute.
- * Param:
- * attr - Attribute list inside the mapped .debug_info section of the ELF
- * file.
- * form - Attribute's form, definig representation of attribute value in the
- * mapped .debug_info section of the ELF file.
- * attr_value - Upon return contains attribute value.
- * Return:
- * Pointer to the next DIE attribute inside the mapped .debug_info section
- * of the ELF file.
- */
- const Elf_Byte* process_attrib(const Elf_Byte* attr,
- Dwarf_Form form,
- Dwarf_Value* attr_value) const;
-
- /* Dumps this compilation unit to the stdout. */
- void dump() const;
-
- /* Gets instance of ElfFile containing this compilation unit. */
- ElfFile* elf_file() const {
- return elf_file_;
- }
-
- /* Gets DIE object for this CU. */
- DIEObject* cu_die() const {
- return cu_die_;
- }
-
- /* Gets byte size of the pointer type for this compilation unit. */
- Elf_Byte addr_sizeof() const {
- return addr_sizeof_;
- }
-
- /* Gets full path to the compilation directory (DW_AT_comp_dir attribute).
- * Return:
- * Full path to the compilation directory (DW_AT_comp_dir attribute),
- * or NULL, if that attribute was missing in CU's attribute list.
- */
- const char* comp_dir_path() const {
- DIEAttrib attr;
- return cu_die()->get_attrib(DW_AT_comp_dir, &attr) ? attr.value()->str :
- NULL;
- }
-
- /* Gets relative (from the compilation directory) path to the compiled file.
- * (DW_AT_name attribute).
- * Return:
- * Relative path to the compiled file (DW_AT_name attribute), or NULL, if
- * that attribute was missing in CU's attribute list.
- */
- const char* rel_cu_path() const {
- DIEAttrib attr;
- return cu_die()->get_attrib(DW_AT_name, &attr) ? attr.value()->str :
- NULL;
- }
-
- /* Gets next compilation unit in the list. NULL indicates the last CU. */
- DwarfCU* prev_cu() const {
- return prev_cu_;
- }
-
- /* Links this CU to the list of prevoiusly discovered CUs. */
- void set_prev_cu(DwarfCU* prev) {
- prev_cu_ = prev;
- }
-
- /* Checks if DWARF version for this CU is higher than 2. */
- bool is_DWARF3_or_higher() const {
- return version_ >= 3;
- }
-
- /* Gets DIE abbreviation for given abbreviation number.
- * See DwarfAbbrDieArray::get() */
- const Dwarf_Abbr_DIE* get_die_abbr(Dwarf_AbbrNum num) const {
- return abbrs_.get(num);
- }
-
- /* Gets DIE object containing given address.
- * DIE address ranges may overlap (for instance, address range for an inlined
- * routine will be contained within the address range of a routine where it
- * was inlined). This method will return a DIE object that is a "leaf" in
- * that inlining tree. I.e the returned DIE object represents the last DIE
- * in the branch of all DIEs containing given address.
- * Param:
- * address - Address to get a DIE for. NOTE: for the sake of simplicity we
- * explicitly use 64-bit type for an address.
- * Return:
- * Leaf DIE containing given address, or NULL if this CU doesn't contain
- * the given address.
- */
- DIEObject* get_leaf_die_for_address(Elf_Xword address) const {
- return cu_die_->get_leaf_for_address(address);
- }
-
- /* Checks if this CU contains 64, or 32-bit addresses. */
- bool is_CU_address_64() const {
- return addr_sizeof_ == 8;
- }
- bool is_CU_address_32() const {
- return addr_sizeof_ == 4;
- }
-
-//=============================================================================
-// DWARF format dependent methods
-//=============================================================================
-
- public:
- /* Parses this compilation unit in .debug_info section, collecting children
- * DIEs of this compilation unit.
- * Param:
- * parse_context - Parsing context that lists tags for DIEs that should be
- * collected during parsing. NULL passed in this parameter indicates DIEs
- * for all tags should be collected.
- * next_cu_die - Upon successful return contains pointer to the next
- * compilation unit descriptor inside mapped .debug_info section of
- * the ELF file.
- * Return:
- * true on success, false on failure.
- */
- virtual bool parse(const DwarfParseContext* parse_context,
- const void** next_cu_die) = 0;
-
- /* Gets a DIE object referenced by an offset from the beginning of
- * this CU in the mapped .debug_info section.
- */
- virtual DIEObject* get_referenced_die_object(Elf_Word ref) const = 0;
-
- /* Gets a reference to a DIE object (offset of the DIE from the
- * beginning of this CU in the mapped .debug_info section.
- */
- virtual Elf_Word get_die_reference(const Dwarf_DIE* die) const = 0;
-
- /* Gets PC address information.
- * Param:
- * address - PC address to get information for.
- * info - Upon success contains information about routine that belongs to
- * this compilation unit, containing the given address.
- * Return:
- * true on success, or false if this CU doesn't contain the given address.
- */
- virtual bool get_pc_address_file_info(Elf_Xword address,
- Dwarf_AddressInfo* info) = 0;
-
- /* Gets file descriptor in the mapped .debug_line section of ELF file for a
- * given index in the file descriptor list.
- * Param:
- * index - 1-based index of file descriptor in the file descriptor list.
- * Return:
- * File descriptor for the given index, or NULL if index was too big.
- * NOTE: pointer returned from this method addressed mapped section of
- * ELF file.
- */
- virtual const Dwarf_STMTL_FileDesc* get_stmt_file_info(Elf_Word index) = 0;
-
- /* Gets directory name by an index in the mapped .debug_line section of
- * ELF file.
- * Param:
- * dir_index - Index of the directory in the file descriptor list. If this
- * parameter is zero, compilation directory (DW_AT_comp_dir) for this CU
- * will be returned.
- * Return:
- * Directory name for the given index, or NULL if index was too big.
- * NOTE: pointer returned from this method addressed mapped section of
- * ELF file.
- */
- virtual const char* get_stmt_dir_name(Elf_Word dir_index) = 0;
-
- protected:
- /* DIE abbreviation descriptors, cached for this compilation unit. */
- DwarfAbbrDieArray abbrs_;
-
- /* Instance of an ELF file that contains this compilation unit. */
- ElfFile* elf_file_;
-
- /* DIE object for this CU. */
- DIEObject* cu_die_;
-
- /* Next compilation unit in the list (previous in the order they've been
- * discovered during ELF file parsing).
- */
- DwarfCU* prev_cu_;
-
- /* DWARF version for this CU. */
- Elf_Half version_;
-
- /* Byte size of the pointer type for this compilation unit. */
- Elf_Byte addr_sizeof_;
-};
-
-/* Encapsulates architecture-dependent functionality of a compilation unit.
- * Template param:
- * Dwarf_CUHdr - type compilation unit header in the mapped .debug_info
- * section of ELF file. Must be:
- * - Dwarf32_CUHdr for 32-bit DWARF, or
- * - Dwarf64_CUHdr for 64-bit DWARF.
- * Dwarf_Off - type for an offset field in DWARF data format. Must be:
- * - Dwarf32_Off for 32-bit DWARF, or
- * - Dwarf64_Off for 64-bit DWARF.
- */
-template <typename Dwarf_CUHdr, typename Dwarf_Off>
-class DwarfCUImpl : public DwarfCU {
- public:
- /* Constructs DwarfCU instance.
- * Param:
- * elf - Instance of ElfFile containing this compilation unit.
- * hdr - Pointer to compilation unit header inside mapped .debug_info
- * section of the ELF file.
- */
- DwarfCUImpl(ElfFile* elf, const Dwarf_CUHdr* hdr);
-
- /* Destructs DwarfCU instance. */
- ~DwarfCUImpl() {
- }
-
- /* Parses this compilation unit in .debug_info section, collecting children
- * DIEs of this compilation unit. This is an implementation of DwarfCU's
- * abstract metod.
- * See DwarfCU::parse().
- */
- bool parse(const DwarfParseContext* parse_context,
- const void** next_cu_die);
-
- /* Gets PC address information.
- * This is an implementation of DwarfCU's abstract metod.
- * See DwarfCU::get_pc_address_file_info().
- */
- bool get_pc_address_file_info(Elf_Xword address, Dwarf_AddressInfo* info);
-
- /* Gets file descriptor in the mapped .debug_line section of ELF file for a
- * given index in the file descriptor list.
- * This is an implementation of DwarfCU's abstract metod.
- * See DwarfCU::get_stmt_file_info().
- */
- const Dwarf_STMTL_FileDesc* get_stmt_file_info(Elf_Word index);
-
- /* Gets directory name by an index in the mapped .debug_line section of
- * ELF file.
- * This is an implementation of DwarfCU's abstract metod.
- * See DwarfCU::get_stmt_dir_name().
- */
- const char* get_stmt_dir_name(Elf_Word dir_index);
-
- /* Gets a DIE object referenced by an offset from the beginning of
- * this CU. This is an implementation of DwarfCU's abstract metod.
- */
- DIEObject* get_referenced_die_object(Elf_Word ref) const {
- const Dwarf_DIE* die = get_referenced_die(ref);
- return cu_die_->find_die_object(die);
- }
-
- /* Gets a reference to a DIE object (offset of the DIE from the
- * beginning of this CU in the mapped .debug_info section.
- * This is an implementation of DwarfCU's abstract metod.
- */
- Elf_Word get_die_reference(const Dwarf_DIE* die) const {
- return static_cast<Elf_Word>(diff_ptr(cu_header_, die));
- }
-
- protected:
- /* Process a child DIE (and all its children) in this compilation unit.
- * Param:
- * parse_context - See DwarfCU::parse().
- * die - DIE descriptor of the child to process in this method.
- * parent_obj - Parent object of the child to process in this method.
- * NOTE: this parameter can be NULL only for a DIE that represents this
- * compilation unit itself.
- * Return:
- * Pointer to the end of child's attribute list in the mapped .debug_info
- * section on success, or NULL on failure. Usually, pointer returned from
- * this method is simply discarded, since parent calculates address of the
- * next sibling's DIE based on DW_AT_sibling attribute of the DIE preceding
- * child's DIE.
- */
- const Elf_Byte* process_DIE(const DwarfParseContext* parse_context,
- const Dwarf_DIE* die,
- DIEObject* parent_obj);
-
- /* Creates a DIE object for the given DIE.
- * Param:
- * parse_context See DwarfCU::parse().
- * die - DIE to create an object for.
- * parent - Parent DIE object for the one that's being created in this
- * method.
- * tag - Tag of the DIE object that's being created in this method.
- * Return:
- * Created DIE object. This method may returns NULL in two cases:
- * - We're not interested in this DIE (decided by looking at 'tag'
- * parameter. In this case errno should be set to zero.
- * - Memory allocation has failed. In this case errno should be
- * set to ENOMEM.
- */
- DIEObject* create_die_object(const DwarfParseContext* parse_context,
- const Dwarf_DIE* die,
- DIEObject* parent,
- Dwarf_Tag tag);
-
- /* Initializes (caches) STMT lines header for this CU. */
- bool init_stmtl();
-
- /* Saves current source file information, collected in the state machine by
- * the "Line Number Program".
- * Param:
- * state - State machine collected "Line Number Program" results.
- * info - Upon success contains source file information, copied over from
- * the state machine.
- * Return:
- * true on success, or false on failure.
- */
- bool set_source_info(const DwarfStateMachine* state,
- Dwarf_AddressInfo* info);
-
- /* Gets pointer to the DIE descriptor for this CU. */
- const Dwarf_DIE* get_DIE() const {
- /* CU's DIE descriptor immediately follows CU header. */
- return INC_CPTR_T(Dwarf_DIE, cu_header_, sizeof(Dwarf_CUHdr));
- }
-
- /* Caches STMTL header from .debug_line section to stmtl_header_.
- * Template param:
- * Dwarf_STMTL_Hdr - Dwarf_STMTL_Hdr32, or Dwarf_STMTL_Hdr64, depending
- * on the header type.
- * Param:
- * stmtl_hdr - STMTL header in the mapped .debug_line section to cache.
- */
- template <typename Dwarf_STMTL_Hdr>
- void cache_stmtl(const Dwarf_STMTL_Hdr* stmtl_hdr) {
- stmtl_header_.unit_length = elf_file()->pull_val(stmtl_hdr->unit_length.size);
- stmtl_header_.version = elf_file()->pull_val(stmtl_hdr->version);
- stmtl_header_.header_length = elf_file()->pull_val(stmtl_hdr->header_length);
- stmtl_header_.min_instruction_len = stmtl_hdr->min_instruction_len;
- stmtl_header_.default_is_stmt = stmtl_hdr->default_is_stmt;
- stmtl_header_.line_base = stmtl_hdr->line_base;
- stmtl_header_.line_range = stmtl_hdr->line_range;
- stmtl_header_.opcode_base = stmtl_hdr->opcode_base;
- stmtl_header_.standard_opcode_lengths = &stmtl_hdr->standard_opcode_lengths;
- stmtl_header_.start = INC_CPTR_T(Elf_Byte, &stmtl_hdr->min_instruction_len,
- stmtl_header_.header_length);
- stmtl_header_.end = INC_CPTR_T(Elf_Byte, &stmtl_hdr->version,
- stmtl_header_.unit_length);
- stmtl_header_.include_directories =
- INC_CPTR_T(char, stmtl_header_.standard_opcode_lengths,
- stmtl_header_.opcode_base - 1);
- const char* dir = stmtl_header_.include_directories;
- while (*dir != '\0') {
- dir += strlen(dir) + 1;
- stmtl_header_.inc_dir_num++;
- }
- stmtl_header_.file_infos = INC_CPTR_T(Dwarf_STMTL_FileDesc, dir, 1);
- }
-
- /* Gets a DIE referenced by an offset from the beginning of this CU
- * in the mapped .debug_info section.
- */
- const Dwarf_DIE* get_referenced_die(Elf_Word ref) const {
- return INC_CPTR_T(Dwarf_DIE, cu_header_, ref);
- }
-
- /* Checks if pointer to the DIE attribute is contained within the CU's area
- * of the mapped .debug_info section.
- * Param:
- * ptr - Pointer to the DIE attribute to check.
- * Return:
- * true, if pointer to the DIE attribute is contained within the CU's area
- * of the mapped .debug_info section, or false if attribute pointer goes
- * beyond CU's area of the mapped .debug_info section.
- */
- bool is_attrib_ptr_valid(const void* ptr) const {
- return diff_ptr(cu_header_, ptr) < cu_size_;
- }
-
- protected:
- /* Pointer to this compilation unit header inside the mapped .debug_info
- * section of the ELF file.
- */
- const Dwarf_CUHdr* cu_header_;
-
- /* Size of this compilation unit area in the mapped .debug_info section.
- * This value has been cached off the CU header in order to avoid
- * endianness conversions.
- */
- Dwarf_Off cu_size_;
-
- /* STMT lines header, cached off mapped .debug_line section. */
- Dwarf_STMTL_Hdr stmtl_header_;
-};
-
-#endif // ELFF_DWARF_CU_H_
diff --git a/distrib/elff/elff/dwarf_defs.h b/distrib/elff/elff/dwarf_defs.h
deleted file mode 100644
index 7516e7b..0000000
--- a/distrib/elff/elff/dwarf_defs.h
+++ /dev/null
@@ -1,1000 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of types, constants and structures
- * describing DWARF format.
- */
-
-#ifndef ELFF_DWARF_DEFS_H_
-#define ELFF_DWARF_DEFS_H_
-
-#include "elff/dwarf.h"
-#include "elff/elf_defs.h"
-
-/* DWARF structures are packed to 1 byte. */
-#define ELFF_PACKED __attribute__ ((packed))
-
-/*
- * Helper types for misc. DWARF variables.
- */
-
-/* Type for DWARF abbreviation number. */
-typedef uint32_t Dwarf_AbbrNum;
-
-/* Type for DWARF tag ID. */
-typedef uint16_t Dwarf_Tag;
-
-/* Type for DWARF attribute ID. */
-typedef uint16_t Dwarf_At;
-
-/* Type for DWARF form ID. */
-typedef uint16_t Dwarf_Form;
-
-/* Type for offset in 32-bit DWARF. */
-typedef uint32_t Dwarf32_Off;
-
-/* Type for offset in 64-bit DWARF. */
-typedef uint64_t Dwarf64_Off;
-
-/* Enumerates types of values, obtained during DWARF attribute decoding. */
-typedef enum DwarfValueType {
- /* Undefined */
- DWARF_VALUE_UNKNOWN = 1,
-
- /* uint8_t */
- DWARF_VALUE_U8,
-
- /* int8_t */
- DWARF_VALUE_S8,
-
- /* uint16_t */
- DWARF_VALUE_U16,
-
- /* int16_t */
- DWARF_VALUE_S16,
-
- /* uint32_t */
- DWARF_VALUE_U32,
-
- /* int32_t */
- DWARF_VALUE_S32,
-
- /* uint64_t */
- DWARF_VALUE_U64,
-
- /* int64_t */
- DWARF_VALUE_S64,
-
- /* const char* */
- DWARF_VALUE_STR,
-
- /* 32-bit address */
- DWARF_VALUE_PTR32,
-
- /* 64-bit address */
- DWARF_VALUE_PTR64,
-
- /* Dwarf_Block */
- DWARF_VALUE_BLOCK,
-} DwarfValueType;
-
-/* Describes block of data, stored directly in the mapped .debug_info
- * section. This type is used to represent an attribute encoded with
- * DW_FORM_block# form.
- */
-typedef struct Dwarf_Block {
- /* Pointer to the block data inside mapped .debug_info section. */
- const void* block_ptr;
-
- /* Byte size of the block data. */
- Elf_Word block_size;
-} Dwarf_Block;
-
-/* Describes a value, obtained from the mapped .debug_info section
- * during DWARF attribute decoding.
- */
-typedef struct Dwarf_Value {
- /* Unites all possible data types for the value.
- * See DwarfValueType for the list of types.
- */
- union {
- Elf_Byte u8;
- Elf_Sbyte s8;
- Elf_Half u16;
- Elf_Shalf s16;
- Elf_Word u32;
- Elf_Sword s32;
- Elf_Xword u64;
- Elf_Sxword s64;
- Elf_Word ptr32;
- Elf_Xword ptr64;
- const char* str;
- Dwarf_Block block;
- };
-
- /* Value type (defines which variable in the union abowe
- * contains the value).
- */
- DwarfValueType type;
-
- /* Number of bytes that encode this value in .debug_info section
- * of ELF file.
- */
- Elf_Word encoded_size;
-} Dwarf_Value;
-
-/* DWARF's LEB128 data type. LEB128 is defined as:
- * Variable Length Data. "Little Endian Base 128" (LEB128) numbers. LEB128 is
- * a scheme for encoding integers densely that exploits the assumption that
- * most integers are small in magnitude. (This encoding is equally suitable
- * whether the target machine architecture represents data in big-endian or
- * littleendian order. It is "little endian" only in the sense that it avoids
- * using space to represent the "big" end of an unsigned integer, when the big
- * end is all zeroes or sign extension bits).
- *
- * Unsigned LEB128 numbers are encoded as follows: start at the low order end
- * of an unsigned integer and chop it into 7-bit chunks. Place each chunk into
- * the low order 7 bits of a byte. Typically, several of the high order bytes
- * will be zero; discard them. Emit the remaining bytes in a stream, starting
- * with the low order byte; set the high order bit on each byte except the last
- * emitted byte. The high bit of zero on the last byte indicates to the decoder
- * that it has encountered the last byte. The integer zero is a special case,
- * consisting of a single zero byte.
- *
- * The encoding for signed LEB128 numbers is similar, except that the criterion
- * for discarding high order bytes is not whether they are zero, but whether
- * they consist entirely of sign extension bits. Consider the 32-bit integer
- * -2. The three high level bytes of the number are sign extension, thus LEB128
- * would represent it as a single byte containing the low order 7 bits, with
- * the high order bit cleared to indicate the end of the byte stream. Note that
- * there is nothing within the LEB128 representation that indicates whether an
- * encoded number is signed or unsigned. The decoder must know what type of
- * number to expect.
- *
- * NOTE: It's assumed that LEB128 will not contain encodings for integers,
- * larger than 64 bit.
-*/
-typedef struct ELFF_PACKED Dwarf_Leb128 {
- /* Beginning of the LEB128 block. */
- Elf_Byte val;
-
- /* Pulls actual value, encoded with this LEB128 block.
- * Param:
- * value - Upon return will contain value, encoded with this LEB128 block.
- * sign - If true, the caller expects the LEB128 to contain a signed
- * integer, otherwise, caller expects an unsigned integer value to be
- * encoded with this LEB128 block.
- */
- void get_common(Dwarf_Value* value, bool sign) const {
- value->u64 = 0;
- /* Integer zero is a special case. */
- if (val == 0) {
- value->type = sign ? DWARF_VALUE_S32 : DWARF_VALUE_U32;
- value->encoded_size = 1;
- return;
- }
-
- /* We've got to reconstruct the integer. */
- value->type = DWARF_VALUE_UNKNOWN;
- value->encoded_size = 0;
-
- /* Byte by byte loop though the LEB128, reconstructing the integer from
- * 7-bits chunks. Byte with 8-th bit set to zero indicates the end
- * of the LEB128 block. For signed integers, 7-th bit of the last LEB128
- * byte controls the sign. If 7-th bit of the last LEB128 byte is set,
- * the integer is negative. If 7-th bit of the last LEB128 byte is not
- * set, the integer is positive.
- */
- const Elf_Byte* cur = &val;
- Elf_Word shift = 0;
- while ((*cur & 0x80) != 0) {
- value->u64 |= (static_cast<Elf_Xword>(*cur) & 0x7F) << shift;
- shift += 7;
- value->encoded_size++;
- cur++;
- }
- value->u64 |= (static_cast<Elf_Xword>(*cur) & 0x7F) << shift;
- value->encoded_size++;
-
- /* LEB128 format doesn't carry any info of the sizeof of the integer it
- * represents. We well guess it, judging by the highest bit set in the
- * reconstucted integer.
- */
- if ((value->u64 & 0xFFFFFFFF00000000LL) == 0) {
- /* 32-bit integer. */
- if (sign) {
- value->type = DWARF_VALUE_S32;
- if (((*cur) & 0x40) != 0) {
- // Value is negative.
- value->u64 |= - (1 << (shift + 7));
- } else if ((value->u32 & 0x80000000) != 0) {
- // Make sure we don't report negative value in this case.
- value->type = DWARF_VALUE_S64;
- }
- } else {
- value->type = DWARF_VALUE_U32;
- }
- } else {
- /* 64-bit integer. */
- if (sign) {
- value->type = DWARF_VALUE_S64;
- if (((*cur) & 0x40) != 0) {
- // Value is negative.
- value->u64 |= - (1 << (shift + 7));
- }
- } else {
- value->type = DWARF_VALUE_U64;
- }
- }
- }
-
- /* Pulls actual unsigned value, encoded with this LEB128 block.
- * See get_common() for more info.
- * Param:
- * value - Upon return will contain unsigned value, encoded with
- * this LEB128 block.
- */
- void get_unsigned(Dwarf_Value* value) const {
- get_common(value, false);
- }
-
- /* Pulls actual signed value, encoded with this LEB128 block.
- * See get_common() for more info.
- * Param:
- * value - Upon return will contain signed value, encoded with
- * this LEB128 block.
- */
- void get_signed(Dwarf_Value* value) const {
- get_common(value, true);
- }
-
- /* Pulls LEB128 value, advancing past this LEB128 block.
- * See get_common() for more info.
- * Return:
- * Pointer to the byte past this LEB128 block.
- */
- const void* process(Dwarf_Value* value, bool sign) const {
- get_common(value, sign);
- return INC_CPTR(&val, value->encoded_size);
- }
-
- /* Pulls LEB128 unsigned value, advancing past this LEB128 block.
- * See process() for more info.
- */
- const void* process_unsigned(Dwarf_Value* value) const {
- return process(value, false);
- }
-
- /* Pulls LEB128 signed value, advancing past this LEB128 block.
- * See process() for more info.
- */
- const void* process_signed(Dwarf_Value* value) const {
- return process(value, true);
- }
-} Dwarf_Leb128;
-
-/* DIE attribute descriptor in the .debug_abbrev section.
- * Attribute descriptor contains two LEB128 values. First one provides
- * attribute ID (one of DW_AT_XXX values), and the second one provides
- * format (one of DW_FORMAT_XXX values), in which attribute value is
- * encoded in the .debug_info section of the ELF file.
- */
-typedef struct ELFF_PACKED Dwarf_Abbr_AT {
- /* Attribute ID (DW_AT_XXX).
- * Attribute format (DW_FORMAT_XXX) follows immediately.
- */
- Dwarf_Leb128 at;
-
- /* Checks if this is a separator descriptor.
- * Zero is an invalid attribute ID, indicating the end of attribute
- * list for the current DIE.
- */
- bool is_separator() const {
- return at.val == 0;
- }
-
- /* Pulls attribute data, advancing past this descriptor.
- * Param:
- * at_value - Upon return contains attribute value of this descriptor.
- * form - Upon return contains form value of this descriptor.
- * Return:
- * Pointer to the byte past this descriptor block (usually, next
- * attribute decriptor).
- */
- const Dwarf_Abbr_AT* process(Dwarf_At* at_value, Dwarf_Form* form) const {
- if (is_separator()) {
- /* Size of separator descriptor is always 2 bytes. */
- *at_value = 0;
- *form = 0;
- return INC_CPTR_T(Dwarf_Abbr_AT, &at.val, 2);
- }
-
- Dwarf_Value val;
-
- /* Process attribute ID. */
- const Dwarf_Leb128* next =
- reinterpret_cast<const Dwarf_Leb128*>(at.process_unsigned(&val));
- *at_value = val.u16;
-
- /* Follow with processing the form. */
- next = reinterpret_cast<const Dwarf_Leb128*>(next->process_unsigned(&val));
- *form = val.u16;
- return reinterpret_cast<const Dwarf_Abbr_AT*>(next);
- }
-} Dwarf_Abbr_AT;
-
-/* DIE abbreviation descriptor in the .debug_abbrev section.
- * DIE abbreviation descriptor contains three parameters. The first one is a
- * LEB128 value, that encodes 1 - based abbreviation descriptor number.
- * Abbreviation descriptor numbers seems to be always in sequential order, and
- * are counted on per-compilation unit basis. I.e. abbreviation number for the
- * first DIE abbreviation descriptor of each compilation unit is always 1.
- *
- * Besides abbreviation number, DIE abbreviation descriptor contains two more
- * values. The first one (after abbr_num) is a LEB128 value containing DIE's
- * tag value, and the second one is one byte flag specifying whether or not
- * the DIE contains any cildren.
- *
- * This descriptor is immediately followed by a list of attribute descriptors
- * (see Dwarf_Abbr_AT) for the DIE represented by this abbreviation descriptor.
- */
-typedef struct ELFF_PACKED Dwarf_Abbr_DIE {
- /* 1 - based abbreviation number for the DIE. */
- Dwarf_Leb128 abbr_num;
-
- /* Gets abbreviation number for this descriptor. */
- Dwarf_AbbrNum get_abbr_num() const {
- Dwarf_Value val;
- abbr_num.get_unsigned(&val);
- return val.u16;
- }
-
- /* Gets DIE tag for this descriptor. */
- Dwarf_Tag get_tag() const {
- Dwarf_Tag tag;
- process(NULL, &tag);
- return tag;
- }
-
- /* Pulls DIE abbreviation descriptor data, advancing past this descriptor.
- * Param:
- * abbr_index - Upon return contains abbreviation number for this
- * descriptor. This parameter can be NULL, if the caller is not interested
- * in this value.
- * tag - Upon return contains tag of the DIE for this descriptor. This
- * parameter can be NULL, if the caller is not interested in this value.
- * form - Upon return contains form of the DIE for this descriptor.
- * Return:
- * Pointer to the list of attribute descriptors for the DIE.
- */
- const Dwarf_Abbr_AT* process(Dwarf_AbbrNum* abbr_index,
- Dwarf_Tag* tag) const {
- Dwarf_Value val;
- const Dwarf_Leb128* next =
- reinterpret_cast<const Dwarf_Leb128*>(abbr_num.process_unsigned(&val));
- if (abbr_index != NULL) {
- *abbr_index = val.u32;
- }
-
- /* Next one is a "tag". */
- next = reinterpret_cast<const Dwarf_Leb128*>(next->process_unsigned(&val));
- if (tag != NULL) {
- *tag = val.u16;
- }
-
- /* Next one is a "has children" one byte flag. We're not interested in it,
- * so jump to the list of attribute descriptors that immediately follows
- * this DIE descriptor. */
- return INC_CPTR_T(Dwarf_Abbr_AT, next, 1);
- }
-} Dwarf_Abbr_DIE;
-
-/* DIE descriptor in the .debug_info section.
- * DIE descriptor contains one LEB128-encoded value, containing DIE's
- * abbreviation descriptor number in the .debug_abbrev section.
- *
- * DIE descriptor is immediately followed by the list of DIE attribute values,
- * format of wich is defined by the list of attribute descriptors in the
- * .debug_abbrev section, that immediately follow the DIE attribute descriptor,
- * addressed by this descriptor's abbr_num LEB128.
- */
-typedef struct ELFF_PACKED Dwarf_DIE {
- /* 1 - based index of DIE abbreviation descriptor (Dwarf_Abbr_DIE) for this
- * DIE in the .debug_abbrev section.
- *
- * NOTE: DIE abbreviation descriptor indexes are tied to the compilation
- * unit. In other words, each compilation unit restarts counting DIE
- * abbreviation descriptors from 1.
- *
- * NOTE: Zero is invalid value for this field, indicating that this DIE is a
- * separator (usually it ends a list of "child" DIEs)
- */
- Dwarf_Leb128 abbr_num;
-
- /* Checks if this is a separator DIE. */
- bool is_separator() const {
- return abbr_num.val == 0;
- }
-
- /* Gets (1 - based) abbreviation number for this DIE. */
- Dwarf_AbbrNum get_abbr_num() const {
- Dwarf_Value val;
- abbr_num.get_unsigned(&val);
- return val.u16;
- }
-
- /* Pulls DIE information, advancing past this descriptor to DIE attributes.
- * Param:
- * abbr_num - Upon return contains abbreviation number for this DIE. This
- * parameter can be NULL, if the caller is not interested in this value.
- * Return:
- * Pointer to the byte past this descriptor (the list of DIE attributes).
- */
- const Elf_Byte* process(Dwarf_AbbrNum* abbr_number) const {
- if (is_separator()) {
- if (abbr_number != NULL) {
- *abbr_number = 0;
- }
- // Size of a separator DIE is 1 byte.
- return INC_CPTR_T(Elf_Byte, &abbr_num.val, 1);
- }
- Dwarf_Value val;
- const void* ret = abbr_num.process_unsigned(&val);
- if (abbr_number != NULL) {
- *abbr_number = val.u32;
- }
- return reinterpret_cast<const Elf_Byte*>(ret);
- }
-} Dwarf_DIE;
-
-/*
- * Variable size headers.
- * When encoding size value in DWARF, the first 32 bits of a "size" header
- * define header type. If first 32 bits of the header contain 0xFFFFFFFF
- * value, this is 64-bit size header with the following 64 bits encoding
- * the size. Otherwise, if first 32 bits are not 0xFFFFFFFF, they contain
- * 32-bit size value.
- */
-
-/* Size header for 32-bit DWARF. */
-typedef struct ELFF_PACKED Dwarf32_SizeHdr {
- /* Size value. */
- Elf_Word size;
-} Dwarf32_SizeHdr;
-
-/* Size header for 64-bit DWARF. */
-typedef struct ELFF_PACKED Dwarf64_SizeHdr {
- /* Size selector. For 64-bit DWARF this field is set to 0xFFFFFFFF */
- Elf_Word size_selector;
-
- /* Actual size value. */
- Elf_Xword size;
-} Dwarf64_SizeHdr;
-
-/* Compilation unit header in the .debug_info section.
- * Template param:
- * Dwarf_SizeHdr - Type for the header's size field. Must be Dwarf32_SizeHdr
- * for 32-bit DWARF, or Dwarf64_SizeHdr for 64-bit DWARF.
- * Elf_Off - Type for abbrev_offset field. Must be Elf_Word for for 32-bit
- * DWARF, or Elf_Xword for 64-bit DWARF.
- */
-template <typename Dwarf_SizeHdr, typename Elf_Off>
-struct ELFF_PACKED Dwarf_CUHdr {
- /* Size of the compilation unit data in .debug_info section. */
- Dwarf_SizeHdr size_hdr;
-
- /* Compilation unit's DWARF version stamp. */
- Elf_Half version;
-
- /* Relative (to the beginning of .debug_abbrev section data) offset of the
- * beginning of abbreviation sequence for this compilation unit.
- */
- Elf_Off abbrev_offset;
-
- /* Pointer size for this compilation unit (should be 4, or 8). */
- Elf_Byte address_size;
-};
-/* Compilation unit header in the .debug_info section for 32-bit DWARF. */
-typedef Dwarf_CUHdr<Dwarf32_SizeHdr, Elf_Word> Dwarf32_CUHdr;
-/* Compilation unit header in the .debug_info section for 64-bit DWARF. */
-typedef Dwarf_CUHdr<Dwarf64_SizeHdr, Elf_Xword> Dwarf64_CUHdr;
-
-/* CU STMTL header in the .debug_line section.
- * Template param:
- * Dwarf_SizeHdr - Type for the header's size field. Must be Dwarf32_SizeHdr
- * for 32-bit DWARF, or Dwarf64_SizeHdr for 64-bit DWARF.
- * Elf_Size - Type for header_length field. Must be Elf_Word for for 32-bit
- * DWARF, or Elf_Xword for 64-bit DWARF.
- */
-template <typename Dwarf_SizeHdr, typename Elf_Size>
-struct ELFF_PACKED Dwarf_STMTLHdr {
- /* The size in bytes of the line number information for this compilation
- * unit, not including the unit_length field itself. */
- Dwarf_SizeHdr unit_length;
-
- /* A version number. This number is specific to the line number information
- * and is independent of the DWARF version number. */
- Elf_Half version;
-
- /* The number of bytes following the header_length field to the beginning of
- * the first byte of the line number program itself. In the 32-bit DWARF
- * format, this is a 4-byte unsigned length; in the 64-bit DWARF format,
- * this field is an 8-byte unsigned length. */
- Elf_Size header_length;
-
- /* The size in bytes of the smallest target machine instruction. Line number
- * program opcodes that alter the address register first multiply their
- * operands by this value. */
- Elf_Byte min_instruction_len;
-
- /* The initial value of the is_stmt register. */
- Elf_Byte default_is_stmt;
-
- /* This parameter affects the meaning of the special opcodes. */
- Elf_Sbyte line_base;
-
- /* This parameter affects the meaning of the special opcodes. */
- Elf_Byte line_range;
-
- /* The number assigned to the first special opcode. */
- Elf_Byte opcode_base;
-
- /* This is first opcode in an array specifying the number of LEB128 operands
- * for each of the standard opcodes. The first element of the array
- * corresponds to the opcode whose value is 1, and the last element
- * corresponds to the opcode whose value is opcode_base - 1. By increasing
- * opcode_base, and adding elements to this array, new standard opcodes can
- * be added, while allowing consumers who do not know about these new opcodes
- * to be able to skip them. NOTE: this array points to the mapped
- * .debug_line section. */
- Elf_Byte standard_opcode_lengths;
-};
-/* CU STMTL header in the .debug_line section for 32-bit DWARF. */
-typedef Dwarf_STMTLHdr<Dwarf32_SizeHdr, Elf_Word> Dwarf32_STMTLHdr;
-/* CU STMTL header in the .debug_line section for 64-bit DWARF. */
-typedef Dwarf_STMTLHdr<Dwarf64_SizeHdr, Elf_Xword> Dwarf64_STMTLHdr;
-
-/* Source file descriptor in the .debug_line section.
- * Descriptor begins with zero-terminated file name, followed by an ULEB128,
- * encoding directory index in the list of included directories, followed by
- * an ULEB12, encoding file modification time, followed by an ULEB12, encoding
- * file size.
- */
-typedef struct ELFF_PACKED Dwarf_STMTL_FileDesc {
- /* Zero-terminated file name. */
- char file_name[1];
-
- /* Checks of this descriptor ends the list. */
- bool is_last_entry() const {
- return file_name[0] == '\0';
- }
-
- /* Gets file name. */
- const char* get_file_name() const {
- return file_name;
- }
-
- /* Processes this descriptor, advancing to the next one.
- * Param:
- * dir_index - Upon return contains index of the parent directory in the
- * list of included directories. Can be NULL if caller is not interested
- * in this value.
- * Return:
- * Pointer to the next source file descriptor in the list.
- */
- const Dwarf_STMTL_FileDesc* process(Elf_Word* dir_index) const {
- if (is_last_entry()) {
- return this;
- }
-
- /* First parameter: include directory index. */
- Dwarf_Value tmp;
- const Dwarf_Leb128* leb =
- INC_CPTR_T(Dwarf_Leb128, file_name, strlen(file_name) + 1);
- leb = reinterpret_cast<const Dwarf_Leb128*>(leb->process_unsigned(&tmp));
- if (dir_index != NULL) {
- *dir_index = tmp.u32;
- }
- /* Process file time. */
- leb = reinterpret_cast<const Dwarf_Leb128*>(leb->process_unsigned(&tmp));
- /* Process file size. */
- return reinterpret_cast<const Dwarf_STMTL_FileDesc*>(leb->process_unsigned(&tmp));
- }
-
- /* Gets directory index for this descriptor. */
- Elf_Word get_dir_index() const {
- assert(!is_last_entry());
- if (is_last_entry()) {
- return 0;
- }
- /* Get directory index. */
- Dwarf_Value ret;
- const Dwarf_Leb128* leb =
- INC_CPTR_T(Dwarf_Leb128, file_name, strlen(file_name) + 1);
- leb->process_unsigned(&ret);
- return ret.u32;
- }
-} Dwarf_STMTL_FileDesc;
-
-/* Encapsulates a DIE attribute, collected during ELF file parsing.
- */
-class DIEAttrib {
- public:
- /* Constructs DIEAttrib intance. */
- DIEAttrib()
- : at_(0),
- form_(0) {
- value_.type = DWARF_VALUE_UNKNOWN;
- }
-
- /* Destructs DIEAttrib intance. */
- ~DIEAttrib() {
- }
-
- /* Gets DWARF attribute ID (DW_AT_Xxx) for this property. */
- Dwarf_At at() const {
- return at_;
- }
-
- /* Gets DWARF form ID (DW_FORM_Xxx) for this property. */
- Dwarf_Form form() const {
- return form_;
- }
-
- /* Gets value of this property. */
- const Dwarf_Value* value() const {
- return &value_;
- }
-
- /* Value of this property. */
- Dwarf_Value value_;
-
- /* DWARF attribute ID (DW_AT_Xxx) for this property. */
- Dwarf_At at_;
-
- /* DWARF form ID (DW_FORM_Xxx) for this property. */
- Dwarf_Form form_;
-};
-
-/* Parse tag context.
- * This structure is used as an ELF file parsing parameter, limiting collected
- * DIEs by the list of tags.
- */
-typedef struct DwarfParseContext {
- /* Zero-terminated list of tags to collect DIEs for. If this field is NULL,
- * DIEs for all tags will be collected during the parsing. */
- const Dwarf_Tag* tags;
-} DwarfParseContext;
-
-/* Checks if a DIE with the given tag should be collected during the parsing.
- * Param:
- * parse_context - Parse context to check the tag against. This parameter can
- * be NULL, indicating that all tags should be collected.
- * tag - Tag to check.
- * Return:
- * true if a DIE with the given tag should be collected during the parsing,
- * or false, if the DIE should not be collected.
- */
-static inline bool
-collect_die(const DwarfParseContext* parse_context, Dwarf_Tag tag) {
- if (parse_context == NULL || parse_context->tags == NULL) {
- return true;
- }
- for (const Dwarf_Tag* tags = parse_context->tags; *tags != 0; tags++) {
- if (*tags == tag) {
- return true;
- }
- }
- return false;
-}
-
-/* Encapsulates an array of Dwarf_Abbr_DIE pointers, cached for a compilation
- * unit. Although Dwarf_Abbr_DIE descriptors in the .debug_abbrev section of
- * the ELF file seems to be always in sequential order, DIE descriptors may
- * reference them randomly. So, to provide better performance, we will cache
- * all Dwarf_Abbr_DIE pointers, that were found for each DIE. Since all of the
- * Dwarf_Abbr_DIE are sequential, an array is the best way to cache them.
- *
- * NOTE: Objects of this class are instantiated one per each CU, as all DIE
- * abbreviation numberation is restarted from 1 for each new CU.
- */
-class DwarfAbbrDieArray {
- public:
- /* Constructs DwarfAbbrDieArray instance.
- * Most of the CUs don't have too many unique Dwarf_Abbr_DIEs, so, in order
- * to decrease the amount of memory allocation calls, we will preallocate
- * a relatively small array for them along with the instance of this class,
- * hopping, that all Dwarf_Abbr_DIEs for the CU will fit into it.
- */
- DwarfAbbrDieArray()
- : array_(&small_array_[0]),
- array_size_(ELFF_ARRAY_SIZE(small_array_)),
- count_(0) {
- }
-
- /* Destructs DwarfAbbrDieArray instance. */
- ~DwarfAbbrDieArray() {
- if (array_ != &small_array_[0]) {
- delete[] array_;
- }
- }
-
- /* Adds new entry to the array
- * Param:
- * abbr - New entry to add.
- * num - Abbreviation number for the adding entry.
- * NOTE: before adding, this method will verify that descriptor for the
- * given abbreviation number has not been cached yet.
- * NOTE: due to the nature of this array, entries MUST be added strictly
- * in sequential order.
- * Return:
- * true on success, false on failure.
- */
- bool add(const Dwarf_Abbr_DIE* abbr, Dwarf_AbbrNum num) {
- assert(num != 0);
- if (num == 0) {
- // Zero is illegal DIE abbreviation number.
- _set_errno(EINVAL);
- return false;
- }
-
- if (num <= count_) {
- // Already cached.
- return true;
- }
-
- // Enforce strict sequential order.
- assert(num == (count_ + 1));
- if (num != (count_ + 1)) {
- _set_errno(EINVAL);
- return false;
- }
-
- if (num >= array_size_) {
- /* Expand the array. Make it 64 entries bigger than adding entry number.
- * NOTE: that we don't check for an overflow here, since we secured
- * ourselves from that by enforcing strict sequential order. So, an
- * overflow may happen iff number of entries cached in this array is
- * close to 4G, which is a) totally unreasonable, and b) we would die
- * long before this amount of entries is cached.
- */
- Dwarf_AbbrNum new_size = num + 64;
-
- // Reallocate.
- const Dwarf_Abbr_DIE** new_array = new const Dwarf_Abbr_DIE*[new_size];
- assert(new_array != NULL);
- if (new_array == NULL) {
- _set_errno(ENOMEM);
- return false;
- }
- memcpy(new_array, array_, count_ * sizeof(const Dwarf_Abbr_DIE*));
- if (array_ != &small_array_[0]) {
- delete[] array_;
- }
- array_ = new_array;
- array_size_ = new_size;
- }
-
- // Abbreviation numbers are 1-based.
- array_[num - 1] = abbr;
- count_++;
- return true;
- }
-
- /* Adds new entry to the array
- * Param:
- * abbr - New entry to add.
- * Return:
- * true on success, false on failure.
- */
- bool add(const Dwarf_Abbr_DIE* abbr) {
- return add(abbr, abbr->get_abbr_num());
- }
-
- /* Gets an entry from the array
- * Param:
- * num - 1-based index of an entry to get.
- * Return:
- * Entry on success, or NULL if num exceeds the number of entries
- * contained in the array.
- */
- const Dwarf_Abbr_DIE* get(Dwarf_AbbrNum num) const {
- assert(num != 0 && num <= count_);
- if (num != 0 && num <= count_) {
- return array_[num - 1];
- } else {
- _set_errno(EINVAL);
- return NULL;
- }
- }
-
- /* Caches Dwarf_Abbr_DIEs into this array up to the requested number.
- * NOTE: This method cannot be called on an empty array. Usually, first
- * entry is inserted into this array when CU object is initialized.
- * Param:
- * num - Entry number to cache entries up to.
- * Return:
- * Last cached entry (actually, an entry for the 'num' index).
- */
- const Dwarf_Abbr_DIE* cache_to(Dwarf_AbbrNum num) {
- /* Last cached DIE abbreviation. We always should have cached at least one
- * abbreviation for the CU DIE itself, added via "add" method when CU
- * object was initialized. */
- const Dwarf_Abbr_DIE* cur_abbr = get(count_);
- assert(cur_abbr != NULL);
- if (cur_abbr == NULL) {
- return NULL;
- }
-
- /* Starting with the last cached DIE abbreviation, loop through the
- * remaining DIE abbreviations in the .debug_abbrev section of the
- * mapped ELF file, caching them until we reach the requested
- * abbreviation descriptor number. Normally, the very next DIE
- * abbreviation will stop the loop. */
- while (num > count_) {
- Dwarf_AbbrNum abbr_num;
- Dwarf_Tag tmp2;
- Dwarf_Form tmp3;
- Dwarf_At tmp4;
-
- /* Process all AT abbreviations for the current DIE entry, reaching next
- * DIE abbreviation. */
- const Dwarf_Abbr_AT* abbr_at = cur_abbr->process(&abbr_num, &tmp2);
- while (!abbr_at->is_separator()) {
- abbr_at = abbr_at->process(&tmp4, &tmp3);
- }
-
- // Next DIE abbreviation is right after the separator AT abbreviation.
- cur_abbr = reinterpret_cast<const Dwarf_Abbr_DIE*>
- (abbr_at->process(&tmp4, &tmp3));
- if (!add(cur_abbr)) {
- return NULL;
- }
- }
-
- return array_[num - 1];
- }
-
- /* Empties array and frees allocations. */
- void empty() {
- if (array_ != &small_array_[0]) {
- delete[] array_;
- array_ = &small_array_[0];
- array_size_ = sizeof(small_array_) / sizeof(small_array_[0]);
- }
- count_ = 0;
- }
-
- protected:
- /* Array, preallocated in anticipation of relatively small number of
- * DIE abbreviations in compilation unit. */
- const Dwarf_Abbr_DIE* small_array_[64];
-
- /* Array of Dwarf_Abbr_DIE pointers, cached for a compilation unit. */
- const Dwarf_Abbr_DIE** array_;
-
- /* Current size of the array. */
- Dwarf_AbbrNum array_size_;
-
- /* Number of entries, cached in the array. */
- Dwarf_AbbrNum count_;
-};
-
-/* Encapsulates a state machine for the "Line Number Program", that is run
- * on data conained in the mapped .debug_line section.
- */
-class DwarfStateMachine {
- public:
- /* Constructs DwarfStateMachine instance.
- * Param:
- * set_is_stmt - Matches value of default_is_stmt field in the STMTL header.
- * see Dwarf_STMTL_HdrXX.
- */
- explicit DwarfStateMachine(bool set_is_stmt)
- : address_(0),
- file_(1),
- line_(1),
- column_(0),
- discriminator_(0),
- is_stmt_(set_is_stmt),
- basic_block_(false),
- end_sequence_(false),
- prologue_end_(false),
- epilogue_begin_(false),
- isa_(0),
- set_file_info_(NULL) {
- }
-
- /* Destructs DwarfStateMachine instance. */
- ~DwarfStateMachine() {
- }
-
- /* Resets the state to default.
- * Param:
- * set_is_stmt - Matches value of default_is_stmt field in the STMTL header.
- * see Dwarf_STMTL_HdrXX.
- */
- void reset(bool set_is_stmt) {
- address_ = 0;
- file_ = 1;
- line_ = 1;
- column_ = 0;
- discriminator_ = 0;
- is_stmt_ = set_is_stmt;
- basic_block_ = false;
- end_sequence_ = false;
- prologue_end_ = false;
- epilogue_begin_ = false;
- isa_ = 0;
- set_file_info_ = NULL;
- }
-
- /*
- * Machine state.
- */
-
- /* Current address (current PC value). */
- Elf_Xword address_;
-
- /* Current index of source file descriptor. */
- Elf_Word file_;
-
- /* Current line in the current source file. */
- Elf_Word line_;
-
- /* Current column. */
- Elf_Word column_;
-
- /* Current discriminator value. */
- Elf_Word discriminator_;
-
- /* Current STMT flag. */
- bool is_stmt_;
-
- /* Current basic block flag. */
- bool basic_block_;
-
- /* Current end of sequence flag. */
- bool end_sequence_;
-
- /* Current end of prologue flag. */
- bool prologue_end_;
-
- /* Current epilogue begin flag. */
- bool epilogue_begin_;
-
- /* Current ISA value. */
- Elf_Word isa_;
-
- /* Current value for explicitly set current source file descriptor.
- * If not NULL, this descriptor has priority over the descriptor, addressed
- * by the file_ member of this class. */
- const Dwarf_STMTL_FileDesc* set_file_info_;
-};
-
-/* Checks if given tag belongs to a routine. */
-static inline bool
-dwarf_tag_is_routine(Dwarf_Tag tag) {
- return tag == DW_TAG_inlined_subroutine ||
- tag == DW_TAG_subprogram ||
- tag == DW_AT_main_subprogram;
-}
-
-/* Checks if given tag belongs to a compilation unit. */
-static inline bool
-dwarf_tag_is_cu(Dwarf_Tag tag) {
- return tag == DW_TAG_compile_unit ||
- tag == DW_TAG_partial_unit;
-}
-
-#endif // ELFF_DWARF_DEFS_H_
diff --git a/distrib/elff/elff/dwarf_die.cc b/distrib/elff/elff/dwarf_die.cc
deleted file mode 100644
index 9d59c23..0000000
--- a/distrib/elff/elff/dwarf_die.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementations of classes defined for a variety of DWARF objects.
- */
-
-#include "stdio.h"
-#include "elff/dwarf_die.h"
-#include "elff/dwarf_cu.h"
-#include "elff/dwarf_utils.h"
-#include "elff/elf_file.h"
-
-DIEObject::~DIEObject() {
- /* Delete all children of this object. */
- DIEObject* to_del = last_child();
- while (to_del != NULL) {
- DIEObject* next = to_del->prev_sibling();
- delete to_del;
- to_del = next;
- }
-}
-
-ElfFile* DIEObject::elf_file() const {
- return parent_cu()->elf_file();
-}
-
-Dwarf_Tag DIEObject::get_tag() const {
- Dwarf_Tag tag;
- return advance(NULL, &tag) != NULL ? tag : 0;
-}
-
-const char* DIEObject::get_name() const {
- DIEAttrib die_attr;
- /* Start with the obvious. */
- if (get_attrib(DW_AT_name, &die_attr)) {
- return die_attr.value()->str;
- }
-
- /* Lets see if there is a reference to the abstract origin, or specification,
- * and use its name as the name for this DIE. */
- if (get_attrib(DW_AT_abstract_origin, &die_attr) ||
- get_attrib(DW_AT_specification, &die_attr)) {
- DIEObject* org_die_obj =
- parent_cu()->get_referenced_die_object(die_attr.value()->u32);
- if (org_die_obj != NULL) {
- return org_die_obj->get_name();
- }
- }
-
- /* Lets see if there is a reference to the type DIE, and use
- * its name as the name for this DIE. */
- if (get_attrib(DW_AT_type, &die_attr)) {
- DIEObject* org_die_obj =
- parent_cu()->get_referenced_die_object(die_attr.value()->u32);
- if (org_die_obj != NULL) {
- return org_die_obj->get_name();
- }
- }
-
- /* Can't figure the name for this DIE. */
- return NULL;
-}
-
-bool DIEObject::get_attrib(Dwarf_At at_id, DIEAttrib* attr) const {
- const Dwarf_Abbr_AT* at_abbr;
-
- /* Advance to DIE attributes. */
- const Elf_Byte* die_attr = advance(&at_abbr, NULL);
- if (die_attr == NULL) {
- _set_errno(EINVAL);
- return false;
- }
-
- /* Loop through all DIE attributes, looking for the one that's being
- * requested. */
- while (!at_abbr->is_separator()) {
- at_abbr = at_abbr->process(&attr->at_, &attr->form_);
- die_attr = parent_cu()->process_attrib(die_attr, attr->form_, &attr->value_);
- if (at_id == attr->at()) {
- return true;
- }
- }
-
- _set_errno(EINVAL);
-
- return false;
-}
-
-DIEObject* DIEObject::get_leaf_for_address(Elf_Xword address) {
- const bool contains = parent_cu()->is_CU_address_64() ?
- contains_address<Elf_Xword>(address) :
- contains_address<Elf_Word>(address);
- if (!contains && !is_cu_die()) {
- /* For CU DIEs address range may be zero size, even though its child DIEs
- * occupie some address space. So, if CU DIE's address range doesn't
- * contain the given address, we still want to go and check the children.
- */
- _set_errno(EINVAL);
- return NULL;
- }
-
- /* This DIE contains given address (or may contain it, if this is a CU DIE).
- * Lets iterate through child DIEs to find the leaf (last DIE) that contains
- * this address. */
- DIEObject* child = last_child();
- while (child != NULL) {
- DIEObject* leaf = child->get_leaf_for_address(address);
- if (leaf != NULL) {
- return leaf;
- }
- child = child->prev_sibling();
- }
- /* No child DIE contains this address. This DIE is the leaf. */
- return contains || !is_cu_die() ? this : NULL;
-}
-
-template <typename AddrType>
-bool DIEObject::contains_address(Elf_Xword address) {
- DIEAttrib die_ranges;
- /* DIE can contain either list of ranges (f.i. DIEs that represent a routine
- * that is inlined in multiple places will contain list of address ranges
- * where that routine is inlined), or a pair "low PC, and high PC" describing
- * contiguos address space where routine has been placed by compiler. */
- if (get_attrib(DW_AT_ranges, &die_ranges)) {
- /* Iterate through this DIE's ranges list, looking for the one that
- * contains the given address. */
- AddrType low;
- AddrType high;
- Elf_Word range_off = die_ranges.value()->u32;
- while (elf_file()->get_range(range_off, &low, &high) &&
- (low != 0 || high != 0)) {
- if (address >= low && address < high) {
- return true;
- }
- range_off += sizeof(AddrType) * 2;
- }
- return false;
- } else {
- /* This DIE doesn't have ranges. Lets see if it has low_pc and high_pc
- * attributes. */
- DIEAttrib low_pc;
- DIEAttrib high_pc;
- if (!get_attrib(DW_AT_low_pc, &low_pc) ||
- !get_attrib(DW_AT_high_pc, &high_pc) ||
- address < low_pc.value()->u64 ||
- address >= high_pc.value()->u64) {
- return false;
- }
- return true;
- }
-}
-
-DIEObject* DIEObject::find_die_object(const Dwarf_DIE* die_to_find) {
- if (die_to_find == die()) {
- return this;
- }
-
- /* First we will iterate through the list of children, since chances to
- * find requested DIE decrease as we go deeper into DIE tree. */
- DIEObject* iter = last_child();
- while (iter != NULL) {
- if (iter->die() == die_to_find) {
- return iter;
- }
- iter = iter->prev_sibling();
- };
-
- /* DIE has not been found among the children. Lets go deeper now. */
- iter = last_child();
- while (iter != NULL) {
- DIEObject* ret = iter->find_die_object(die_to_find);
- if (ret != NULL) {
- return ret;
- }
- iter = iter->prev_sibling();
- }
-
- _set_errno(EINVAL);
- return NULL;
-}
-
-void DIEObject::dump(bool only_this) const {
- const Dwarf_Abbr_AT* at_abbr;
- Dwarf_Tag tag;
-
- const Elf_Byte* die_attr = advance(&at_abbr, &tag);
- if (die_attr != NULL) {
- printf("\n********** DIE[%p(%04X)] %s: %s **********\n",
- die_, parent_cu()->get_die_reference(die_), dwarf_tag_name(tag),
- get_name());
-
- /* Dump this DIE attributes. */
- while (!at_abbr->is_separator()) {
- DIEAttrib attr;
- at_abbr = at_abbr->process(&attr.at_, &attr.form_);
- die_attr = parent_cu()->process_attrib(die_attr, attr.form(), &attr.value_);
- dump_attrib(attr.at(), attr.form(), attr.value());
- if (attr.at() == DW_AT_ranges) {
- /* Dump all ranges for this DIE. */
- Elf_Word off = attr.value()->u32;
- if (parent_cu()->is_CU_address_64()) {
- Elf_Xword low, high;
- while (elf_file()->get_range<Elf_Xword>(off, &low, &high) &&
- (low != 0 || high != 0)) {
- printf(" %08llX - %08llX\n",
- (unsigned long long)low, (unsigned long long)high);
- off += 16;
- }
- } else {
- Elf_Word low, high;
- while (elf_file()->get_range<Elf_Word>(off, &low, &high) &&
- (low != 0 || high != 0)) {
- printf(" %08X - %08X\n",
- low, high);
- off += 8;
- }
- }
- }
- }
- }
-
- if (only_this) {
- if (parent_die_ != NULL && !parent_die_->is_cu_die()) {
- printf("\n-----------> CHILD OF:\n");
- parent_die_->dump(true);
- }
- } else {
- /* Dump this DIE's children. */
- if (last_child() != NULL) {
- last_child()->dump(false);
- }
-
- /* Dump this DIE's siblings. */
- if (prev_sibling() != NULL) {
- prev_sibling()->dump(false);
- }
- }
-}
-
-const Elf_Byte* DIEObject::advance(const Dwarf_Abbr_AT** at_abbr,
- Dwarf_Tag* tag) const {
- Dwarf_AbbrNum abbr_num;
- Dwarf_Tag die_tag;
-
- const Elf_Byte* die_attr = die()->process(&abbr_num);
- const Dwarf_Abbr_DIE* abbr = parent_cu()->get_die_abbr(abbr_num);
- if (abbr == NULL) {
- return NULL;
- }
-
- const Dwarf_Abbr_AT* attrib_abbr = abbr->process(NULL, &die_tag);
- if (at_abbr != NULL) {
- *at_abbr = attrib_abbr;
- }
- if (tag != NULL) {
- *tag = die_tag;
- }
- return die_attr;
-}
diff --git a/distrib/elff/elff/dwarf_die.h b/distrib/elff/elff/dwarf_die.h
deleted file mode 100644
index 5f76bcc..0000000
--- a/distrib/elff/elff/dwarf_die.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of classes defined for a variety of DWARF objects.
- */
-
-#ifndef ELFF_DWARF_DIE_H_
-#define ELFF_DWARF_DIE_H_
-
-#include "dwarf_defs.h"
-#include "elff/elf_alloc.h"
-
-class ElfFile;
-class DwarfCU;
-
-/* Encapsulates an object that wraps up a DIE, cached during
- * ELF file parsing.
- */
-class DIEObject : public DwarfAllocBase {
- public:
- /* Constructs DIEObject intance.
- * Param:
- * die - DIE represented with this instance.
- * parent_cu - Compilation unit this DIE belongs to.
- * parent_die - Parent DIE object for this DIE. This parameter can be NULL
- * only for compilation unit DIEs.
- */
- DIEObject(const Dwarf_DIE* die, DwarfCU* parent_cu, DIEObject* parent_die)
- : die_(die),
- parent_cu_(parent_cu),
- parent_die_(parent_die),
- last_child_(NULL),
- prev_sibling_(NULL) {
- }
-
- /* Destructs DIEObject intance. */
- ~DIEObject();
-
- /* Gets ELF file this DIE belongs to. */
- ElfFile* elf_file() const;
-
- /* Gets DWARF tag (DW_TAG_Xxx) for the DIE represented with this instance. */
- Dwarf_Tag get_tag() const;
-
- /* Gets the best name for this DIE.
- * Some DIEs (such as inline routine DIEs) may have no DW_AT_name property,
- * but may reference to another DIE that may contain DIE name. This method
- * tries its best to get DIE name by iterating through different methods of
- * naming the DIE.
- * Return:
- * Name for this DIE, or NULL if it was not possible to find a relevant DIE
- * with DW_AT_name property.
- */
- const char* get_name() const;
-
- /* Gets DIE's attribute by its ID.
- * Param:
- * at_id - ID (DW_AT_Xxx) of the attribute to get.
- * attr - Upon successful return contains requested attribute information.
- * Return:
- * true on success, or false if attribute for the given ID doesn't exist
- * in the DIE's attribute list.
- */
- bool get_attrib(Dwarf_At at, DIEAttrib* attr) const;
-
- /* Gets the leaf DIE object containing given address.
- * See DwarfCU::get_leaf_die_for_address() for method details.
- * See DIEObject::contains_address() for implementation details.
- */
- DIEObject* get_leaf_for_address(Elf_Xword address);
-
- /* Finds a DIE object for the given die in the branch starting with
- * this DIE object.
- */
- DIEObject* find_die_object(const Dwarf_DIE* die_to_find);
-
- /* Dumps this object to stdout.
- * Param:
- * only_this - If true, only this object will be dumped. If this parameter
- * is false, all the childs and siblings of this object will be dumped
- * along with this object.
- */
- void dump(bool only_this) const;
-
- protected:
- /* Checks if this DIE object containing given address.
- * Template param:
- * AddrType - Type of compilation unin address (4, or 8 bytes), defined by
- * address_size field of the CU header. Must be Elf_Xword for 8 bytes
- * address, or Elf_Word for 4 bytes address.
- * Param:
- * address - Address ti check.
- * Return:
- * True, if this DIE address ranges (including low_pc, high_pc attributes)
- * contain given address, or false otherwise.
- */
- template <typename AddrType>
- bool contains_address(Elf_Xword address);
-
- /* Advances to the DIE's property list.
- * Param:
- * at_abbr - Upon successful return contains a pointer to the beginning of
- * DIE attribute abbreviation list. This parameter can be NULL, if the
- * caller is not interested in attribute abbreviation list for this DIE.
- * tag - Upon successful return contains DIE's tag. This parameter can be
- * NULL, if the caller is not interested in the tag value for this DIE.
- * Return:
- * Pointer to the beginning of the DIE attribute list in mapped .debug_info
- * section on success, or NULL on failure.
- */
- const Elf_Byte* advance(const Dwarf_Abbr_AT** at_abbr, Dwarf_Tag* tag) const;
-
- public:
- /* Gets DIE represented with this instance. */
- const Dwarf_DIE* die() const {
- return die_;
- }
-
- /* Gets compilation unit this DIE belongs to. */
- DwarfCU* parent_cu() const {
- return parent_cu_;
- }
-
- /* Gets parent DIE object for this die. */
- DIEObject* parent_die() const {
- return parent_die_;
- }
-
- /* Gets last child object in the list of this DIE's childs. NOTE: for better
- * performace the list is created in reverse order (relatively to the order,
- * in which children DIEs have been discovered).
- */
- DIEObject* last_child() const {
- return last_child_;
- }
-
- /* Links next child to the list of this DIE childs. */
- void link_child(DIEObject* child) {
- last_child_ = child;
- }
-
- /* Gets previous sibling of this DIE in the parent's DIE object list. */
- DIEObject* prev_sibling() const {
- return prev_sibling_;
- }
-
- /* Links next sibling to the list of this DIE siblings. */
- void link_sibling(DIEObject* sibl) {
- prev_sibling_ = sibl;
- }
-
- /* Checks if this DIE object represents a CU DIE.
- * We relay here on the fact that only CU DIE objects have no parent
- * DIE objects.
- */
- bool is_cu_die() const {
- return parent_die_ == NULL;
- }
-
- /* Gets this DIE level in the branch.
- * DIE level defines DIE's distance from the CU DIE in the branch this DIE
- * belongs to. In other words, DIE level defines how many parent DIEs exist
- * between this DIE, and the CU DIE. For instance, the CU DIE has level 0,
- * a subroutine a() in this compilation unit has level 1, a soubroutine b(),
- * that has been inlined into subroutine a() will have level 2, a try/catch
- * block in the inlined subroutine b() will have level 3, and so on.
- */
- Elf_Word get_level() const {
- return parent_die_ != NULL ? parent_die_->get_level() + 1 : 0;
- }
-
- protected:
- /* DIE that is represented with this instance. */
- const Dwarf_DIE* die_;
-
- /* Compilation unit this DIE belongs to. */
- DwarfCU* parent_cu_;
-
- /* Parent DIE object for this die. */
- DIEObject* parent_die_;
-
- /* Last child object in the list of this DIE's childs. NOTE: for better
- * performace the list is created in reverse order (relatively to the order,
- * in which children DIEs have been discovered).
- */
- DIEObject* last_child_;
-
- /* Previous sibling of this DIE in the parent's DIE object list. */
- DIEObject* prev_sibling_;
-};
-
-#endif // ELFF_DWARF_DIE_H_
diff --git a/distrib/elff/elff/dwarf_utils.cc b/distrib/elff/elff/dwarf_utils.cc
deleted file mode 100644
index 86178af..0000000
--- a/distrib/elff/elff/dwarf_utils.cc
+++ /dev/null
@@ -1,315 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of misc. DWARF utility routines.
- */
-
-#include <stdio.h>
-#define __STDC_FORMAT_MACROS 1
-#include <inttypes.h>
-#include "elff/dwarf_utils.h"
-
-/* "Stringifies" the parameter. */
-#define DWARF_NAMEFY(val) case val: return "" #val ""
-
-/* "Stringifies" two parameters. */
-#define DWARF_NAMEFY2(val1, val2) case val1: return "" #val1 " | " #val2 ""
-
-const char*
-dwarf_at_name(Dwarf_At at) {
- switch (at) {
- DWARF_NAMEFY(DW_AT_sibling);
- DWARF_NAMEFY(DW_AT_location);
- DWARF_NAMEFY(DW_AT_name);
- DWARF_NAMEFY(DW_AT_ordering);
- DWARF_NAMEFY(DW_AT_subscr_data);
- DWARF_NAMEFY(DW_AT_byte_size);
- DWARF_NAMEFY(DW_AT_bit_offset);
- DWARF_NAMEFY(DW_AT_bit_size);
- DWARF_NAMEFY(DW_AT_element_list);
- DWARF_NAMEFY(DW_AT_stmt_list);
- DWARF_NAMEFY(DW_AT_low_pc);
- DWARF_NAMEFY(DW_AT_high_pc);
- DWARF_NAMEFY(DW_AT_language);
- DWARF_NAMEFY(DW_AT_member);
- DWARF_NAMEFY(DW_AT_discr);
- DWARF_NAMEFY(DW_AT_discr_value);
- DWARF_NAMEFY(DW_AT_visibility);
- DWARF_NAMEFY(DW_AT_import);
- DWARF_NAMEFY(DW_AT_string_length);
- DWARF_NAMEFY(DW_AT_common_reference);
- DWARF_NAMEFY(DW_AT_comp_dir);
- DWARF_NAMEFY(DW_AT_const_value);
- DWARF_NAMEFY(DW_AT_containing_type);
- DWARF_NAMEFY(DW_AT_default_value);
- DWARF_NAMEFY(DW_AT_inline);
- DWARF_NAMEFY(DW_AT_is_optional);
- DWARF_NAMEFY(DW_AT_lower_bound);
- DWARF_NAMEFY(DW_AT_producer);
- DWARF_NAMEFY(DW_AT_prototyped);
- DWARF_NAMEFY(DW_AT_return_addr);
- DWARF_NAMEFY(DW_AT_start_scope);
- DWARF_NAMEFY2(DW_AT_bit_stride, DW_AT_stride_size);
- DWARF_NAMEFY(DW_AT_upper_bound);
- DWARF_NAMEFY(DW_AT_abstract_origin);
- DWARF_NAMEFY(DW_AT_accessibility);
- DWARF_NAMEFY(DW_AT_address_class);
- DWARF_NAMEFY(DW_AT_artificial);
- DWARF_NAMEFY(DW_AT_base_types);
- DWARF_NAMEFY(DW_AT_calling_convention);
- DWARF_NAMEFY(DW_AT_count);
- DWARF_NAMEFY(DW_AT_data_member_location);
- DWARF_NAMEFY(DW_AT_decl_column);
- DWARF_NAMEFY(DW_AT_decl_file);
- DWARF_NAMEFY(DW_AT_decl_line);
- DWARF_NAMEFY(DW_AT_declaration);
- DWARF_NAMEFY(DW_AT_discr_list);
- DWARF_NAMEFY(DW_AT_encoding);
- DWARF_NAMEFY(DW_AT_external);
- DWARF_NAMEFY(DW_AT_frame_base);
- DWARF_NAMEFY(DW_AT_friend);
- DWARF_NAMEFY(DW_AT_identifier_case);
- DWARF_NAMEFY(DW_AT_macro_info);
- DWARF_NAMEFY(DW_AT_namelist_item);
- DWARF_NAMEFY(DW_AT_priority);
- DWARF_NAMEFY(DW_AT_segment);
- DWARF_NAMEFY(DW_AT_specification);
- DWARF_NAMEFY(DW_AT_static_link);
- DWARF_NAMEFY(DW_AT_type);
- DWARF_NAMEFY(DW_AT_use_location);
- DWARF_NAMEFY(DW_AT_variable_parameter);
- DWARF_NAMEFY(DW_AT_virtuality);
- DWARF_NAMEFY(DW_AT_vtable_elem_location);
- DWARF_NAMEFY(DW_AT_allocated);
- DWARF_NAMEFY(DW_AT_associated);
- DWARF_NAMEFY(DW_AT_data_location);
- DWARF_NAMEFY2(DW_AT_byte_stride, DW_AT_stride);
- DWARF_NAMEFY(DW_AT_entry_pc);
- DWARF_NAMEFY(DW_AT_use_UTF8);
- DWARF_NAMEFY(DW_AT_extension);
- DWARF_NAMEFY(DW_AT_ranges);
- DWARF_NAMEFY(DW_AT_trampoline);
- DWARF_NAMEFY(DW_AT_call_column);
- DWARF_NAMEFY(DW_AT_call_file);
- DWARF_NAMEFY(DW_AT_call_line);
- DWARF_NAMEFY(DW_AT_description);
- DWARF_NAMEFY(DW_AT_binary_scale);
- DWARF_NAMEFY(DW_AT_decimal_scale);
- DWARF_NAMEFY(DW_AT_small);
- DWARF_NAMEFY(DW_AT_decimal_sign);
- DWARF_NAMEFY(DW_AT_digit_count);
- DWARF_NAMEFY(DW_AT_picture_string);
- DWARF_NAMEFY(DW_AT_mutable);
- DWARF_NAMEFY(DW_AT_threads_scaled);
- DWARF_NAMEFY(DW_AT_explicit);
- DWARF_NAMEFY(DW_AT_object_pointer);
- DWARF_NAMEFY(DW_AT_endianity);
- DWARF_NAMEFY(DW_AT_elemental);
- DWARF_NAMEFY(DW_AT_pure);
- DWARF_NAMEFY(DW_AT_recursive);
- DWARF_NAMEFY(DW_AT_signature);
- DWARF_NAMEFY(DW_AT_main_subprogram);
- DWARF_NAMEFY(DW_AT_data_bit_offset);
- DWARF_NAMEFY(DW_AT_const_expr);
- DWARF_NAMEFY(DW_AT_enum_class);
- DWARF_NAMEFY(DW_AT_linkage_name);
- default:
- return "DW_AT_Unknown";
- }
-}
-
-const char*
-dwarf_form_name(Dwarf_Form form) {
- switch (form) {
- DWARF_NAMEFY(DW_FORM_addr);
- DWARF_NAMEFY(DW_FORM_block2);
- DWARF_NAMEFY(DW_FORM_block4);
- DWARF_NAMEFY(DW_FORM_data2);
- DWARF_NAMEFY(DW_FORM_data4);
- DWARF_NAMEFY(DW_FORM_data8);
- DWARF_NAMEFY(DW_FORM_string);
- DWARF_NAMEFY(DW_FORM_block);
- DWARF_NAMEFY(DW_FORM_block1);
- DWARF_NAMEFY(DW_FORM_data1);
- DWARF_NAMEFY(DW_FORM_flag);
- DWARF_NAMEFY(DW_FORM_sdata);
- DWARF_NAMEFY(DW_FORM_strp);
- DWARF_NAMEFY(DW_FORM_udata);
- DWARF_NAMEFY(DW_FORM_ref_addr);
- DWARF_NAMEFY(DW_FORM_ref1);
- DWARF_NAMEFY(DW_FORM_ref2);
- DWARF_NAMEFY(DW_FORM_ref4);
- DWARF_NAMEFY(DW_FORM_ref8);
- DWARF_NAMEFY(DW_FORM_ref_udata);
- DWARF_NAMEFY(DW_FORM_indirect);
- DWARF_NAMEFY(DW_FORM_sec_offset);
- DWARF_NAMEFY(DW_FORM_exprloc);
- DWARF_NAMEFY(DW_FORM_flag_present);
- DWARF_NAMEFY(DW_FORM_ref_sig8);
- default:
- return "DW_FORM_Unknown";
- }
-}
-
-const char*
-dwarf_tag_name(Dwarf_Tag tag) {
- switch (tag) {
- DWARF_NAMEFY(DW_TAG_array_type);
- DWARF_NAMEFY(DW_TAG_class_type);
- DWARF_NAMEFY(DW_TAG_entry_point);
- DWARF_NAMEFY(DW_TAG_enumeration_type);
- DWARF_NAMEFY(DW_TAG_formal_parameter);
- DWARF_NAMEFY(DW_TAG_imported_declaration);
- DWARF_NAMEFY(DW_TAG_label);
- DWARF_NAMEFY(DW_TAG_lexical_block);
- DWARF_NAMEFY(DW_TAG_member);
- DWARF_NAMEFY(DW_TAG_pointer_type);
- DWARF_NAMEFY(DW_TAG_reference_type);
- DWARF_NAMEFY(DW_TAG_compile_unit);
- DWARF_NAMEFY(DW_TAG_string_type);
- DWARF_NAMEFY(DW_TAG_structure_type);
- DWARF_NAMEFY(DW_TAG_subroutine_type);
- DWARF_NAMEFY(DW_TAG_typedef);
- DWARF_NAMEFY(DW_TAG_union_type);
- DWARF_NAMEFY(DW_TAG_unspecified_parameters);
- DWARF_NAMEFY(DW_TAG_variant);
- DWARF_NAMEFY(DW_TAG_common_block);
- DWARF_NAMEFY(DW_TAG_common_inclusion);
- DWARF_NAMEFY(DW_TAG_inheritance);
- DWARF_NAMEFY(DW_TAG_inlined_subroutine);
- DWARF_NAMEFY(DW_TAG_module);
- DWARF_NAMEFY(DW_TAG_ptr_to_member_type);
- DWARF_NAMEFY(DW_TAG_set_type);
- DWARF_NAMEFY(DW_TAG_subrange_type);
- DWARF_NAMEFY(DW_TAG_with_stmt);
- DWARF_NAMEFY(DW_TAG_access_declaration);
- DWARF_NAMEFY(DW_TAG_base_type);
- DWARF_NAMEFY(DW_TAG_catch_block);
- DWARF_NAMEFY(DW_TAG_const_type);
- DWARF_NAMEFY(DW_TAG_constant);
- DWARF_NAMEFY(DW_TAG_enumerator);
- DWARF_NAMEFY(DW_TAG_file_type);
- DWARF_NAMEFY(DW_TAG_friend);
- DWARF_NAMEFY(DW_TAG_namelist);
- DWARF_NAMEFY2(DW_TAG_namelist_item, DW_TAG_namelist_items);
- DWARF_NAMEFY(DW_TAG_packed_type);
- DWARF_NAMEFY(DW_TAG_subprogram);
- DWARF_NAMEFY2(DW_TAG_template_type_parameter, DW_TAG_template_type_param);
- DWARF_NAMEFY2(DW_TAG_template_value_parameter,
- DW_TAG_template_value_param);
- DWARF_NAMEFY(DW_TAG_thrown_type);
- DWARF_NAMEFY(DW_TAG_try_block);
- DWARF_NAMEFY(DW_TAG_variant_part);
- DWARF_NAMEFY(DW_TAG_variable);
- DWARF_NAMEFY(DW_TAG_volatile_type);
- DWARF_NAMEFY(DW_TAG_dwarf_procedure);
- DWARF_NAMEFY(DW_TAG_restrict_type);
- DWARF_NAMEFY(DW_TAG_interface_type);
- DWARF_NAMEFY(DW_TAG_namespace);
- DWARF_NAMEFY(DW_TAG_imported_module);
- DWARF_NAMEFY(DW_TAG_unspecified_type);
- DWARF_NAMEFY(DW_TAG_partial_unit);
- DWARF_NAMEFY(DW_TAG_imported_unit);
- DWARF_NAMEFY(DW_TAG_mutable_type);
- DWARF_NAMEFY(DW_TAG_condition);
- DWARF_NAMEFY(DW_TAG_shared_type);
- DWARF_NAMEFY(DW_TAG_type_unit);
- DWARF_NAMEFY(DW_TAG_rvalue_reference_type);
- DWARF_NAMEFY(DW_TAG_template_alias);
- default:
- return "DW_TAG_Unknown";
- }
-}
-
-void
-dump_attrib(Dwarf_At at, Dwarf_Form form, const Dwarf_Value* val) {
- if (form != 0) {
- printf(" +++ Attribute: %s [%s]\n",
- dwarf_at_name(at), dwarf_form_name(form));
- } else {
- printf(" +++ Attribute: %s\n", dwarf_at_name(at));
- }
- dump_value(val);
-}
-
-void
-dump_value(const Dwarf_Value* attr_value) {
- printf(" Data[%03u]: (", attr_value->encoded_size);
- switch (attr_value->type) {
- case DWARF_VALUE_U8:
- printf("BYTE) = %u (x%02X)\n", (Elf_Word)attr_value->u8,
- (Elf_Word)attr_value->u8);
- break;
-
- case DWARF_VALUE_S8:
- printf("SBYTE) = %d (x%02X)\n", (Elf_Sword)attr_value->s8,
- (Elf_Sword)attr_value->s8);
- break;
-
- case DWARF_VALUE_U16:
- printf("WORD) = %u (x%04X)\n", (Elf_Word)attr_value->u16,
- (Elf_Word)attr_value->u16);
- break;
-
- case DWARF_VALUE_S16:
- printf("SWORD) = %d (x%04X)\n", (Elf_Sword)attr_value->s16,
- (Elf_Sword)attr_value->s16);
- break;
-
- case DWARF_VALUE_U32:
- printf("DWORD) = %u (x%08X)\n", attr_value->u32,
- attr_value->u32);
- break;
-
- case DWARF_VALUE_S32:
- printf("SDWORD) = %d (x%08X)\n", attr_value->s32,
- attr_value->s32);
- break;
-
- case DWARF_VALUE_U64:
- printf("XWORD) = %" PRIu64 " (x%" PRIX64 ")\n", attr_value->u64,
- attr_value->u64);
- break;
-
- case DWARF_VALUE_S64:
- printf("SXWORD) = %" PRId64 " (x%" PRIX64 ")\n", attr_value->s64,
- attr_value->s64);
- break;
-
- case DWARF_VALUE_STR:
- printf("STRING) = %s\n", attr_value->str);
- break;
-
- case DWARF_VALUE_PTR32:
- printf("PTR32) = x%08X\n", attr_value->ptr32);
- break;
-
- case DWARF_VALUE_PTR64:
- printf("PTR64) = x%08" PRIX64 "\n", attr_value->ptr64);
- break;
-
- case DWARF_VALUE_BLOCK:
- printf("BLOCK) = [%u]:", attr_value->block.block_size);
- for (Elf_Xword i = 0; i < attr_value->block.block_size; i++) {
- Elf_Byte prnt = *((const Elf_Byte*)attr_value->block.block_ptr + i);
- printf(" x%02X", prnt);
- }
- printf("\n");
- break;
-
- case DWARF_VALUE_UNKNOWN:
- default:
- printf("UNKNOWN)");
- break;
- }
-}
diff --git a/distrib/elff/elff/dwarf_utils.h b/distrib/elff/elff/dwarf_utils.h
deleted file mode 100644
index 38ee3b0..0000000
--- a/distrib/elff/elff/dwarf_utils.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of misc. DWARF utility routines.
- */
-
-#ifndef ELFF_DWARF_UTILS_
-#define ELFF_DWARF_UTILS_
-
-#include "elff/dwarf_defs.h"
-
-/* Gets DWARF attribute name string (DW_AT_Xxx) for a given attribute ID.
- * Param:
- * at - DWARF attribute ID to get name string for.
- * Return:
- * Attribute name string. Note that this routine returns "DW_AT_Unknown",
- * if DWARF attribute value passed to this routine has not been recognized.
- */
-const char* dwarf_at_name(Dwarf_At at);
-
-/* Gets DWARF form name string (DW_FORM_Xxx) for a given form.
- * Param:
- * form - DWARF form to get name string for.
- * Return:
- * Form name string. Note that this routine returns "DW_FORM_Unknown", if
- * DWARF form value passed to this routine has not been recognized.
- */
-const char* dwarf_form_name(Dwarf_Form form);
-
-/* Gets DWARF tag name string (DW_TAG_Xxx) for a given tag.
- * Param:
- * tag - DWARF tag to get name string for.
- * Return:
- * Tag name string. Note that this routine returns "DW_TAG_Unknown", if DWARF
- * tag value passed to this routine has not been recognized.
- */
-const char* dwarf_tag_name(Dwarf_Tag tag);
-
-/* Dumps DWARF attribute to stdout.
- * Param:
- * at - Attribute ID (DW_AT_Xxx)
- * form - Attribute form (DW_FORM_Xxx)
- * val - Attribute value.
- */
-void dump_attrib(Dwarf_At at, Dwarf_Form form, const Dwarf_Value* val);
-
-/* Dumps DWARF attribute value to stdout.
- * Param:
- * val - Attribute value.
- */
-void dump_value(const Dwarf_Value* val);
-
-#endif // ELFF_DWARF_UTILS_
diff --git a/distrib/elff/elff/elf_alloc.cc b/distrib/elff/elff/elf_alloc.cc
deleted file mode 100644
index 6eb0f43..0000000
--- a/distrib/elff/elff/elf_alloc.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of class ElfAllocator, that implements memory
- * allocations for DWARF objects.
- */
-
-#include "elff/elf_alloc.h"
-#include "elff/elf_file.h"
-
-ElfAllocator::ElfAllocator()
- : current_chunk_(NULL) {
-}
-
-ElfAllocator::~ElfAllocator() {
- ElfAllocatorChunk* chunk_to_free = current_chunk_;
- while (chunk_to_free != NULL) {
- ElfAllocatorChunk* next_chunk = chunk_to_free->prev;
- free(chunk_to_free);
- chunk_to_free = next_chunk;
- }
-}
-
-void* ElfAllocator::alloc(size_t size) {
- /* Lets keep everyting properly aligned. */
- size = (size + ELFALLOC_ALIGNMENT_MASK) & ~ELFALLOC_ALIGNMENT_MASK;
-
- if (current_chunk_ == NULL || current_chunk_->remains < size) {
- /* Allocate new chunk. */
- ElfAllocatorChunk* new_chunk =
- reinterpret_cast<ElfAllocatorChunk*>(malloc(ELF_ALLOC_CHUNK_SIZE));
- assert(new_chunk != NULL);
- if (new_chunk == NULL) {
- _set_errno(ENOMEM);
- return NULL;
- }
- new_chunk->size = ELF_ALLOC_CHUNK_SIZE;
- new_chunk->avail = INC_PTR(new_chunk, sizeof(ElfAllocatorChunk));
- new_chunk->remains = new_chunk->size - sizeof(ElfAllocatorChunk);
- new_chunk->prev = current_chunk_;
- current_chunk_ = new_chunk;
- }
-
- void* ret = current_chunk_->avail;
- current_chunk_->remains -= size;
- current_chunk_->avail = INC_PTR(current_chunk_->avail, size);
- return ret;
-}
-
-void* DwarfAllocBase::operator new(size_t size, const ElfFile* elf) {
- return elf->allocator()->alloc(size);
-}
diff --git a/distrib/elff/elff/elf_alloc.h b/distrib/elff/elff/elf_alloc.h
deleted file mode 100644
index 066e6dc..0000000
--- a/distrib/elff/elff/elf_alloc.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declaration of class ElfAllocator, that implements memory
- * allocations for DWARF objects.
- */
-
-#ifndef ELFF_ELF_ALLOC_H_
-#define ELFF_ELF_ALLOC_H_
-
-#include <stdint.h>
-#include "elff/elff-common.h"
-
-class ElfFile;
-
-/* Alignment mask for blocks, allocated with this allocator. */
-#define ELFALLOC_ALIGNMENT_MASK 3
-
-/* Chunk size. Even on relatively small ELF files, there are a lot of DWARF
- * info, which makes our parsing pretty hungry on memory. On average, memory
- * consumption on cached DWARF objects may easily reach 640K, which makes
- * choosing 32K as chunk size pretty reasonable.
- */
-#define ELF_ALLOC_CHUNK_SIZE (32 * 1024)
-
-/* Describes a chunk of memory, allocated by ElfAllocator.
- * NOTE: this header's sizeof must be always aligned accordingly to the
- * ELFALLOC_ALIGNMENT_MASK value, so we can produce properly aligned blocks
- * without having to adjust alignment of the blocks, returned from alloc()
- * method.
- */
-typedef struct ElfAllocatorChunk {
- /* Previous chunk in the chain of chunks allocated by ElfAllocator instance.
- * For better allocation performance, ElfAllocator keeps its list of
- * allocated chunks in reverse order (relatively to the chunk allocation
- * sequence). So this field in each chunk references the chunk, allocated
- * just prior this one. This field contains NULL for the first allocated
- * chunk.
- */
- ElfAllocatorChunk* prev;
-
- /* Address of the next available block in this chunk. */
- void* avail;
-
- /* Chunk size. */
- size_t size;
-
- /* Number of bytes that remain available in this chunk. */
- size_t remains;
-} ElfAllocatorChunk;
-
-/* Encapsulates memory allocator for DWARF-related objects.
- * Due to the implementation of ELF/DWARF framework in this library, data,
- * collected during ELF/DWARF parsing stays in memory for as long, as instance
- * of ElfFile that's being parsed is alive. To save performance on the numerous
- * memory allocations (and then, deallocations) we will use this simple memory
- * allocator that will grab memory from the heap in large chunks and then will
- * provide DWARF objects with blocks of the required size inside those chunks.
- * This will be much faster than going to the heap all the time, and since we
- * will use overwritten operators new/delete for the DWARF objects that use
- * this allocator, this is going to be pretty flexible and reliable solution
- * for DWARF object allocation implementation. See DwarfAllocBase for more
- * details.
- *
- * Instance (always one) of this class is created by ElfFile object when it is
- * initializing.
- */
-class ElfAllocator {
- public:
- /* Constructs ElfAllocator instance. */
- ElfAllocator();
-
- /* Destructs ElfAllocator instance. */
- ~ElfAllocator();
-
- /* Allocates requested number of bytes for a DWARF object.
- * Param:
- * size - Number of bytes to allocate. Value passed in this parameter
- * will be rounded up accordingly to ELFALLOC_ALIGNMENT_MASK value,
- * simplifying alignment adjustments for the allocated blocks.
- * Return:
- * Address of allocated block of the requested size on success,
- * or NULL on failure.
- */
- void* alloc(size_t size);
-
- protected:
- /* Current chunk to allocate memory from. NOTE: chunks are listed here
- * in reverse order (relatively to the chunk allocation sequence).
- */
- ElfAllocatorChunk* current_chunk_;
-};
-
-/* Base class for all WDARF objects that will use ElfAllocator class for
- * instance allocations. NOTE: it's required, that all classes that use
- * ElfAllocator are derived from this one, as it provides compilation-time
- * protection from mistakenly using "traditional" operator 'new' for object
- * instantiation.
- */
-class DwarfAllocBase {
- public:
- /* Constructs DwarfAllocBase instance. */
- DwarfAllocBase() {
- }
-
- /* Destructs DwarfAllocBase instance. */
- virtual ~DwarfAllocBase() {
- }
-
- /* Main operator new.
- * Implements allocation of objects of derived classes from elf's "chunked"
- * allocator, instantiated in ElfFile object (see ElfAllocator class).
- * Param:
- * size - Number of bytes to allocate for an instance of the derived class.
- * elf - ELF file instance that owns the allocating object.
- * Return:
- * Pointer to the allocated memory on success, or NULL on failure.
- */
- void* operator new(size_t size, const ElfFile* elf);
-
- /* Overwitten operator delete.
- * Since deleting for chunk-allocated objects is a "no-op", we don't do
- * anything in this operator. We, however, are obliged to implement this
- * operator in order to compliment overwritten operator 'new'.
- */
- void operator delete(void* ptr) {
- }
-
- /* Overwitten operator delete.
- * Since deleting for chunk-allocated objects is a "no-op", we don't do
- * anything in this operator. We, however, are obliged to implement this
- * operator in order to compliment overwritten operator 'new'.
- */
- void operator delete[](void* ptr) {
- }
-
- private:
- /* Default operator new.
- * We override it making 'private' in order to cause a compiler error on
- * attempts to instantiate objects of derived classes using this version
- * of operator 'new'.
- */
- void* operator new(size_t size) throw() {
- return NULL;
- }
-};
-
-extern "C" void* elff_alloc(size_t size);
-extern "C" void elff_free(void* ptr);
-
-#endif // ELFF_ELF_ALLOC_H_
diff --git a/distrib/elff/elff/elf_defs.h b/distrib/elff/elff/elf_defs.h
deleted file mode 100644
index acc586a..0000000
--- a/distrib/elff/elff/elf_defs.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains some helpful macros, and inline routines.
- */
-
-#ifndef ELFF_ELF_DEFS_H_
-#define ELFF_ELF_DEFS_H_
-
-#include "elff/elff_elf.h"
-
-//=============================================================================
-// Macros.
-//=============================================================================
-
-/* Increments a pointer by n bytes.
- * Param:
- * p - Pointer to increment.
- * n - Number of bytes to increment the pointer with.
- */
-static inline uint8_t* INC_PTR(void* p, size_t n) {
- return reinterpret_cast<uint8_t*>(p) + n;
-}
-
-/* Increments a constant pointer by n bytes.
- * Param:
- * p - Pointer to increment.
- * n - Number of bytes to increment the pointer with.
- */
-static inline const uint8_t* INC_CPTR(const void* p, size_t n) {
- return reinterpret_cast<const uint8_t*>(p) + n;
-}
-
-/* Increments a constant pointer of a given type by n bytes.
- * Param:
- * T - Pointer type
- * p - Pointer to increment.
- * n - Number of bytes to increment the pointer with.
- */
-template <typename T>
-static inline const T* INC_CPTR_T_INNER_TEMPLATE(const void* p, size_t n) {
- union {
- const void* p;
- const uint8_t* p8;
- const T* pt;
- } u;
- u.p = p;
- u.p8 += n;
- return u.pt;
-}
-
-#define INC_CPTR_T(T, p, n) INC_CPTR_T_INNER_TEMPLATE<T>(p, n)
-
-/* Calculates number of entries in a static array.
- * Param:
- * a - Array.
- * Return:
- * Number of entries in the array.
- */
-#define ELFF_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
-
-/* Calculates offset of a field inside a structure (or a class) of the
- * given type.
- * Param:
- * T - Structure (or class) type.
- * f - Name of a field (member variable) for this structure (or class).
- */
-#define ELFF_FIELD_OFFSET(T, f) offsetof(T, f)
-
-//=============================================================================
-// Inline routines.
-//=============================================================================
-
-/* Calculates byte interval between two pointers.
- * Param:
- * s - Starting pointer of the interval. Must be less, or equal to 'e'.
- * e - Ending pointer of the interval. Must be greater, or equal to 's'.
- * Return:
- * Byte interval between two pointers.
- */
-static inline size_t
-diff_ptr(const void* s, const void* e) {
- assert(s <= e);
- return ((size_t)(reinterpret_cast<const uint8_t*>(e) -
- reinterpret_cast<const uint8_t*>(s)));
-}
-
-/* Gets one byte from an index inside a memory block.
- * Param:
- * ptr - Address of the beginning of the memory block.
- * bt - Index of a byte inside the block to get.
- * Return:
- * A byte at the given index inside the given memory block.
- */
-static inline uint8_t
-get_byte(const void* ptr, uint32_t bt) {
- return *(reinterpret_cast<const uint8_t*>(ptr) + bt);
-}
-
-/* Checks if given address range is fully contained within a section.
- * Param:
- * rp - Beginning of the range to check.
- * rsize - Size of the range to check.
- * ss - Beginning of the section that should contain the checking range.
- * ssize - Size of the section that should contain the checking range.
- * Return:
- * true, if given address range is fully contained within a section, or
- * false, if any part of the address range is not contained in the secton.
- */
-static inline bool
-is_in_section(const void* rp, size_t rsize, const void* ss, size_t ssize) {
- const void* rend = INC_CPTR(rp, rsize);
- /* We also make sure here that increment didn't overflow the pointer. */
- return rp >= ss && ss != NULL && (diff_ptr(ss, rend) <= ssize) && rend >= rp;
-}
-
-/* Checks if this code runs on CPU with a little-endian data format.
- * Return:
- * true, if this code runs on CPU with a little-endian data format,
- * or false, if this code runs on CPU with a big-endian data format.
- */
-static inline bool
-is_little_endian_cpu(void) {
- uint16_t tmp = 0x00FF;
- /* Lets see if byte has flipped for little-endian. */
- return get_byte(&tmp, 0) == 0xFF;
-}
-
-#endif // ELFF_ELF_DEFS_H_
diff --git a/distrib/elff/elff/elf_file.cc b/distrib/elff/elff/elf_file.cc
deleted file mode 100644
index 4fbb261..0000000
--- a/distrib/elff/elff/elf_file.cc
+++ /dev/null
@@ -1,476 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of ElfFile classes that encapsulate an ELF file.
- */
-
-#include "string.h"
-#include "elff/elf_file.h"
-#include "elff/elf_alloc.h"
-#include "elff/dwarf_cu.h"
-#include "elff/dwarf_utils.h"
-
-#include <fcntl.h>
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/* Tags to parse when collecting info about routines. */
-static const Dwarf_Tag parse_rt_tags[] = {
- DW_TAG_compile_unit,
- DW_TAG_partial_unit,
- DW_TAG_inlined_subroutine,
- DW_TAG_subprogram,
- 0
-};
-static const DwarfParseContext parse_rt_context = { parse_rt_tags };
-
-//=============================================================================
-// Base ElfFile implementation
-//=============================================================================
-
-ElfFile::ElfFile()
- : fixed_base_address_(0),
- elf_handle_((MapFile*)-1),
- elf_file_path_(NULL),
- allocator_(NULL),
- sec_table_(NULL),
- sec_count_(0),
- sec_entry_size_(0),
- last_cu_(NULL),
- cu_count_(0),
- is_exec_(0) {
-}
-
-ElfFile::~ElfFile() {
- DwarfCU* cu_to_del = last_cu_;
- while (cu_to_del != NULL) {
- DwarfCU* next_cu_to_del = cu_to_del->prev_cu_;
- delete cu_to_del;
- cu_to_del = next_cu_to_del;
- }
-
- if (mapfile_is_valid(elf_handle_)) {
- mapfile_close(elf_handle_);
- }
-
- if (elf_file_path_ != NULL) {
- delete[] elf_file_path_;
- }
-
- if (sec_table_ != NULL) {
- delete[] reinterpret_cast<Elf_Byte*>(sec_table_);
- }
-
- /* Must be deleted last! */
- if (allocator_ != NULL) {
- delete allocator_;
- }
-}
-
-ElfFile* ElfFile::Create(const char* path) {
- ElfFile* ret = NULL;
- /* Allocate enough space on the stack to fit the largest ELF file header. */
- Elf64_FHdr header;
- const Elf_CommonHdr* elf_hdr = &header.common;
-
- assert(path != NULL && *path != '\0');
- if (path == NULL || *path == '\0') {
- _set_errno(EINVAL);
- return NULL;
- }
-
- /*
- * Open ELF file, and read its header (the largest one possible).
- */
- MapFile* file_handle = mapfile_open(path, O_RDONLY | O_BINARY, 0);
- if (!mapfile_is_valid(file_handle)) {
- return NULL;
- }
- const ssize_t read_bytes = mapfile_read(file_handle, &header, sizeof(header));
- mapfile_close(file_handle);
- assert(read_bytes != -1 && read_bytes == sizeof(header));
- if (read_bytes == -1 || read_bytes != sizeof(header)) {
- if (read_bytes != -1) {
- _set_errno(EINVAL);
- }
- return NULL;
- }
-
- /* Lets see if this is an ELF file at all. */
- if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) {
- /* File is not an ELF file. */
- _set_errno(ENOEXEC);
- return NULL;
- }
-
- /* Lets check ELF's "bitness". */
- assert(elf_hdr->ei_info.ei_class == ELFCLASS32 ||
- elf_hdr->ei_info.ei_class == ELFCLASS64);
- if (elf_hdr->ei_info.ei_class != ELFCLASS32 &&
- elf_hdr->ei_info.ei_class != ELFCLASS64) {
- /* Neither 32, or 64-bit ELF file. Something wrong here. */
- _set_errno(EBADF);
- return NULL;
- }
-
- /* Lets instantiate appropriate ElfFileImpl object for this ELF. */
- if (elf_hdr->ei_info.ei_class == ELFCLASS32) {
- ret = new ElfFileImpl<Elf32_Addr, Elf32_Off>;
- } else {
- ret = new ElfFileImpl<Elf64_Addr, Elf64_Off>;
- }
- assert(ret != NULL);
- if (ret != NULL) {
- if (!ret->initialize(elf_hdr, path)) {
- delete ret;
- ret = NULL;
- }
- } else {
- _set_errno(ENOMEM);
- }
-
- return ret;
-}
-
-bool ElfFile::initialize(const Elf_CommonHdr* elf_hdr, const char* path) {
- /* Must be created first! */
- allocator_ = new ElfAllocator();
- assert(allocator_ != NULL);
- if (allocator_ == NULL) {
- _set_errno(ENOMEM);
- return false;
- }
-
- /* Copy file path. */
- size_t path_len = strlen(path) + 1;
- elf_file_path_ = new char[path_len];
- assert(elf_file_path_ != NULL);
- if (elf_file_path_ == NULL) {
- _set_errno(ENOMEM);
- return false;
- }
- memcpy(elf_file_path_, path, path_len);
-
- /* Cache some basic ELF properties. */
- is_ELF_64_ = elf_hdr->ei_info.ei_class == ELFCLASS64;
- is_elf_big_endian_ = elf_hdr->ei_info.ei_data == ELFDATA2MSB;
- same_endianness_ = is_elf_little_endian() == is_little_endian_cpu();
- is_exec_ = elf_hdr->e_type == 2;
-
- /* Reopen file for further reads and mappings. */
- elf_handle_ = mapfile_open(elf_file_path_, O_RDONLY | O_BINARY, 0);
- return mapfile_is_valid(elf_handle_);
-}
-
-bool ElfFile::get_pc_address_info(Elf_Xword address,
- Elf_AddressInfo* address_info) {
- assert(address_info != NULL);
- if (address_info == NULL) {
- _set_errno(EINVAL);
- return false;
- }
-
- /* Collect routine information for all CUs in this file. */
- if (parse_compilation_units(&parse_rt_context) == -1) {
- return false;
- }
-
- /* Iterate through the collected CUs looking for the one that
- * contains the given address. */
- address_info->inline_stack = NULL;
- DwarfCU* cu = last_cu();
- while (cu != NULL) {
- /* Find a leaf DIE object in the current CU that contains the address. */
- Dwarf_AddressInfo info;
- info.die_obj = cu->get_leaf_die_for_address(address);
- if (info.die_obj != NULL) {
- /* Convert the address to a location inside source file. */
- if (cu->get_pc_address_file_info(address, &info)) {
- /* Copy location information to the returning structure. */
- address_info->file_name = info.file_name;
- address_info->dir_name = info.dir_name;
- address_info->line_number = info.line_number;
- } else {
- address_info->file_name = NULL;
- address_info->dir_name = NULL;
- address_info->line_number = 0;
- }
-
- /* Lets see if the DIE represents a routine (rather than
- * a lexical block, for instance). */
- Dwarf_Tag tag = info.die_obj->get_tag();
- while (!dwarf_tag_is_routine(tag)) {
- /* This is not a routine DIE. Lets loop trhough the parents of that
- * DIE looking for the first routine DIE. */
- info.die_obj = info.die_obj->parent_die();
- if (info.die_obj == NULL) {
- /* Reached compilation unit DIE. Can't go any further. */
- address_info->routine_name = "<unknown>";
- return true;
- }
- tag = info.die_obj->get_tag();
- }
-
- /* Save name of the routine that contains the address. */
- address_info->routine_name = info.die_obj->get_name();
- if (address_info->routine_name == NULL) {
- /* In some cases (minimum debugging info in the file) routine
- * name may be not avaible. We, however, are obliged by API
- * considerations to return something in this field. */
- address_info->routine_name = "<unknown>";
- }
-
- /* Lets see if address belongs to an inlined routine. */
- if (tag != DW_TAG_inlined_subroutine) {
- address_info->inline_stack = NULL;
- return true;
- }
-
- /*
- * Address belongs to an inlined routine. Create inline stack.
- */
-
- /* Allocate inline stack array big enough to fit all parent entries. */
- address_info->inline_stack =
- new Elf_InlineInfo[info.die_obj->get_level() + 1];
- assert(address_info->inline_stack != NULL);
- if (address_info->inline_stack == NULL) {
- _set_errno(ENOMEM);
- return false;
- }
- memset(address_info->inline_stack, 0,
- sizeof(Elf_InlineInfo) * (info.die_obj->get_level() + 1));
-
- /* Reverse DIEs filling in inline stack entries for inline
- * routine tags. */
- int inl_index = 0;
- do {
- /* Save source file information. */
- DIEAttrib file_desc;
- if (info.die_obj->get_attrib(DW_AT_call_file, &file_desc)) {
- const Dwarf_STMTL_FileDesc* desc =
- cu->get_stmt_file_info(file_desc.value()->u32);
- if (desc != NULL) {
- address_info->inline_stack[inl_index].inlined_in_file =
- desc->file_name;
- address_info->inline_stack[inl_index].inlined_in_file_dir =
- cu->get_stmt_dir_name(desc->get_dir_index());
- }
- }
- if (address_info->inline_stack[inl_index].inlined_in_file == NULL) {
- address_info->inline_stack[inl_index].inlined_in_file = "<unknown>";
- address_info->inline_stack[inl_index].inlined_in_file_dir = NULL;
- }
-
- /* Save source line information. */
- if (info.die_obj->get_attrib(DW_AT_call_line, &file_desc)) {
- address_info->inline_stack[inl_index].inlined_at_line = file_desc.value()->u32;
- }
-
- /* Advance DIE to the parent routine, and save its name. */
- info.die_obj = info.die_obj->parent_die();
- assert(info.die_obj != NULL);
- if (info.die_obj != NULL) {
- tag = info.die_obj->get_tag();
- while (!dwarf_tag_is_routine(tag)) {
- info.die_obj = info.die_obj->parent_die();
- if (info.die_obj == NULL) {
- break;
- }
- tag = info.die_obj->get_tag();
- }
- if (info.die_obj != NULL) {
- address_info->inline_stack[inl_index].routine_name =
- info.die_obj->get_name();
- }
- }
- if (address_info->inline_stack[inl_index].routine_name == NULL) {
- address_info->inline_stack[inl_index].routine_name = "<unknown>";
- }
-
- /* Continue with the parent DIE. */
- inl_index++;
- } while (info.die_obj != NULL && tag == DW_TAG_inlined_subroutine);
-
- return true;
- }
- cu = cu->prev_cu();
- }
-
- return false;
-}
-
-void ElfFile::free_pc_address_info(Elf_AddressInfo* address_info) const {
- assert(address_info != NULL);
- if (address_info != NULL && address_info->inline_stack != NULL) {
- delete address_info->inline_stack;
- address_info->inline_stack = NULL;
- }
-}
-
-//=============================================================================
-// ElfFileImpl
-//=============================================================================
-
-template <typename Elf_Addr, typename Elf_Off>
-bool ElfFileImpl<Elf_Addr, Elf_Off>::initialize(const Elf_CommonHdr* elf_hdr,
- const char* path) {
- /* Must be called first! */
- if (!ElfFile::initialize(elf_hdr, path)) {
- return false;
- }
-
- /* Cache some header data, so later we can discard the header. */
- const Elf_FHdr<Elf_Addr, Elf_Off>* header =
- reinterpret_cast<const Elf_FHdr<Elf_Addr, Elf_Off>*>(elf_hdr);
- sec_count_ = pull_val(header->e_shnum);
- sec_entry_size_ = pull_val(header->e_shentsize);
- fixed_base_address_ = pull_val(header->e_entry) & ~0xFFF;
-
- /* Cache section table (must have one!) */
- const Elf_Off sec_table_off = pull_val(header->e_shoff);
- assert(sec_table_off != 0 && sec_count_ != 0);
- if (sec_table_off == 0 || sec_count_ == 0) {
- _set_errno(EBADF);
- return false;
- }
- const size_t sec_table_size = sec_count_ * sec_entry_size_;
- sec_table_ = new Elf_Byte[sec_table_size];
- assert(sec_table_ != NULL);
- if (sec_table_ == NULL) {
- _set_errno(ENOMEM);
- return false;
- }
- if (mapfile_read_at(elf_handle_, sec_table_off, sec_table_,
- sec_table_size) < 0) {
- return false;
- }
-
- /* Map ELF's string section (must have one!). */
- const Elf_Half str_sec_index = pull_val(header->e_shstrndx);
- assert(str_sec_index != SHN_UNDEF);
- if (str_sec_index == SHN_UNDEF) {
- _set_errno(EBADF);
- return false;
- }
- const Elf_SHdr<Elf_Addr, Elf_Off>* str_sec =
- reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
- (get_section_by_index(str_sec_index));
- assert(str_sec != NULL);
- if (str_sec == NULL) {
- _set_errno(EBADF);
- return false;
- }
- if (!string_section_.map(elf_handle_, pull_val(str_sec->sh_offset),
- pull_val(str_sec->sh_size))) {
- return false;
- }
-
- /* Lets determine DWARF format. According to the docs, DWARF is 64 bit, if
- * first 4 bytes in the compilation unit header are set to 0xFFFFFFFF.
- * .debug_info section of the ELF file begins with the first CU header. */
- if (!map_section_by_name(".debug_info", &debug_info_)) {
- _set_errno(EBADF);
- return false;
- }
-
- /* Note that we don't care about endianness here, since 0xFFFFFFFF is an
- * endianness-independent value, so we don't have to pull_val here. */
- is_DWARF_64_ =
- *reinterpret_cast<const Elf_Word*>(debug_info_.data()) == 0xFFFFFFFF;
-
- return true;
-}
-
-template <typename Elf_Addr, typename Elf_Off>
-int ElfFileImpl<Elf_Addr, Elf_Off>::parse_compilation_units(
- const DwarfParseContext* parse_context) {
- /* Lets see if we already parsed the file. */
- if (last_cu() != NULL) {
- return cu_count_;
- }
-
- /* Cache sections required for this parsing. */
- if (!map_section_by_name(".debug_abbrev", &debug_abbrev_) ||
- !map_section_by_name(".debug_ranges", &debug_ranges_) ||
- !map_section_by_name(".debug_line", &debug_line_) ||
- !map_section_by_name(".debug_str", &debug_str_)) {
- _set_errno(EBADF);
- return false;
- }
-
- /* .debug_info section opens with the first CU header. */
- const void* next_cu = debug_info_.data();
-
- /* Iterate through CUs until we reached the end of .debug_info section, or
- * advanced to a CU with zero size, indicating the end of CU list for this
- * file. */
- while (is_valid_cu(next_cu)) {
- /* Instatiate CU, depending on DWARF "bitness". */
- DwarfCU* cu = DwarfCU::create_instance(this, next_cu);
- if (cu == NULL) {
- _set_errno(ENOMEM);
- return -1;
- }
-
- if (cu->parse(parse_context, &next_cu)) {
- cu->set_prev_cu(last_cu_);
- last_cu_ = cu;
- cu_count_++;
- } else {
- delete cu;
- return -1;
- }
- };
-
- return cu_count_;
-}
-
-template <typename Elf_Addr, typename Elf_Off>
-bool ElfFileImpl<Elf_Addr, Elf_Off>::get_section_info_by_name(const char* name,
- Elf_Off* offset,
- Elf_Word* size) {
- const Elf_SHdr<Elf_Addr, Elf_Off>* cur_section =
- reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>(sec_table_);
-
- for (Elf_Half sec = 0; sec < sec_count_; sec++) {
- const char* sec_name = get_str_sec_str(pull_val(cur_section->sh_name));
- if (sec_name != NULL && strcmp(name, sec_name) == 0) {
- *offset = pull_val(cur_section->sh_offset);
- *size = pull_val(cur_section->sh_size);
- return true;
- }
- cur_section = reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
- (INC_CPTR(cur_section, sec_entry_size_));
- }
- _set_errno(EINVAL);
- return false;
-}
-
-template <typename Elf_Addr, typename Elf_Off>
-bool ElfFileImpl<Elf_Addr, Elf_Off>::map_section_by_name(
- const char* name,
- ElfMappedSection* section) {
- if (section->is_mapped()) {
- return true;
- }
-
- Elf_Off offset;
- Elf_Word size;
- if (!get_section_info_by_name(name, &offset, &size)) {
- return false;
- }
-
- return section->map(elf_handle_, offset, size);
-}
diff --git a/distrib/elff/elff/elf_file.h b/distrib/elff/elff/elf_file.h
deleted file mode 100644
index 15e7158..0000000
--- a/distrib/elff/elff/elf_file.h
+++ /dev/null
@@ -1,622 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declaration of ElfFile classes that encapsulate an ELF file.
- */
-
-#ifndef ELFF_ELF_FILE_H_
-#define ELFF_ELF_FILE_H_
-
-#include "elff/dwarf_die.h"
-#include "elff/elf_mapped_section.h"
-#include "elff/elff_api.h"
-#include "elff/elff_map_file.h"
-
-/* Encapsulates architecture-independent functionality of an ELF file.
- *
- * This class is a base class for templated ElfFileImpl. This class implements
- * functionality around an ELF file that is independent from particulars of the
- * ELF's CPU architectire, while ElfFileImpl handles all particulars of CPU
- * architecture (namely, 32 or 64-bit), for which ELF file has been built.
- *
- * NOTE: This class operates on ELF sections that have been mapped to memory.
- *
- */
-class ElfFile {
- public:
- /* Constructs ElfFile instance. */
- ElfFile();
-
- /* Destructs ElfFile instance. */
- virtual ~ElfFile();
-
- /* Creates ElfFileImpl instance, depending on ELF file CPU architecture.
- * This method will collect initial information about requested ELF file,
- * and will instantiate appropriate ElfFileImpl class object for it.
- * Param:
- * path - Full path to the ELF file.
- * Return:
- * Initialized ElfFileImpl instance, typecasted back to ElfFile object on
- * success, or NULL on failure, with errno providing extended error
- * information.
- */
- static ElfFile* Create(const char* path);
-
- /* Checks if ELF file is a 64, or 32-bit ELF file. */
- bool is_ELF_64() const {
- return is_ELF_64_;
- }
- bool is_ELF_32() const {
- return !is_ELF_64_;
- }
-
- /* Checks if ELF file data format is big, or little-endian. */
- bool is_elf_big_endian() const {
- return is_elf_big_endian_;
- }
- bool is_elf_little_endian() const {
- return !is_elf_big_endian_;
- }
-
- /* Checks whether or not endianness of CPU this library is built for matches
- * endianness of the ELF file that is represented with this instance. */
- bool same_endianness() const {
- return same_endianness_;
- }
-
- /* Checks if format of DWARF data in this file is 64, or 32-bit. */
- bool is_DWARF_64() const {
- return is_DWARF_64_;
- }
- bool is_DWARF_32() const {
- return !is_DWARF_64_;
- }
-
- /* Gets DWARF objects allocator for this instance. */
- class ElfAllocator* allocator() const {
- return allocator_;
- }
-
- /* Gets head of compilation unit list, collected during parsing of this file.
- * NOTE: list of collected compilation units returned from this method is
- * in reverse order relatively to the order CUs have been added to the list
- * during ELF file parsing.
- */
- class DwarfCU* last_cu() const {
- return last_cu_;
- }
-
- /* Gets number of compilation units, collected during parsing of
- * this ELF file with parse_compilation_units() method.
- */
- int cu_count() const {
- return cu_count_;
- }
-
- /* Gets executable file flag */
- bool is_exec() const {
- return is_exec_;
- }
-
- protected:
- /* Initializes ElfFile instance. This method is called from Create method of
- * this class after appropriate ElfFileImpl instance has been created. Note,
- * that Create() method will validate that requested file is an ELF file,
- * prior to instantiating of an ElfFileImpl object, and calling this method.
- * Param:
- * elf_hdr - Address of the common ELF file header.
- * path - See Create().
- * Return:
- * true on success, or false on failure, with errno containing extended
- * error information.
- */
- virtual bool initialize(const Elf_CommonHdr* elf_hdr, const char* path);
-
-/*=============================================================================
- * Endianness helper methods.
- * Since endianness of ELF file may differ from the endianness of the CPU this
- * library runs on, every time a value is required from a section of the ELF
- * file, it must be first pulled out of that section to a local variable, and
- * then used from that local variable. While value is pulled from ELF file
- * section, it must be converted accordingly to the endianness of the CPU and
- * ELF file. Routines bellow provide such functionality.
-=============================================================================*/
-
- public:
- /* Pulls one byte value from ELF file. Note that for one byte we don't need
- * to do any endianness conversion, and these two methods are provided purely
- * for completness of the API.
- * Param:
- * val - References value inside ELF file buffer to pull data from.
- * Return
- * Pulled value with endianness appropriate for the CPU this library is
- * running on.
- */
- uint8_t pull_val(const uint8_t* val) const {
- return *val;
- }
- uint8_t pull_val(const uint8_t& val) const {
- return val;
- }
- int8_t pull_val(const int8_t* val) const {
- return *val;
- }
- int8_t pull_val(const int8_t& val) const {
- return val;
- }
-
- /* Pulls two byte value from ELF file.
- * Param:
- * val - References value inside ELF file buffer to pull data from.
- * Return
- * Pulled value with endianness appropriate for the CPU this library is
- * running on.
- */
- uint16_t pull_val(const uint16_t* val) const {
- if (same_endianness()) {
- return *val;
- }
- if (is_elf_big_endian()) {
- return (uint16_t)get_byte(val, 0) << 8 | get_byte(val, 1);
- } else {
- return (uint16_t)get_byte(val, 1) << 8 | get_byte(val, 0);
- }
- }
- uint16_t pull_val(const uint16_t& val) const {
- return same_endianness() ? val : pull_val(&val);
- }
- int16_t pull_val(const int16_t* val) const {
- return static_cast<int16_t>
- (pull_val(reinterpret_cast<const uint16_t*>(val)));
- }
- int16_t pull_val(const int16_t& val) const {
- return static_cast<int16_t>
- (pull_val(reinterpret_cast<const uint16_t&>(val)));
- }
-
- /* Pulls four byte value from ELF file.
- * Param:
- * val - References value inside ELF file buffer to pull data from.
- * Return
- * Pulled value with endianness appropriate for the CPU this library is
- * running on.
- */
- uint32_t pull_val(const uint32_t* val) const {
- if (same_endianness()) {
- return *val;
- }
- if (is_elf_big_endian()) {
- return (uint32_t)get_byte(val, 0) << 24 |
- (uint32_t)get_byte(val, 1) << 16 |
- (uint32_t)get_byte(val, 2) << 8 |
- (uint32_t)get_byte(val, 3);
- } else {
- return (uint32_t)get_byte(val, 3) << 24 |
- (uint32_t)get_byte(val, 2) << 16 |
- (uint32_t)get_byte(val, 1) << 8 |
- (uint32_t)get_byte(val, 0);
- }
- }
- uint32_t pull_val(const uint32_t& val) const {
- return same_endianness() ? val : pull_val(&val);
- }
- int32_t pull_val(const int32_t* val) const {
- return static_cast<int32_t>
- (pull_val(reinterpret_cast<const uint32_t*>(val)));
- }
- int32_t pull_val(const int32_t& val) const {
- return static_cast<int32_t>
- (pull_val(reinterpret_cast<const uint32_t&>(val)));
- }
-
- /* Pulls eight byte value from ELF file.
- * Param:
- * val - References value inside ELF file buffer to pull data from.
- * Return
- * Pulled value with endianness appropriate for the CPU this library is
- * running on.
- */
- uint64_t pull_val(const uint64_t* val) const {
- if (same_endianness()) {
- return *val;
- }
- if (is_elf_big_endian()) {
- return (uint64_t)get_byte(val, 0) << 56 |
- (uint64_t)get_byte(val, 1) << 48 |
- (uint64_t)get_byte(val, 2) << 40 |
- (uint64_t)get_byte(val, 3) << 32 |
- (uint64_t)get_byte(val, 4) << 24 |
- (uint64_t)get_byte(val, 5) << 16 |
- (uint64_t)get_byte(val, 6) << 8 |
- (uint64_t)get_byte(val, 7);
- } else {
- return (uint64_t)get_byte(val, 7) << 56 |
- (uint64_t)get_byte(val, 6) << 48 |
- (uint64_t)get_byte(val, 5) << 40 |
- (uint64_t)get_byte(val, 4) << 32 |
- (uint64_t)get_byte(val, 3) << 24 |
- (uint64_t)get_byte(val, 2) << 16 |
- (uint64_t)get_byte(val, 1) << 8 |
- (uint64_t)get_byte(val, 0);
- }
- }
- uint64_t pull_val(const uint64_t& val) const {
- return same_endianness() ? val : pull_val(&val);
- }
- int64_t pull_val(const int64_t* val) const {
- return static_cast<int64_t>
- (pull_val(reinterpret_cast<const uint64_t*>(val)));
- }
- int64_t pull_val(const int64_t& val) const {
- return static_cast<int64_t>
- (pull_val(reinterpret_cast<const uint64_t&>(val)));
- }
-
-//=============================================================================
-// ELF file section management.
-//=============================================================================
-
- public:
- /* Gets a string contained in ELF's string section by index.
- * Param:
- * index - String index (byte offset) in the ELF's string section.
- * Return:
- * Pointer to the requested string, or NULL if string index exceeds ELF's
- * string section size.
- * NOTE: pointer returned from this method points to a mapped section of
- * ELF file.
- */
- const char* get_str_sec_str(Elf_Xword index) const {
- assert(string_section_.is_mapped() && index < string_section_.size());
- if (string_section_.is_mapped() && index < string_section_.size()) {
- return INC_CPTR_T(char, string_section_.data(), index);
- } else {
- _set_errno(EINVAL);
- return NULL;
- }
- }
-
- /* Gets a string contained in ELF's debug string section (.debug_str)
- * by index.
- * Param:
- * index - String index (byte offset) in the ELF's debug string section.
- * Return:
- * Pointer to the requested string, or NULL if string index exceeds ELF's
- * debug string section size.
- * NOTE: pointer returned from this method points to a mapped section of
- * ELF file.
- */
- const char* get_debug_str(Elf_Xword index) const {
- assert(debug_str_.is_mapped() && index < debug_str_.size());
- if (debug_str_.is_mapped() && index < debug_str_.size()) {
- return INC_CPTR_T(char, debug_str_.data(), index);
- } else {
- _set_errno(EINVAL);
- return NULL;
- }
- }
-
- protected:
- /* Gets pointer to a section header, given section index within ELF's
- * section table.
- * Param:
- * index - Section index within ELF's section table.
- * Return:
- * Pointer to a section header (ElfXX_SHdr flavor, depending on ELF's CPU
- * architecture) on success, or NULL if section index exceeds number of
- * sections for this ELF file.
- */
- const void* get_section_by_index(Elf_Half index) const {
- assert(index < sec_count_);
- if (index < sec_count_) {
- return INC_CPTR(sec_table_, static_cast<size_t>(index) * sec_entry_size_);
- } else {
- _set_errno(EINVAL);
- return NULL;
- }
- }
-
-//=============================================================================
-// DWARF management.
-//=============================================================================
-
- protected:
- /* Parses DWARF, and buids a list of compilation units for this ELF file.
- * Compilation unit, collected with this methods are linked together in a
- * list, head of which is available via last_cu() method of this class.
- * NOTE: CUs in the list returned via last_cu() method are in reverse order
- * relatively to the order in which CUs are stored in .debug_info section.
- * This is ELF and DWARF data format - dependent method.
- * Param:
- * parse_context - Parsing context that defines which tags, and which
- * properties for which tag should be collected during parsing. NULL
- * passed in this parameter indicates that all properties for all tags
- * should be collected.
- * Return:
- * Number of compilation units, collected in this method on success,
- * or -1 on failure.
- */
- virtual int parse_compilation_units(const DwarfParseContext* parse_context) = 0;
-
- public:
- /* Gets PC address information.
- * Param:
- * address - PC address to get information for. The address must be relative
- * to the beginning of ELF file represented by this class.
- * address_info - Upon success contains information about routine(s) that
- * contain the given address.
- * Return:
- * true if routine(s) containing has been found and its information has been
- * saved into address_info, or false if no appropriate routine for that
- * address has been found, or there was a memory error when collecting
- * routine(s) information. In case of failure, errno contains extended error
- * information.
- */
- bool get_pc_address_info(Elf_Xword address, Elf_AddressInfo* address_info);
-
- /* Frees resources aqcuired for address information in successful call to
- * get_pc_address_info().
- * Param:
- * address_info - Address information structure, initialized in successful
- * call to get_pc_address_info() routine.
- */
- void free_pc_address_info(Elf_AddressInfo* address_info) const;
-
- /* Gets beginning of the .debug_info section data.
- * Return:
- * Beginning of the .debug_info section data.
- * NOTE: pointer returned from this method points to a mapped section of
- * ELF file.
- */
- const void* get_debug_info_data() const {
- return debug_info_.data();
- }
-
- /* Gets beginning of the .debug_abbrev section data.
- * Return:
- * Beginning of the .debug_abbrev section data.
- * NOTE: pointer returned from this method points to a mapped section of
- * ELF file.
- */
- const void* get_debug_abbrev_data() const {
- return debug_abbrev_.data();
- }
-
- /* Gets beginning of the .debug_ranges section data.
- * Return:
- * Beginning of the .debug_ranges section data.
- * NOTE: pointer returned from this method points to a mapped section of
- * ELF file.
- */
- const void* get_debug_ranges_data() const {
- return debug_ranges_.data();
- }
-
- /* Gets beginning of the .debug_line section data.
- * Return:
- * Beginning of the .debug_line section data.
- * NOTE: pointer returned from this method points to a mapped section of
- * ELF file.
- */
- const void* get_debug_line_data() const {
- return debug_line_.data();
- }
-
- /* Checks, if given address range is contained in the mapped .debug_info
- * section of this file.
- * Param:
- * ptr - Starting address of the range.
- * size - Range size in bytes.
- * Return:
- * true if given address range is contained in the mapped .debug_info
- * section of this file, or false if any part of the range doesn't belong
- * to that section.
- */
- bool is_valid_die_ptr(const void* ptr, size_t size) const {
- return debug_info_.is_contained(ptr, size);
- }
-
- /* Checks, if given address range is contained in the mapped .debug_abbrev
- * section of this file.
- * Param:
- * ptr - Starting address of the range.
- * size - Range size in bytes.
- * Return:
- * true if given address range is contained in the mapped .debug_abbrev
- * section of this file, or false if any part of the range doesn't belong
- * to that section.
- */
- bool is_valid_abbr_ptr(const void* ptr, size_t size) const {
- return debug_abbrev_.is_contained(ptr, size);
- }
-
- /* Checks if given pointer addresses a valid compilation unit header in the
- * mapped .debug_info section of the ELF file.
- * Param:
- * cu_header - Pointer to a compilation unit header to check.
- * Return
- * true, if given pointer addresses a valid compilation unit header, or
- * false, if it's not. A valid CU header must be fully conained inside
- * .debug_info section of the ELF file, and its size must not be zero.
- */
- bool is_valid_cu(const void* cu_header) const {
- if (is_DWARF_64()) {
- return is_valid_die_ptr(cu_header, sizeof(Dwarf64_CUHdr)) &&
- reinterpret_cast<const Dwarf64_CUHdr*>(cu_header)->size_hdr.size != 0;
- } else {
- return is_valid_die_ptr(cu_header, sizeof(Dwarf32_CUHdr)) &&
- reinterpret_cast<const Dwarf32_CUHdr*>(cu_header)->size_hdr.size != 0;
- }
- }
-
- /* Gets range's low and high pc for the given range reference in the mapped
- * .debug_ranges section of an ELF file.
- * Template param:
- * AddrType - Defines pointer type for the CU the range belongs to. CU's
- * pointer type can be defined independently from ELF and DWARF types,
- * and is encoded in address_size field of the CU header in .debug_info
- * section of ELF file.
- * Param:
- * offset - Byte offset within .debug_ranges section of the range record.
- * low - Upon successful return contains value for range's low pc.
- * high - Upon successful return contains value for range's high pc.
- * Return:
- * true on success, or false, if requested record is not fully contained
- * in the .debug_ranges section.
- */
- template<typename AddrType>
- bool get_range(Elf_Word offset, AddrType* low, AddrType* high) {
- const AddrType* ptr = INC_CPTR_T(AddrType, debug_ranges_.data(), offset);
- assert(debug_ranges_.is_contained(ptr, sizeof(AddrType) * 2));
- if (!debug_ranges_.is_contained(ptr, sizeof(AddrType) * 2)) {
- _set_errno(EINVAL);
- return false;
- }
- *low = pull_val(ptr);
- *high = pull_val(ptr + 1);
- return true;
- }
-
- protected:
- /* Mapped ELF string section. */
- ElfMappedSection string_section_;
-
- /* Mapped .debug_info section. */
- ElfMappedSection debug_info_;
-
- /* Mapped .debug_abbrev section. */
- ElfMappedSection debug_abbrev_;
-
- /* Mapped .debug_str section. */
- ElfMappedSection debug_str_;
-
- /* Mapped .debug_line section. */
- ElfMappedSection debug_line_;
-
- /* Mapped .debug_ranges section. */
- ElfMappedSection debug_ranges_;
-
- /* Base address of the loaded module (if fixed), or 0 if module doesn't get
- * loaded at fixed address. */
- Elf_Xword fixed_base_address_;
-
- /* Handle to the ELF file represented with this instance. */
- MapFile* elf_handle_;
-
- /* Path to the ELF file represented with this instance. */
- char* elf_file_path_;
-
- /* DWARF objects allocator for this instance. */
- class ElfAllocator* allocator_;
-
- /* Beginning of the cached ELF's section table. */
- void* sec_table_;
-
- /* Number of sections in the ELF file wrapped by this instance. */
- Elf_Half sec_count_;
-
- /* Byte size of an entry in the section table. */
- Elf_Half sec_entry_size_;
-
- /* Head of compilation unit list, collected during the parsing. */
- class DwarfCU* last_cu_;
-
- /* Number of compilation units in last_cu_ list. */
- int cu_count_;
-
- /* Flags ELF's CPU architecture: 64 (true), or 32 bits (false). */
- bool is_ELF_64_;
-
- /* Flags endianness of the processed ELF file. true indicates that ELF file
- * data is stored in big-endian form, false indicates that ELF file data is
- * stored in big-endian form.
- */
- bool is_elf_big_endian_;
-
- /* Flags whether or not endianness of CPU this library is built for matches
- * endianness of the ELF file that is represented with this instance.
- */
- bool same_endianness_;
-
- /* Flags DWARF format: 64, or 32 bits. DWARF format is determined by looking
- * at the first 4 bytes of .debug_info section (which is the beginning of the
- * first compilation unit header). If first 4 bytes contain 0xFFFFFFFF, the
- * DWARF is 64 bit. Otherwise, DWARF is 32 bit. */
- bool is_DWARF_64_;
-
- /* Flags executable file. If this member is 1, ELF file represented with this
- * instance is an executable. If this member is 0, file is a shared library.
- */
- bool is_exec_;
-};
-
-/* Encapsulates architecture-dependent functionality of an ELF file.
- * Template param:
- * Elf_Addr - type for an address field in ELF file. Must be:
- * - Elf32_Addr for 32-bit CPU, or
- * - Elf64_Addr for 64-bit CPU.
- * Elf_Off - type for an offset field in ELF file. Must be:
- * - Elf64_Off for 32-bit CPU, or
- * - Elf64_Off for 64-bit CPU.
- */
-template <typename Elf_Addr, typename Elf_Off>
-class ElfFileImpl : protected ElfFile {
-/* Instance of this class must be instantiated from
- * ElfFile::Create() method only. */
-friend class ElfFile;
- protected:
- /* Constructs ElfFileImpl instance. */
- ElfFileImpl() {
- };
-
- /* Destructs ElfFileImpl instance. */
- ~ElfFileImpl() {
- }
-
- protected:
- /* Initializes instance. This is an override of the base class method.
- * See ElfFile::initialize().
- */
- bool initialize(const Elf_CommonHdr* elf_hdr, const char* path);
-
- /* Parses DWARF, and buids list of compilation units for this ELF file.
- * This is an implementation of the base class' abstract method.
- * See ElfFile::parse_compilation_units().
- */
- virtual int parse_compilation_units(const DwarfParseContext* parse_context);
-
- /* Gets section information by section name.
- * Param:
- * name - Name of the section to get information for.
- * offset - Upon success contains offset of the section data in ELF file.
- * size - Upon success contains size of the section data in ELF file.
- * Return:
- * true on sucess, or false if section with such name doesn't exist in
- * this ELF file.
- */
- bool get_section_info_by_name(const char* name,
- Elf_Off* offset,
- Elf_Word* size);
-
- /* Maps section by its name.
- * Param:
- * name - Name of the section to map.
- * section - Upon success contains section's mapping information.
- * Return:
- * true on sucess, or false if section with such name doesn't exist in
- * this ELF file, or mapping has failed.
- */
- bool map_section_by_name(const char* name, ElfMappedSection* section);
-};
-
-#endif // ELFF_ELF_FILE_H_
diff --git a/distrib/elff/elff/elf_mapped_section.cc b/distrib/elff/elff/elf_mapped_section.cc
deleted file mode 100644
index 99229c2..0000000
--- a/distrib/elff/elff/elf_mapped_section.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of a class ElfMappedSection, that encapsulates
- * a section of an ELF file, mapped to memory.
- */
-
-#include "elff/elf_defs.h"
-#include "elff/elf_mapped_section.h"
-
-ElfMappedSection::ElfMappedSection()
- : mapped_at_(NULL),
- data_(NULL),
- size_(0) {
-}
-
-ElfMappedSection::~ElfMappedSection() {
- if (mapped_at_ != NULL) {
- mapfile_unmap(mapped_at_, diff_ptr(mapped_at_, data_) + size_);
- }
-}
-
-bool ElfMappedSection::map(MapFile* handle,
- Elf_Xword offset,
- Elf_Word size) {
- void* section_ptr;
- size_t mapped_bytes;
- mapped_at_ = mapfile_map(handle, offset, size, PROT_READ,
- §ion_ptr, &mapped_bytes);
- if (mapped_at_ == NULL) {
- return false;
- }
-
- data_ = section_ptr;
- size_ = (Elf_Word)mapped_bytes;
-
- return true;
-}
diff --git a/distrib/elff/elff/elf_mapped_section.h b/distrib/elff/elff/elf_mapped_section.h
deleted file mode 100644
index 805c9e4..0000000
--- a/distrib/elff/elff/elf_mapped_section.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declaration of a class ElfMappedSection, that encapsulates
- * a section of an ELF file, mapped to memory.
- */
-
-#ifndef ELFF_ELF_MAPPED_SECTION_H_
-#define ELFF_ELF_MAPPED_SECTION_H_
-
-#include "elff/elf_defs.h"
-#include "elff/elff_map_file.h"
-
-/* Encapsulates a section of an ELF file, mapped to memory. */
-class ElfMappedSection {
- public:
- /* Constructs ElfMappedSection instance. */
- ElfMappedSection();
-
- /* Destructs ElfMappedSection instance. */
- ~ElfMappedSection();
-
- /* Maps ELF file section to memory.
- * Param:
- * handle - Handle to an opened ELF file.
- * offset - Offset of the beginning of the section data in ELF file.
- * NOTE: we explicitly use 64-bit type for this parameter, since we may
- * still allow 32-bit library to process 64 bits ELF/DWARF formats. We
- * really only care about section size being small enough to fit in 32
- * bits value in this case (which seems to be always true for ELF files,
- * as section size is encoded with 32-bit value even in 64-bit ELF file).
- * size - Section byte size in ELF file.
- * Return:
- * true on success, or false on failure, with errno providing extended
- * error information.
- * NOTE: if section has already been mapped, this method immediately
- * returns with success.
- */
- bool map(MapFile* handle, Elf_Xword offset, Elf_Word size);
-
- /* Checks if section has been mapped. */
- bool is_mapped() const {
- return mapped_at_ != NULL;
- }
-
- /* Gets address of the beginning of the mapped section. */
- const void* data() const {
- assert(is_mapped());
- return data_;
- }
-
- /* Gets section size. */
- Elf_Word size() const {
- assert(is_mapped());
- return size_;
- }
-
- /* Checks if an address range is fully contained in this section. */
- bool is_contained(const void* ptr, size_t rsize) const {
- assert(is_mapped());
- return is_mapped() && is_in_section(ptr, rsize, data(), size());
- }
-
- protected:
- /* Beginning of the memory mapping, containing the section.
- * NOTE: due to page alignment requirements of the mapping API, mapping
- * address may differ from the address where the actual section data
- * starts inside that mapping.
- */
- void* mapped_at_;
-
- /* Address of the beginning of the mapped section. */
- const void* data_;
-
- /* Section size. */
- Elf_Word size_;
-};
-
-#endif // ELFF_ELF_MAPPED_SECTION_H_
diff --git a/distrib/elff/elff/elff-common.h b/distrib/elff/elff/elff-common.h
deleted file mode 100644
index a8ae7fb..0000000
--- a/distrib/elff/elff/elff-common.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Includes common headers for the ELFF library.
- */
-
-#ifndef ELFF_ELFF_COMMON_H_
-#define ELFF_ELFF_COMMON_H_
-
-#include "stddef.h"
-#include "sys/types.h"
-#include "assert.h"
-#include "memory.h"
-#include "errno.h"
-#include "stdlib.h"
-#ifdef WIN32
-#include "windows.h"
-#else // WIN32
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#endif // WIN32
-
-static inline void _set_errno(uint32_t err) {
- errno = err;
-}
-
-#endif // ELFF_ELFF_COMMON_H_
diff --git a/distrib/elff/elff/elff_api.cc b/distrib/elff/elff/elff_api.cc
deleted file mode 100644
index 7430a79..0000000
--- a/distrib/elff/elff/elff_api.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains implementation of routines that encapsulte an API for parsing
- * an ELF file containing debugging information in DWARF format.
- */
-
-#include "elff/elff_api.h"
-#include "elff/elf_file.h"
-#include "elff/dwarf_defs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-ELFF_HANDLE
-elff_init(const char* elf_file_path)
-{
- ElfFile* elf_file = ElfFile::Create(elf_file_path);
- return reinterpret_cast<ELFF_HANDLE>(elf_file);
-}
-
-void
-elff_close(ELFF_HANDLE handle)
-{
- if (handle != NULL) {
- delete reinterpret_cast<ElfFile*>(handle);
- }
-}
-
-int
-elff_is_exec(ELFF_HANDLE handle)
-{
- assert(handle != NULL);
- if (handle == NULL) {
- _set_errno(EINVAL);
- return -1;
- }
- return reinterpret_cast<ElfFile*>(handle)->is_exec();
-}
-
-int
-elff_get_pc_address_info(ELFF_HANDLE handle,
- uint64_t address,
- Elf_AddressInfo* address_info)
-{
- assert(handle != NULL && address_info != NULL);
- if (handle == NULL || address_info == NULL) {
- _set_errno(EINVAL);
- return -1;
- }
-
- if (reinterpret_cast<ElfFile*>(handle)->get_pc_address_info(address,
- address_info)) {
- return 0;
- } else {
- return -1;
- }
-}
-
-void
-elff_free_pc_address_info(ELFF_HANDLE handle, Elf_AddressInfo* address_info)
-{
- assert(handle != NULL && address_info != NULL);
- if (handle == NULL || address_info == NULL) {
- return;
- }
- reinterpret_cast<ElfFile*>(handle)->free_pc_address_info(address_info);
-}
-
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-
diff --git a/distrib/elff/elff/elff_api.h b/distrib/elff/elff/elff_api.h
deleted file mode 100644
index d18798b..0000000
--- a/distrib/elff/elff/elff_api.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declaration of types, strctures, routines, etc. that encapsulte
- * an API for parsing an ELF file containing debugging information in DWARF
- * format.
- */
-
-#ifndef ELFF_API_H_
-#define ELFF_API_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-/* Defines type for a handle used in ELFF API. */
-typedef void* ELFF_HANDLE;
-
-/* Defines an entry for 'inline_stack' array in Elf_AddressInfo structure.
- * Each entry in the array represents a routine, where routine represented
- * with the previous array entry has been inlined. First element in the array
- * (at index 0) represents information for the inlined routine, referenced by
- * Elf_AddressInfo structure itself. If name for a routine was not available
- * (DW_AT_name attribute was missing), routine name is set to "<unknown>".
- * Last entry in the array has all its fields set to zero. It's sufficient
- * just to check for routine_name field of this structure to be NULL to detect
- * last entry in the array.
- */
-typedef struct Elf_InlineInfo {
- /* Name of the routine where previous routine is inlined.
- * This field can never be NULL, except for the last array entry.
- */
- const char* routine_name;
-
- /* Source file name where routine is inlined.
- * This field can be NULL, if it was not possible to obtain information
- * about source file location for the routine. If this field is NULL, content
- * of inlined_in_file_dir and inlined_at_line fields is undefined and should
- * be ignored. */
- const char* inlined_in_file;
-
- /* Source file directory where routine is inlined.
- * If inlined_in_file field contains NULL, content of this field is undefined
- * and should be ignored. */
- const char* inlined_in_file_dir;
-
- /* Source file line number where routine is inlined.
- * If inlined_in_file field contains NULL, content of this field is undefined
- * and should be ignored. */
- uint32_t inlined_at_line;
-} Elf_InlineInfo;
-
-/* Checks if an entry is the last entry in the array.
- * Return:
- * Boolean: 1 if this is last entry, or zero otherwise.
- */
-static inline int
-elfinlineinfo_is_last_entry(const Elf_InlineInfo* info) {
- return info->routine_name == 0;
-}
-
-/* PC address information descriptor.
- * This descriptor contains as much information about a PC address as it was
- * possible to collect from an ELF file. */
-typedef struct Elf_AddressInfo {
- /* Name of the routine containing the address. If name of the routine
- * was not available (DW_AT_name attribute was missing) this field
- * is set to "<unknown>". */
- const char* routine_name;
-
- /* Name of the source file containing the routine. If source location for the
- * routine was not available, this field is set to NULL, and content of
- * dir_name, and line_number fields of this structure is not defined. */
- const char* file_name;
-
- /* Path to the source file directory. If file_name field of this structure is
- * NULL, content of this field is not defined. */
- const char* dir_name;
-
- /* Line number in the source file for the address. If file_name field of this
- * structure is NULL, content of this field is not defined. */
- uint32_t line_number;
-
- /* If routine that contains the given address has been inlined (or it is part
- * of even deeper inline branch) this array lists information about that
- * inline branch rooting to the first routine that has not been inlined. The
- * first element in the array references a routine, where routine containing
- * the given address has been inlined. The second entry contains information
- * about a routine referenced by the first entry (and so on). If routine,
- * containing the given address has not been inlined, this field is set to
- * NULL. The array ends with an entry containing all zeroes. */
- Elf_InlineInfo* inline_stack;
-} Elf_AddressInfo;
-
-//=============================================================================
-// API routines
-//=============================================================================
-
-/* Initializes ELFF API for the given ELF file.
- * Param:
- * elf_file_path - Path to the ELF file to initialize API for.
- * Return:
- * On success, this routine returns a handle that can be used in subsequent
- * calls to this API dealing with the given ELF file. On failure this routine
- * returns NULL, with errno providing extended error information.
- * NOTE: handle returned from this routine must be closed using elff_close().
- */
-ELFF_HANDLE elff_init(const char* elf_file_path);
-
-/* Closes a handle obtained after successful call to elff_init routine.
- * Param:
- * handle - A handle to close. This handle must be a handle returned from
- * a successful call to elff_init routine.
- */
-void elff_close(ELFF_HANDLE handle);
-
-/* Checks if ELF file represents an executable file, or a shared library.
- * handle - A handle obtained from successful call to elff_init().
- * Return:
- * 1 if ELF file represents an executable file, or
- * 0 if ELF file represents a shared library, or
- * -1 if handle is invalid.
- */
-int elff_is_exec(ELFF_HANDLE handle);
-
-/* Gets PC address information.
- * Param:
- * handle - A handle obtained from successful call to elff_init().
- * address - PC address to get information for. Address must be relative to
- * the beginning of ELF file represented by the handle parameter.
- * address_info - Upon success contains information about routine(s) that
- * contain the given address.
- * Return:
- * 0 if routine(s) containing the given address has been found and information
- * has been saved into address_info, or -1 if no appropriate routine for that
- * address has been found, or there was a memory error when collecting
- * routine(s) information. In case of failure, errno provides extended
- * error information.
- * NOTE: Successful call to this routine must be complimented with a call
- * to free_pc_address_info, so ELFF API can release resources aquired for
- * address_info.
- */
-int elff_get_pc_address_info(ELFF_HANDLE handle,
- uint64_t address,
- Elf_AddressInfo* address_info);
-
-/* Frees resources acquired for address information in successful call to
- * get_pc_address_info().
- * Param:
- * handle - A handle obtained from successful call to elff_init().
- * address_info - Address information structure, initialized in successful
- * call to get_pc_address_info() routine.
- */
-void elff_free_pc_address_info(ELFF_HANDLE handle,
- Elf_AddressInfo* address_info);
-
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-
-#endif // ELFF_API_H_
diff --git a/distrib/elff/elff/elff_elf.h b/distrib/elff/elff/elff_elf.h
deleted file mode 100644
index 00e73f7..0000000
--- a/distrib/elff/elff/elff_elf.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-/*
- * Contains declarations of types, constants and structures
- * describing ELF file format.
- */
-
-#ifndef ELFF_ELH_H_
-#define ELFF_ELH_H_
-
-#include <stdint.h>
-#include "elff/elff-common.h"
-
-//=============================================================================
-// ELF file definitions
-//=============================================================================
-
-/*
- * ELF format documentation uses Elf##_Xxx notation for data types, where
- * ## stands for CPU architecture (32, or 64 bit), and Xxx stands for a
- * specific type. For the sake of compliance, we will follow doc's notation
- * when defining types used in ELF file descriptors. However, for the sake of
- * code simplicity, we will drop CPU architecture index from the types that
- * have equal sizes on both, 32 and 64 bit architectures.
- */
-
-/*
- * Architecture independent types.
- */
-
-typedef uint8_t Elf_Byte;
-typedef int8_t Elf_Sbyte;
-
-typedef uint16_t Elf_Half;
-typedef int16_t Elf_Shalf;
-
-typedef uint32_t Elf_Word;
-typedef int32_t Elf_Sword;
-
-typedef uint64_t Elf_Xword;
-typedef int64_t Elf_Sxword;
-
-/*
- * Architecture dependent types.
- */
-
-/* 32-bit ELF address. */
-typedef uint32_t Elf32_Addr;
-/* 32-bit ELF offset. */
-typedef uint32_t Elf32_Off;
-
-/* 64-bit ELF address. */
-typedef uint64_t Elf64_Addr;
-/* 64-bit ELF offset. */
-typedef uint64_t Elf64_Off;
-
-//=============================================================================
-// ELF file header
-//=============================================================================
-
-/* Byte size of the fixed portion of ELF header. */
-#define EI_NIDENT 16
-
-/* Common (architecture independent portion of) ELF file header,
- * that starts at offset 0 in ELF file.
- */
-typedef struct Elf_CommonHdr {
- union {
- struct {
- /* ei_mag0 - ei_mag3 contain ELF header signature. See ELFMAGx bellow. */
- Elf_Byte ei_mag0;
- Elf_Byte ei_mag1;
- Elf_Byte ei_mag2;
- Elf_Byte ei_mag3;
-
- /* File class (32, or 64 bits). See ELFCLASSxxx bellow. */
- Elf_Byte ei_class;
-
- /* Data encoding (endianness). See ELFDATAxxx bellow. */
- Elf_Byte ei_data;
-
- /* ELF header version number. */
- Elf_Byte ei_version;
- } ei_info;
- unsigned char e_ident[EI_NIDENT];
- };
-
- /* File type (executable, shared object, etc.) */
- Elf_Half e_type;
-
- /* Processor type. */
- Elf_Half e_machine;
-
- /* File version. */
- Elf_Word e_version;
-} Elf_CommonHdr;
-
-
-/* ELF header signature. */
-#define ELFMAG0 0x7f
-#define ELFMAG1 'E'
-#define ELFMAG2 'L'
-#define ELFMAG3 'F'
-#define ELFMAG "\177ELF"
-#define SELFMAG 4
-
-/*
- * Possible ei_class values.
- */
-
-/* Invalid. */
-#define ELFCLASSNONE 0
-/* It's 32-bit ELF file. */
-#define ELFCLASS32 1
-/* It's 64-bit ELF file. */
-#define ELFCLASS64 2
-
-/*
- * Possible ei_data values.
- */
-
-/* Invalid. */
-#define ELFDATANONE 0
-/* ELF data is formatted in little-endian. */
-#define ELFDATA2LSB 1
-/* ELF data is formatted in big-endian. */
-#define ELFDATA2MSB 2
-
-/* Tempated (architecture dependent) ELF file header.
- * Template param:
- * Elf_Addr - Actual type for address encoding (Elf32_Addr, or Elf64_Addr).
- * Elf_Off - Actual type for offset encoding (Elf32_Off, or Elf64_Off).
- */
-template <typename Elf_Addr, typename Elf_Off>
-struct Elf_FHdr {
- /* Common header. */
- Elf_CommonHdr common;
-
- /* Module entry point. */
- Elf_Addr e_entry;
-
- /* Programm header table offset (in bytes) from the beginning of the file.
- * Zero if there is no programm header in this file.
- */
- Elf_Off e_phoff;
-
- /* Section header table offset (in bytes) from the beginning of the file.
- * Zero if there is no section header in this file.
- */
- Elf_Off e_shoff;
-
- /* Processor-specific flags. */
- Elf_Word e_flags;
-
- /* This header size in bytes. */
- Elf_Half e_ehsize;
-
- /* Byte size of an entry in programm header table. All entries
- * in the table are the same size.
- */
- Elf_Half e_phentsize;
-
- /* Number of entries in programm header table. */
- Elf_Half e_phnum;
-
- /* Byte size of an entry in section header table. All entries
- * in the table are the same size.
- */
- Elf_Half e_shentsize;
-
- /* Number of entries in section header table. */
- Elf_Half e_shnum;
-
- /* Zero-based index of an entry for name string table section in the section
- * header table. If no such section exists in the file this field contains
- * SHN_UNDEF value.
- */
- Elf_Half e_shstrndx;
-};
-/* 32-bit ELF header. */
-typedef Elf_FHdr<Elf32_Addr, Elf32_Off> Elf32_FHdr;
-/* 64-bit ELF header. */
-typedef Elf_FHdr<Elf64_Addr, Elf64_Off> Elf64_FHdr;
-
-//=============================================================================
-// ELF section header
-//=============================================================================
-
-/* Templated (architecture dependent) section header for ELF file.
- * Template param:
- * Elf_Addr - Actual type for address encoding (Elf32_Addr, or Elf64_Addr).
- * Elf_Off - Actual type for offset encoding (Elf32_Off, or Elf64_Off).
- */
-template <typename Elf_Addr, typename Elf_Off>
-struct Elf_SHdr {
- /* Index (byte offset) of section name in the name string table section. */
- Elf_Word sh_name;
-
- /* Section type and semantics. */
- Elf_Word sh_type;
-
- /* Section flags and attributes. */
- Elf_Word sh_flags;
-
- /* Section address in the memory image of the process. */
- Elf_Addr sh_addr;
-
- /* Byte offset from the beginning of the ELF file to the first
- * byte in the section.
- */
- Elf_Off sh_offset;
-
- /* Section size in bytes. */
- Elf_Word sh_size;
-
- /* Section header table index link. Depends on section type. */
- Elf_Word sh_link;
-
- /* Extra section information, depending on the section type. */
- Elf_Word sh_info;
-
- /* Address alignment constrains. 0 and 1 means that section has no
- * alignment constrains.
- */
- Elf_Word sh_addralign;
-
- /* Entry size for sections that hold some kind of a table. */
- Elf_Word sh_entsize;
-};
-/* 32-bit section header. */
-typedef Elf_SHdr<Elf32_Addr, Elf32_Off> Elf32_SHdr;
-/* 64-bit section header. */
-typedef Elf_SHdr<Elf64_Addr, Elf64_Off> Elf64_SHdr;
-
-/*
- * Special section indices
- */
-#define SHN_UNDEF 0
-#define SHN_LORESERVE 0xff00
-#define SHN_LOPROC 0xff00
-#define SHN_HIPROC 0xff1f
-#define SHN_LOOS 0xff20
-#define SHN_HIOS 0xff3f
-#define SHN_ABS 0xfff1
-#define SHN_COMMON 0xfff2
-#define SHN_XINDEX 0xffff
-#define SHN_HIRESERVE 0xffff
-
-/*
- * Values for sh_type
- */
-#define SHT_NULL 0
-#define SHT_PROGBITS 1
-#define SHT_SYMTAB 2
-#define SHT_STRTAB 3
-#define SHT_RELA 4
-#define SHT_HASH 5
-#define SHT_DYNAMIC 6
-#define SHT_NOTE 7
-#define SHT_NOBITS 8
-#define SHT_REL 9
-#define SHT_SHLIB 10
-#define SHT_DYNSYM 11
-#define SHT_INIT_ARRAY 14
-#define SHT_FINI_ARRAY 15
-#define SHT_PREINIT_ARRAY 16
-#define SHT_GROUP 17
-#define SHT_SYMTAB_SHNDX 18
-#define SHT_NUM 19
-
-#endif // ELFF_ELH_H_
diff --git a/distrib/elff/elff/elff_map_file.h b/distrib/elff/elff/elff_map_file.h
deleted file mode 100644
index a5fd08b..0000000
--- a/distrib/elff/elff/elff_map_file.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-#ifndef ELFF_MAP_FILE_H
-#define ELFF_MAP_FILE_H
-
-// TODO(digit): Provide standalone implementation for the library.
-#include "android/utils/mapfile.h"
-
-#endif // ELFF_MAP_FILE_H
diff --git a/docs/ANDROID-MEMCHECK.TXT b/docs/ANDROID-MEMCHECK.TXT
deleted file mode 100644
index 95e3959..0000000
--- a/docs/ANDROID-MEMCHECK.TXT
+++ /dev/null
@@ -1,57 +0,0 @@
-ANDROID MEMORY CHECKER COMPONENT
-
-The docs/ANDROID-MEMCHECK.TXT document contains description of a memory checker
-implemented in the emulator
-
-The memory checker is intended to catch simple memory access violations in the
-emulated system, including:
-- Memory leaks
-- Attempts to free / reallocate invalid pointers (including pointers that have
- already been freed, or reallocated).
-- Attempts to read from / write to areas outside of allocated blocks.
-
-To provide this functionality, the memory checker works in conjunction with
-an instrumented version of libc.so library used by the emulated system. Both,
-emulator's memory checking, and libc's instrumentation are turned on by the
--memcheck command-line option. If this argument is omitted, libc.so will run in
-the regular, not instrumented mode, and the emulator will not perform any
-actions related to the memory checking.
-
-The way emulator and instrumented libc.so work together is as such:
-libc.so hooks up every memory allocation call (malloc, free, calloc, realloc,
-and memalign). For each such call, libc sends a notification message to the
-emulator, providing an allocation descriptor that contains information about
-allocation block and operation that is being performed on this block. Emulator
-and libc use a "magic page" that is set up in such a way that every write to
-that page on the emulated system produces some sort of event in the emulator,
-allowing emulator to receive data that emulated system has written to the "magic
-page". For more info on that, see hw/android/goldfish/trace.c
-
-In response to events, received from libc.so, emulator keep tracks of all blocks
-that have been allocated from the heap on emulated system. Block descriptors are
-kept in a per-process basis, so when a process exits, emulator can list all the
-leaked blocks the process left behind.
-
-When a free, or realloc operation is performed on the emulated system, emulator
-can verify that the pointer passed to free/realloc matches the address of a
-block recorded in the current process' descriptors table. This way emulator can
-detect and report attempts to free/reallocate invalid pointers.
-
-To detect read/write violations, emulator uses prefix and suffix guarding areas
-that were added to the allocated blocks by the instrumented libc. To watch for
-access violations, emulator instruments ld_/st_mmu routines to verify that
-accessed memory doesn't belong to a guarding area of a block allocated in
-context of the current process.
-
-There are some tricky things like:
-- invalidating every page containing allocated blocks every time anything has
- been read, or written to that page, so we can be sure that we don't miss AV
- on condition that page has been cached and ld_/st_mmu is omitted when
- accessing memory in that page.
-- Keeping track of each thread calling stack, so when access violation is
- reported, we can pinpoint violation to precise location in the source code.
-- etc.
-
-All the code related to memory checking is guarded in emulator's code by
-CONFIG_ANDROID_MEMCHECK macro, making it easy to spot changes related to it in the
-sources.
diff --git a/exec.c b/exec.c
index 6f29389..b0ec6e2 100644
--- a/exec.c
+++ b/exec.c
@@ -48,9 +48,6 @@
#if defined(CONFIG_USER_ONLY)
#include <qemu.h>
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck_api.h"
-#endif // CONFIG_ANDROID_MEMCHECK
//#define DEBUG_SUBPAGE
diff --git a/hw/android/android_arm.c b/hw/android/android_arm.c
index 2ee31db..52ad2ab 100644
--- a/hw/android/android_arm.c
+++ b/hw/android/android_arm.c
@@ -22,9 +22,6 @@
#include "ui/console.h"
#include "sysemu/blockdev.h"
#include "hw/android/goldfish/pipe.h"
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck_api.h"
-#endif // CONFIG_ANDROID_MEMCHECK
#include "android/utils/debug.h"
@@ -126,11 +123,6 @@
goldfish_add_device_no_io(&nand_device);
nand_dev_init(nand_device.base);
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- trace_dev_init();
- }
-#endif // CONFIG_ANDROID_MEMCHECK
bool newDeviceNaming =
(androidHwConfig_getKernelDeviceNaming(android_hw) >= 1);
diff --git a/hw/android/android_mips.c b/hw/android/android_mips.c
index 4b25660..2f13a1e 100644
--- a/hw/android/android_mips.c
+++ b/hw/android/android_mips.c
@@ -21,9 +21,6 @@
#include "android/globals.h"
#include "audio/audio.h"
#include "sysemu/blockdev.h"
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck_api.h"
-#endif // CONFIG_ANDROID_MEMCHECK
#include "android/utils/debug.h"
@@ -227,11 +224,6 @@
nand_dev_init(nand_device.base);
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- trace_dev_init();
- }
-#endif // CONFIG_ANDROID_MEMCHECK
bool newDeviceNaming =
(androidHwConfig_getKernelDeviceNaming(android_hw) >= 1);
pipe_dev_init(newDeviceNaming);
diff --git a/hw/android/goldfish/trace.c b/hw/android/goldfish/trace.c
index 27fada5..9ca4cd2 100644
--- a/hw/android/goldfish/trace.c
+++ b/hw/android/goldfish/trace.c
@@ -17,10 +17,6 @@
#include "hw/android/goldfish/trace.h"
#include "hw/android/goldfish/vmem.h"
#include "sysemu/sysemu.h"
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck.h"
-#include "android/qemu/memcheck/memcheck_util.h"
-#endif // CONFIG_ANDROID_MEMCHECK
/* Set to 1 to debug tracing */
#define DEBUG 0
@@ -76,11 +72,6 @@
if (trace_filename != NULL) {
D("QEMU.trace: kernel, context switch %u\n", value);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_switch(value);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
tid = (unsigned) value;
break;
case TRACE_DEV_REG_TGID: // save the tgid for the following fork/clone
@@ -95,22 +86,12 @@
if (trace_filename != NULL) {
D("QEMU.trace: kernel, fork %u\n", value);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_fork(tgid, value);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
break;
case TRACE_DEV_REG_CLONE: // fork, clone new pid (i.e. thread)
DPID("QEMU.trace: clone (pid=%d tgid=%d value=%d)\n", pid, tgid, value);
if (trace_filename != NULL) {
D("QEMU.trace: kernel, clone %u\n", value);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_clone(tgid, value);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
break;
case TRACE_DEV_REG_EXECVE_VMSTART: // execve, vstart
vstart = value;
@@ -127,16 +108,6 @@
D("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n",
vstart, vend, eoff, exec_path);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- if (exec_path[0] == '\0') {
- // vstrcpy may fail to copy path. In this case lets do it
- // differently.
- memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
- }
- memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
exec_path[0] = 0;
break;
case TRACE_DEV_REG_CMDLINE_LEN: // execve, process cmdline length
@@ -147,11 +118,6 @@
if (trace_filename != NULL) {
D("QEMU.trace: kernel, execve [%.*s]\n", cmdlen, exec_arg);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_set_cmd_line(exec_arg, cmdlen);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
#if DEBUG || DEBUG_PID
if (trace_filename != NULL) {
int i;
@@ -168,11 +134,6 @@
if (trace_filename != NULL) {
D("QEMU.trace: kernel, exit %x\n", value);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_exit(value);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
break;
case TRACE_DEV_REG_NAME: // record thread name
vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
@@ -193,26 +154,11 @@
if (trace_filename != NULL) {
D("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, exec_path);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- if (exec_path[0] == '\0') {
- // vstrcpy may fail to copy path. In this case lets do it
- // differently.
- memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
- }
- memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
exec_path[0] = 0;
break;
case TRACE_DEV_REG_INIT_PID: // init, name the pid that starts before device registered
pid = value;
DPID("QEMU.trace: pid=%d\n", value);
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_init_pid(value);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
break;
case TRACE_DEV_REG_INIT_NAME: // init, the comm of the init pid
vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
@@ -265,11 +211,6 @@
unmap_start = value;
break;
case TRACE_DEV_REG_UNMAP_END:
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (memcheck_enabled) {
- memcheck_unmap(unmap_start, value);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
break;
case TRACE_DEV_REG_METHOD_ENTRY:
@@ -286,38 +227,6 @@
}
break;
-#ifdef CONFIG_ANDROID_MEMCHECK
- case TRACE_DEV_REG_MALLOC:
- if (memcheck_enabled) {
- memcheck_guest_alloc(value);
- }
- break;
-
- case TRACE_DEV_REG_FREE_PTR:
- if (memcheck_enabled) {
- memcheck_guest_free(value);
- }
- break;
-
- case TRACE_DEV_REG_QUERY_MALLOC:
- if (memcheck_enabled) {
- memcheck_guest_query_malloc(value);
- }
- break;
-
- case TRACE_DEV_REG_LIBC_INIT:
- if (memcheck_enabled) {
- memcheck_guest_libc_initialized(value);
- }
- break;
-
- case TRACE_DEV_REG_PRINT_USER_STR:
- if (memcheck_enabled) {
- memcheck_guest_print_str(value);
- }
- break;
-#endif // CONFIG_ANDROID_MEMCHECK
-
default:
if (offset < 4096) {
cpu_abort(cpu_single_env, "trace_dev_write: Bad offset %x\n", offset);
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 7befcdd..6939cb4 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -182,18 +182,6 @@
struct TranslationBlock *jmp_next[2];
struct TranslationBlock *jmp_first;
uint32_t icount;
-
-#ifdef CONFIG_ANDROID_MEMCHECK
- /* Maps PCs in this translation block to corresponding PCs in guest address
- * space. The array is arranged in such way, that every even entry contains
- * PC in the translation block, followed by an odd entry that contains
- * guest PC corresponding to that PC in the translation block. This
- * arrangement is set by tcg_gen_code_common that initializes this array
- * when performing guest code translation. */
- uintptr_t* tpc2gpc;
- /* Number of pairs (pc_tb, pc_guest) in tpc2gpc array. */
- unsigned int tpc2gpc_pairs;
-#endif // CONFIG_ANDROID_MEMCHECK
};
#include "exec/spinlock.h"
@@ -235,67 +223,13 @@
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
-/* Gets translated PC for a given (translated PC, guest PC) pair.
- * Return:
- * Translated PC, or NULL if pair index was too large.
- */
-static inline target_ulong
-tb_get_tb_pc(const TranslationBlock* tb, unsigned int pair)
-{
- return (tb->tpc2gpc != NULL && pair < tb->tpc2gpc_pairs) ?
- tb->tpc2gpc[pair * 2] : 0;
-}
-
-/* Gets guest PC for a given (translated PC, guest PC) pair.
- * Return:
- * Guest PC, or NULL if pair index was too large.
- */
-static inline target_ulong
-tb_get_guest_pc(const TranslationBlock* tb, unsigned int pair)
-{
- return (tb->tpc2gpc != NULL && pair < tb->tpc2gpc_pairs) ?
- tb->tpc2gpc[pair * 2 + 1] : 0;
-}
-
-/* Gets guest PC for a given translated PC.
- * Return:
- * Guest PC for a given translated PC, or NULL if there was no pair, matching
- * translated PC in tb's tpc2gpc array.
- */
-static inline target_ulong
-tb_search_guest_pc_from_tb_pc(const TranslationBlock* tb, target_ulong tb_pc)
-{
- if (tb->tpc2gpc != NULL && tb->tpc2gpc_pairs != 0) {
- unsigned int m_min = 0;
- unsigned int m_max = (tb->tpc2gpc_pairs - 1) << 1;
- /* Make sure that tb_pc is within TB array. */
- if (tb_pc < tb->tpc2gpc[0]) {
- return 0;
- }
- while (m_min <= m_max) {
- const unsigned int m = ((m_min + m_max) >> 1) & ~1;
- if (tb_pc < tb->tpc2gpc[m]) {
- m_max = m - 2;
- } else if (m == m_max || tb_pc < tb->tpc2gpc[m + 2]) {
- return tb->tpc2gpc[m + 1];
- } else {
- m_min = m + 2;
- }
- }
- return tb->tpc2gpc[m_max + 1];
- }
- return 0;
-}
-#endif // CONFIG_ANDROID_MEMCHECK
-
void tb_free(TranslationBlock *tb);
void tb_flush(CPUArchState *env);
void tb_link_phys(TranslationBlock *tb,
target_ulong phys_pc, target_ulong phys_page2);
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
void tb_invalidate_phys_page_fast0(hwaddr start, int len);
-
+
extern uint8_t *code_gen_ptr;
extern int code_gen_max_blocks;
diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h
index 21d9701..5ddf5ae 100644
--- a/include/exec/softmmu_template.h
+++ b/include/exec/softmmu_template.h
@@ -112,20 +112,6 @@
#endif
-#if defined(CONFIG_ANDROID_MEMCHECK) && !defined(SOFTMMU_CODE_ACCESS)
-/*
- * Support for memory access checker.
- * We need to instrument __ldx/__stx_mmu routines implemented in this file with
- * callbacks to access validation routines implemented by the memory checker.
- * Note that (at least for now) we don't do that instrumentation for memory
- * addressing the code (SOFTMMU_CODE_ACCESS controls that). Also, we don't want
- * to instrument code that is used by emulator itself (OUTSIDE_JIT controls
- * that).
- */
-#define CONFIG_ANDROID_MEMCHECK_MMU
-#include "android/qemu/memcheck/memcheck_api.h"
-#endif // CONFIG_ANDROID_MEMCHECK && !SOFTMMU_CODE_ACCESS
-
static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
hwaddr physaddr,
target_ulong addr,
@@ -168,9 +154,6 @@
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- int invalidate_cache = 0;
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
/* If the TLB entry is for a different page, reload and try again. */
if ((addr & TARGET_PAGE_MASK)
@@ -203,16 +186,6 @@
if (DATA_SIZE > 1
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
>= TARGET_PAGE_SIZE)) {
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- /* We only validate access to the guest's user space, for which
- * mmu_idx is set to 1. */
- if (memcheck_instrument_mmu && mmu_idx == 1 &&
- memcheck_validate_ld(addr, DATA_SIZE, (target_ulong)(retaddr - GETPC_ADJ))) {
- /* Memory read breaks page boundary. So, if required, we
- * must invalidate two caches in TLB. */
- invalidate_cache = 2;
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
target_ulong addr1, addr2;
DATA_TYPE res1, res2;
unsigned shift;
@@ -232,14 +205,6 @@
res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
return res;
}
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (DATA_SIZE == 1) {
- if (memcheck_instrument_mmu && mmu_idx == 1) {
- invalidate_cache = memcheck_validate_ld(addr, DATA_SIZE,
- (target_ulong)(retaddr + GETPC_ADJ));
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
/* Handle aligned access or unaligned access in the same page. */
#ifdef ALIGNED_ONLY
@@ -254,20 +219,6 @@
#else
res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (invalidate_cache) {
- /* Accessed memory is under memchecker control. We must invalidate
- * containing page(s) in order to make sure that next access to them
- * will invoke _ld/_st_mmu. */
- env->tlb_table[mmu_idx][index].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index].addr_write ^= TARGET_PAGE_MASK;
- if ((invalidate_cache == 2) && (index < CPU_TLB_SIZE)) {
- // Read crossed page boundaris. Invalidate second cache too.
- env->tlb_table[mmu_idx][index + 1].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index + 1].addr_write ^= TARGET_PAGE_MASK;
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
return res;
}
@@ -285,9 +236,6 @@
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- int invalidate_cache = 0;
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
/* If the TLB entry is for a different page, reload and try again. */
if ((addr & TARGET_PAGE_MASK)
@@ -320,16 +268,6 @@
if (DATA_SIZE > 1
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
>= TARGET_PAGE_SIZE)) {
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- /* We only validate access to the guest's user space, for which
- * mmu_idx is set to 1. */
- if (memcheck_instrument_mmu && mmu_idx == 1 &&
- memcheck_validate_ld(addr, DATA_SIZE, (target_ulong)(retaddr - GETPC_ADJ))) {
- /* Memory read breaks page boundary. So, if required, we
- * must invalidate two caches in TLB. */
- invalidate_cache = 2;
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
target_ulong addr1, addr2;
DATA_TYPE res1, res2;
unsigned shift;
@@ -349,14 +287,6 @@
res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
return res;
}
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (DATA_SIZE == 1) {
- if (memcheck_instrument_mmu && mmu_idx == 1) {
- invalidate_cache = memcheck_validate_ld(addr, DATA_SIZE,
- (target_ulong)(retaddr + GETPC_ADJ));
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
/* Handle aligned access or unaligned access in the same page. */
#ifdef ALIGNED_ONLY
@@ -367,20 +297,6 @@
haddr = addr + env->tlb_table[mmu_idx][index].addend;
res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (invalidate_cache) {
- /* Accessed memory is under memchecker control. We must invalidate
- * containing page(s) in order to make sure that next access to them
- * will invoke _ld/_st_mmu. */
- env->tlb_table[mmu_idx][index].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index].addr_write ^= TARGET_PAGE_MASK;
- if ((invalidate_cache == 2) && (index < CPU_TLB_SIZE)) {
- // Read crossed page boundaris. Invalidate second cache too.
- env->tlb_table[mmu_idx][index + 1].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index + 1].addr_write ^= TARGET_PAGE_MASK;
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
return res;
}
#endif /* DATA_SIZE > 1 */
@@ -447,10 +363,6 @@
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
uintptr_t haddr;
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- int invalidate_cache = 0;
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
-
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@@ -485,17 +397,6 @@
if (DATA_SIZE > 1
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
>= TARGET_PAGE_SIZE)) {
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- /* We only validate access to the guest's user space, for which
- * mmu_idx is set to 1. */
- if (memcheck_instrument_mmu && mmu_idx == 1 &&
- memcheck_validate_st(addr, DATA_SIZE, (uint64_t)val,
- (target_ulong)(retaddr + GETPC_ADJ))) {
- /* Memory write breaks page boundary. So, if required, we
- * must invalidate two caches in TLB. */
- invalidate_cache = 2;
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
int i;
do_unaligned_access:
#ifdef ALIGNED_ONLY
@@ -514,17 +415,6 @@
}
return;
}
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (DATA_SIZE == 1) {
- /* We only validate access to the guest's user space, for which
- * mmu_idx is set to 1. */
- if (memcheck_instrument_mmu && mmu_idx == 1) {
- invalidate_cache = memcheck_validate_st(addr, DATA_SIZE,
- (uint64_t)val,
- (target_ulong)(retaddr + GETPC_ADJ));
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
/* Handle aligned access or unaligned access in the same page. */
#ifdef ALIGNED_ONLY
@@ -539,20 +429,6 @@
#else
glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (invalidate_cache) {
- /* Accessed memory is under memchecker control. We must invalidate
- * containing page(s) in order to make sure that next access to them
- * will invoke _ld/_st_mmu. */
- env->tlb_table[mmu_idx][index].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index].addr_write ^= TARGET_PAGE_MASK;
- if ((invalidate_cache == 2) && (index < CPU_TLB_SIZE)) {
- // Write crossed page boundaris. Invalidate second cache too.
- env->tlb_table[mmu_idx][index + 1].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index + 1].addr_write ^= TARGET_PAGE_MASK;
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
}
#if DATA_SIZE > 1
@@ -563,10 +439,6 @@
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
uintptr_t haddr;
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- int invalidate_cache = 0;
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
-
/* Adjust the given return address. */
retaddr -= GETPC_ADJ;
@@ -601,17 +473,6 @@
if (DATA_SIZE > 1
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
>= TARGET_PAGE_SIZE)) {
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- /* We only validate access to the guest's user space, for which
- * mmu_idx is set to 1. */
- if (memcheck_instrument_mmu && mmu_idx == 1 &&
- memcheck_validate_st(addr, DATA_SIZE, (uint64_t)val,
- (target_ulong)(retaddr + GETPC_ADJ))) {
- /* Memory write breaks page boundary. So, if required, we
- * must invalidate two caches in TLB. */
- invalidate_cache = 2;
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
int i;
do_unaligned_access:
#ifdef ALIGNED_ONLY
@@ -630,17 +491,6 @@
}
return;
}
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (DATA_SIZE == 1) {
- /* We only validate access to the guest's user space, for which
- * mmu_idx is set to 1. */
- if (memcheck_instrument_mmu && mmu_idx == 1) {
- invalidate_cache = memcheck_validate_st(addr, DATA_SIZE,
- (uint64_t)val,
- (target_ulong)(retaddr + GETPC_ADJ));
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
/* Handle aligned access or unaligned access in the same page. */
#ifdef ALIGNED_ONLY
@@ -651,20 +501,6 @@
haddr = addr + env->tlb_table[mmu_idx][index].addend;
glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
-#ifdef CONFIG_ANDROID_MEMCHECK_MMU
- if (invalidate_cache) {
- /* Accessed memory is under memchecker control. We must invalidate
- * containing page(s) in order to make sure that next access to them
- * will invoke _ld/_st_mmu. */
- env->tlb_table[mmu_idx][index].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index].addr_write ^= TARGET_PAGE_MASK;
- if ((invalidate_cache == 2) && (index < CPU_TLB_SIZE)) {
- // Write crossed page boundaris. Invalidate second cache too.
- env->tlb_table[mmu_idx][index + 1].addr_read ^= TARGET_PAGE_MASK;
- env->tlb_table[mmu_idx][index + 1].addr_write ^= TARGET_PAGE_MASK;
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK_MMU
}
#endif /* DATA_SIZE > 1 */
diff --git a/target-arm/helper-android.c b/target-arm/helper-android.c
deleted file mode 100644
index ec82f13..0000000
--- a/target-arm/helper-android.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "exec/gdbstub.h"
-#include "exec/def-helper.h"
-#include "helper-android.h"
-#include "qemu-common.h"
-
-/* copy a string from the simulated virtual space to a buffer in QEMU */
-void vstrcpy(target_ulong ptr, char *buf, int max)
-{
- int index;
-
- if (buf == NULL) return;
-
- for (index = 0; index < max; index += 1) {
- cpu_physical_memory_read(ptr + index, (uint8_t*)buf + index, 1);
- if (buf[index] == 0)
- break;
- }
-}
-
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck_api.h"
-
-void HELPER(on_call)(target_ulong pc, target_ulong ret) {
- memcheck_on_call(pc, ret);
-}
-
-void HELPER(on_ret)(target_ulong ret) {
- memcheck_on_ret(ret);
-}
-#endif // CONFIG_ANDROID_MEMCHECK
diff --git a/target-arm/helper-android.h b/target-arm/helper-android.h
deleted file mode 100644
index f4d4500..0000000
--- a/target-arm/helper-android.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* This file must be included from helper.h */
-#ifdef CONFIG_ANDROID_MEMCHECK
-/* Hooks to translated BL/BLX. This callback is used to build thread's
- * calling stack.
- * Param:
- * First pointer contains guest PC where BL/BLX has been found.
- * Second pointer contains guest PC where BL/BLX will return.
- */
-DEF_HELPER_2(on_call, void, i32, i32)
-/* Hooks to return from translated BL/BLX. This callback is used to build
- * thread's calling stack.
- * Param:
- * Pointer contains guest PC where BL/BLX will return.
- */
-DEF_HELPER_1(on_ret, void, i32)
-#endif // CONFIG_ANDROID_MEMCHECK
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 5b5566e..f9834ac 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -470,5 +470,4 @@
DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
DEF_HELPER_2(neon_vldst_all, void, env, i32)
-#include "helper-android.h"
#include "exec/def-helper.h"
diff --git a/target-arm/translate-android.h b/target-arm/translate-android.h
deleted file mode 100644
index d5f4749..0000000
--- a/target-arm/translate-android.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/* This file must be included from target-arm/translate.c */
-
-/*****
- *****
- *****
- ***** C O N F I G _ M E M C H E C K
- *****
- *****
- *****/
-
-#ifdef CONFIG_ANDROID_MEMCHECK
-
-/*
- * Memchecker addition in this module is intended to inject qemu callback into
- * translated code for each BL/BLX, as well as BL/BLX returns. These callbacks
- * are used to build calling stack of the thread in order to provide better
- * reporting on memory access violations. Although this may seem as something
- * that may gratly impact the performance, in reality it doesn't. Overhead that
- * is added by setting up callbacks and by callbacks themselves is neglectable.
- * On the other hand, maintaining calling stack can indeed add some perf.
- * overhead (TODO: provide solid numbers here).
- * One of the things to watch out with regards to injecting callbacks, is
- * consistency between intermediate code generated for execution, and for guest
- * PC address calculation. If code doesn't match, a segmentation fault is
- * guaranteed.
- */
-
-#include "android/qemu/memcheck/memcheck_proc_management.h"
-#include "android/qemu/memcheck/memcheck_api.h"
-
-/* Array of return addresses detected in gen_intermediate_code_internal. */
-AddrArray ret_addresses = { 0 };
-
-/* Checks if call stack collection is enabled for the given context.
- * We collect call stack only for the user mode (both, code and CPU), and on
- * condition that memory checking, and call collection are enabled. It also
- * seems that collecting stack for the linker code is excessive, as it doesn't
- * provide much useful info for the memory checker.
- * Return:
- * boolean: 1 if stack collection is enabled for the given context, or 0 if
- * it's not enabled.
- */
-static inline int
-watch_call_stack(DisasContext *s)
-{
- if (!memcheck_enabled || !memcheck_watch_call_stack) {
- return 0;
- }
-
-#ifndef CONFIG_USER_ONLY
- if (!s->user) {
- /* We're not interested in kernel mode CPU stack. */
- return 0;
- }
-#endif // CONFIG_USER_ONLY
-
- /* We're not interested in kernel code stack (pc >= 0xC0000000).
- * Android specific: We're also not interested in android linker stack
- * (0xB0000000 - 0xB00FFFFF) */
- if (s->pc >= 0xC0000000 || (0xB0000000 <= s->pc && s->pc <= 0xB00FFFFF)) {
- return 0;
- }
- return 1;
-}
-
-/* Checks if given ARM instruction is BL, or BLX.
- * Return:
- * boolean: 1 if ARM instruction is BL/BLX, or 0 if it's not.
- */
-static inline int
-is_arm_bl_or_blx(uint32_t insn)
-{
- /* ARM BL (immediate): xxxx 1011 xxxx xxxx xxxx xxxx xxxx xxxx
- * ARM BLX (immediate): 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx
- * ARM BLX (register): xxxx 0001 0010 xxxx xxxx xxxx 0011 xxxx
- */
- if ((insn & 0x0F000000) == 0x0B000000 || // ARM BL (imm)
- (insn & 0xFE000000) == 0xFA000000 || // ARM BLX (imm)
- (insn & 0x0FF000F0) == 0x12000030) { // ARM BLX (reg)
- return 1;
- }
- return 0;
-}
-
-/* Checks if given THUMB instruction is BL, or BLX.
- * Param:
- * insn - THUMB instruction to check.
- * pc - Emulated PC address for the instruction.
- * ret_off - If insn is BL, or BLX, upon return ret_off contains
- * instruction's byte size. If instruction is not BL, or BLX, content of
- * this parameter is undefined on return.
- * Return:
- * boolean: 1 if THUMB instruction is BL/BLX, or 0 if it's not.
- */
-static inline int
-is_thumb_bl_or_blx(CPUARMState* env, uint16_t insn, target_ulong pc, target_ulong* ret_off)
-{
- /* THUMB BLX(register): 0100 0111 1xxx xxxx
- * THUMB BL(1-stimmediate): 1111 0xxx xxxx xxxx
- * THUMB BLX(1-stimmediate): 1111 0xxx xxxx xxxx
- */
- if ((insn & 0xFF80) == 0x4780) { // THUMB BLX(reg)
- *ret_off = 2;
- return 1;
- } else if ((insn & 0xF800) == 0xF000) { // THUMB BL(X)(imm)
- // This is a 32-bit THUMB. Get the second half of the instuction.
- insn = cpu_lduw_code(env, pc + 2);
- if ((insn & 0xC000) == 0xC000) {
- *ret_off = 4;
- return 1;
- }
- }
- return 0;
-}
-
-/* Registers a return address detected in gen_intermediate_code_internal.
- * NOTE: If return address has been registered as new in this routine, this will
- * cause invalidation of all existing TBs that contain translated code for that
- * address.
- * NOTE: Before storing PC address in the array, we convert it from emulated
- * address to a physical address. This way we deal with emulated addresses
- * overlapping for different processes.
- * Param:
- * env - CPU state environment.
- * addr - Return address to register.
- * Return:
- * 1 - Address has been registered in this routine.
- * -1 - Address has been already registered before.
- * 0 - Insufficient memory.
- */
-static int
-register_ret_address(CPUARMState* env, target_ulong addr)
-{
- int ret;
- if ((0x90000000 <= addr && addr <= 0xBFFFFFFF)) {
- /* Address belongs to a module that always loads at this fixed address.
- * So, we can keep this address in the global array. */
- ret = addrarray_add(&ret_addresses, get_page_addr_code(env, addr));
- } else {
- ret = addrarray_add(&ret_addresses, get_page_addr_code(env, addr));
- }
- assert(ret != 0);
-
- if (ret == 1) {
- /* If this ret address has been added to the array, we need to make sure
- * that all TBs that contain translated code for that address are
- * invalidated. This will force retranslation of that code, which will
- * make sure that our ret callback is set. This is also important part
- * in keeping consistency between translated code, and intermediate code
- * generated for guest PC calculation. If we don't invalidate TBs, and
- * PC calculation code is generated, there will be inconsistency due to
- * the fact that TB code doesn't contain ret callback, while PC calc
- * code contains it. This inconsistency will lead to an immanent
- * segmentation fault.*/
- TranslationBlock* tb;
- const target_ulong phys_pc = get_page_addr_code(env, addr);
- const target_ulong phys_page1 = phys_pc & TARGET_PAGE_MASK;
-
- for(tb = tcg_ctx.tb_ctx.tb_phys_hash[tb_phys_hash_func(phys_pc)]; tb != NULL;
- tb = tb->phys_hash_next) {
- if (tb->pc == addr && tb->page_addr[0] == phys_page1) {
- tb_phys_invalidate(tb, -1);
- }
- }
- }
- return ret;
-}
-
-/* Checks if given address is recognized as a return address.
- * Return:
- * boolean: 1 if if given address is recognized as a return address,
- * or 0 if it's not.
- */
-static inline int
-is_ret_address(CPUARMState* env, target_ulong addr)
-{
- if ((0x90000000 <= addr && addr <= 0xBFFFFFFF)) {
- return addrarray_check(&ret_addresses, get_page_addr_code(env, addr));
- } else {
- return addrarray_check(&ret_addresses, get_page_addr_code(env, addr));
- }
-}
-
-/* Adds "on_call" callback into generated intermediate code. */
-static inline void
-set_on_call(target_ulong pc, target_ulong ret)
-{
- TCGv_ptr tmp_pc = tcg_const_ptr(pc & ~1);
- TCGv_ptr tmp_ret = tcg_const_ptr(ret & ~1);
-
- gen_helper_on_call(tmp_pc, tmp_ret);
-
- tcg_temp_free_ptr(tmp_ret);
- tcg_temp_free_ptr(tmp_pc);
-}
-
-/* Adds "on_ret" callback into generated intermediate code. */
-static inline void
-set_on_ret(target_ulong ret)
-{
- TCGv_ptr tmp_ret = tcg_const_ptr(ret & ~1);
-
- gen_helper_on_ret(tmp_ret);
-
- tcg_temp_free_ptr(tmp_ret);
-}
-
-
-# define ANDROID_WATCH_CALLSTACK_ARM(s) \
- if (watch_call_stack(s)) { \
- if (is_ret_address(env, s->pc)) { \
- set_on_ret(s->pc); \
- } \
- if (is_arm_bl_or_blx(insn)) { \
- set_on_call(s->pc, s->pc + 4); \
- if (!s->search_pc) { \
- register_ret_address(env, s->pc + 4); \
- } \
- } \
- }
-
-# define ANDROID_WATCH_CALLSTACK_THUMB(s) \
- if (watch_call_stack(s)) { \
- target_ulong ret_off; \
- if (is_ret_address(env, s->pc)) { \
- set_on_ret(s->pc); \
- } \
- if (is_thumb_bl_or_blx(env, insn, s->pc, &ret_off)) { \
- set_on_call(s->pc, s->pc + ret_off); \
- if (!s->search_pc) { \
- register_ret_address(env, s->pc + ret_off); \
- } \
- } \
- }
-
-# define ANDROID_DISAS_CONTEXT_FIELDS \
- int search_pc;
-
-# define ANDROID_START_CODEGEN(search_pc) \
- dc->search_pc = search_pc
-
- /* When memchecker is enabled, we need to keep a match between
- * translated PC and guest PCs, so memchecker can quickly covert
- * one to another. Note that we do that only for user mode. */
-# define ANDROID_CHECK_CODEGEN_PC(search_pc) \
- ((search_pc) || (memcheck_enabled && dc->user))
-
-# define ANDROID_END_CODEGEN() \
- do { \
- if (memcheck_enabled && dc->user) { \
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; \
- lj++; \
- while (lj <= j) \
- tcg_ctx.gen_opc_instr_start[lj++] = 0; \
- } \
- } while (0)
-
-#else /* !CONFIG_ANDROID_MEMCHECK */
-
-# define ANDROID_WATCH_CALLSTACK_ARM ((void)0)
-# define ANDROID_WATCH_CALLSTACK_THUMB ((void)0)
-# define ANDROID_DISAS_CONTEXT_FIELDS /* nothing */
-# define ANDROID_START_CODEGEN(s) ((void)(s))
-# define ANDROID_CHECK_CODEGEN_PC(s) (s)
-# define ANDROID_END_CODEGEN() ((void)0)
-
-#endif /* !CONFIG_ANDROID_MEMCHECK */
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 20e2e89..7bc50c1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -66,12 +66,8 @@
int vfp_enabled;
int vec_len;
int vec_stride;
-#ifdef CONFIG_ANDROID_MEMCHECK
- int search_pc;
-#endif
} DisasContext;
-#include "translate-android.h"
static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
#if defined(CONFIG_USER_ONLY)
@@ -6585,8 +6581,6 @@
insn = cpu_ldl_code(env, s->pc);
- ANDROID_WATCH_CALLSTACK_ARM(s);
-
s->pc += 4;
/* M variants do not implement ARM mode. */
@@ -9022,8 +9016,6 @@
insn = cpu_lduw_code(env, s->pc);
- ANDROID_WATCH_CALLSTACK_THUMB(s);
-
s->pc += 2;
switch (insn >> 12) {
@@ -9722,7 +9714,6 @@
#if !defined(CONFIG_USER_ONLY)
dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
#endif
- ANDROID_START_CODEGEN(search_pc);
dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
@@ -9817,19 +9808,6 @@
}
}
- if (ANDROID_CHECK_CODEGEN_PC(search_pc)) {
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
-
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
@@ -9969,7 +9947,6 @@
while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
- ANDROID_END_CODEGEN();
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
}
diff --git a/translate-all.c b/translate-all.c
index 80581bf..e4a5e2b 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -102,22 +102,6 @@
/* code generation context */
TCGContext tcg_ctx;
-#ifdef CONFIG_ANDROID_MEMCHECK
-/*
- * Memchecker code in this module copies TB PC <-> Guest PC map to the TB
- * descriptor after guest code has been translated in cpu_gen_init routine.
- */
-#include "android/qemu/memcheck/memcheck_api.h"
-
-/* Array of (tb_pc, guest_pc) pairs, big enough for all translations. This
- * array is used to obtain guest PC address from a translated PC address.
- * tcg_gen_code_common will fill it up when memchecker is enabled. */
-static void* gen_opc_tpc2gpc[OPC_BUF_SIZE * 2];
-void** gen_opc_tpc2gpc_ptr = &gen_opc_tpc2gpc[0];
-/* Number of (tb_pc, guest_pc) pairs stored in gen_opc_tpc2gpc array. */
-unsigned int gen_opc_tpc2gpc_pairs;
-#endif // CONFIG_ANDROID_MEMCHECK
-
/* XXX: suppress that */
unsigned long code_gen_max_block_size(void)
{
@@ -198,20 +182,6 @@
s->code_out_len += gen_code_size;
#endif
-#ifdef CONFIG_ANDROID_MEMCHECK
- /* Save translated PC -> guest PC map into TB. */
- if (memcheck_enabled && gen_opc_tpc2gpc_pairs && is_cpu_user(env)) {
- tb->tpc2gpc =
- g_malloc(gen_opc_tpc2gpc_pairs * 2 * sizeof(uintptr_t));
- if (tb->tpc2gpc != NULL) {
- memcpy(tb->tpc2gpc, gen_opc_tpc2gpc_ptr,
- gen_opc_tpc2gpc_pairs * 2 * sizeof(uintptr_t));
- tb->tpc2gpc_pairs = gen_opc_tpc2gpc_pairs;
- }
-
- }
-#endif // CONFIG_ANDROID_MEMCHECK
-
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
@@ -695,10 +665,6 @@
tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
tb->pc = pc;
tb->cflags = 0;
-#ifdef CONFIG_ANDROID_MEMCHECK
- tb->tpc2gpc = NULL;
- tb->tpc2gpc_pairs = 0;
-#endif // CONFIG_ANDROID_MEMCHECK
return tb;
}
@@ -776,17 +742,6 @@
CPU_FOREACH(cpu) {
CPUArchState *env = cpu->env_ptr;
-#ifdef CONFIG_ANDROID_MEMCHECK
- int tb_to_clean;
- for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
- if (env->tb_jmp_cache[tb_to_clean] != NULL &&
- env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
- g_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
- env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
- env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
- }
- }
-#endif // CONFIG_ANDROID_MEMCHECK
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
}
@@ -964,14 +919,6 @@
}
tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (tb->tpc2gpc != NULL) {
- g_free(tb->tpc2gpc);
- tb->tpc2gpc = NULL;
- tb->tpc2gpc_pairs = 0;
- }
-#endif // CONFIG_ANDROID_MEMCHECK
-
tcg_ctx.tb_ctx.tb_phys_invalidate_count++;
}
diff --git a/vl-android.c b/vl-android.c
index 7023b44..88108a6 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -79,10 +79,6 @@
#include "exec/hwaddr.h"
#include "android/tcpdump.h"
-#ifdef CONFIG_ANDROID_MEMCHECK
-#include "android/qemu/memcheck/memcheck.h"
-#endif // CONFIG_ANDROID_MEMCHECK
-
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
@@ -3000,15 +2996,6 @@
}
break;
-#ifdef CONFIG_ANDROID_MEMCHECK
- case QEMU_OPTION_android_memcheck:
- android_op_memcheck = (char*)optarg;
- /* This will set ro.kernel.memcheck system property
- * to memcheck's tracing flags. */
- stralloc_add_format(kernel_config, " memcheck=%s", android_op_memcheck);
- break;
-#endif // CONFIG_ANDROID_MEMCHECK
-
case QEMU_OPTION_snapshot_no_time_update:
android_snapshot_update_time = 0;
break;
@@ -3397,12 +3384,6 @@
stralloc_add_format(kernel_config, " ndns=%d", dns_count);
}
-#ifdef CONFIG_ANDROID_MEMCHECK
- if (android_op_memcheck) {
- memcheck_init(android_op_memcheck);
- }
-#endif // CONFIG_ANDROID_MEMCHECK
-
/* qemu.gles will be read by the OpenGL ES emulation libraries.
* If set to 0, the software GL ES renderer will be used as a fallback.
* If the parameter is undefined, this means the system image runs