aboutsummaryrefslogtreecommitdiffstats
path: root/ddms/libs/ddmuilib/src/com/android/ddmuilib/Addr2Line.java
diff options
context:
space:
mode:
Diffstat (limited to 'ddms/libs/ddmuilib/src/com/android/ddmuilib/Addr2Line.java')
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/Addr2Line.java355
1 files changed, 0 insertions, 355 deletions
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/Addr2Line.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/Addr2Line.java
deleted file mode 100644
index 10799ec..0000000
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/Addr2Line.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ddmuilib;
-
-import com.android.ddmlib.Log;
-import com.android.ddmlib.NativeLibraryMapInfo;
-import com.android.ddmlib.NativeStackCallInfo;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Represents an addr2line process to get filename/method information from a
- * memory address.<br>
- * Each process can only handle one library, which should be provided when
- * creating a new process.<br>
- * <br>
- * The processes take some time to load as they need to parse the library files.
- * For this reason, processes cannot be manually started. Instead the class
- * keeps an internal list of processes and one asks for a process for a specific
- * library, using <code>getProcess(String library)<code>.<br></br>
- * Internally, the processes are started in pipe mode to be able to query them
- * with multiple addresses.
- */
-public class Addr2Line {
- private static final String ANDROID_SYMBOLS_ENVVAR = "ANDROID_SYMBOLS";
-
- private static final String LIBRARY_NOT_FOUND_MESSAGE_FORMAT =
- "Unable to locate library %s on disk. Addresses mapping to this library "
- + "will not be resolved. In order to fix this, set the the library search path "
- + "in the UI, or set the environment variable " + ANDROID_SYMBOLS_ENVVAR + ".";
-
- /**
- * Loaded processes list. This is also used as a locking object for any
- * methods dealing with starting/stopping/creating processes/querying for
- * method.
- */
- private static final HashMap<String, Addr2Line> sProcessCache =
- new HashMap<String, Addr2Line>();
-
- /**
- * byte array representing a carriage return. Used to push addresses in the
- * process pipes.
- */
- private static final byte[] sCrLf = {
- '\n'
- };
-
- /** Path to the library */
- private NativeLibraryMapInfo mLibrary;
-
- /** the command line process */
- private Process mProcess;
-
- /** buffer to read the result of the command line process from */
- private BufferedReader mResultReader;
-
- /**
- * output stream to provide new addresses to decode to the command line
- * process
- */
- private BufferedOutputStream mAddressWriter;
-
- private static final String DEFAULT_LIBRARY_SYMBOLS_FOLDER;
- static {
- String symbols = System.getenv(ANDROID_SYMBOLS_ENVVAR);
- if (symbols == null) {
- DEFAULT_LIBRARY_SYMBOLS_FOLDER = DdmUiPreferences.getSymbolDirectory();
- } else {
- DEFAULT_LIBRARY_SYMBOLS_FOLDER = symbols;
- }
- }
-
- private static List<String> mLibrarySearchPaths = new ArrayList<String>();
-
- /**
- * Set the search path where libraries should be found.
- * @param path search path to use, can be a colon separated list of paths if multiple folders
- * should be searched
- */
- public static void setSearchPath(String path) {
- mLibrarySearchPaths.clear();
- mLibrarySearchPaths.addAll(Arrays.asList(path.split(":")));
- }
-
- /**
- * Returns the instance of a Addr2Line process for the specified library.
- * <br>The library should be in a format that makes<br>
- * <code>$ANDROID_PRODUCT_OUT + "/symbols" + library</code> a valid file.
- *
- * @param library the library in which to look for addresses.
- * @return a new Addr2Line object representing a started process, ready to
- * be queried for addresses. If any error happened when launching a
- * new process, <code>null</code> will be returned.
- */
- public static Addr2Line getProcess(final NativeLibraryMapInfo library) {
- String libName = library.getLibraryName();
-
- // synchronize around the hashmap object
- if (libName != null) {
- synchronized (sProcessCache) {
- // look for an existing process
- Addr2Line process = sProcessCache.get(libName);
-
- // if we don't find one, we create it
- if (process == null) {
- process = new Addr2Line(library);
-
- // then we start it
- boolean status = process.start();
-
- if (status) {
- // if starting the process worked, then we add it to the
- // list.
- sProcessCache.put(libName, process);
- } else {
- // otherwise we just drop the object, to return null
- process = null;
- }
- }
- // return the process
- return process;
- }
- }
- return null;
- }
-
- /**
- * Construct the object with a library name. The library should be present
- * in the search path as provided by ANDROID_SYMBOLS, ANDROID_OUT/symbols, or in the user
- * provided search path.
- *
- * @param library the library in which to look for address.
- */
- private Addr2Line(final NativeLibraryMapInfo library) {
- mLibrary = library;
- }
-
- /**
- * Search for the library in the library search path and obtain the full path to where it
- * is found.
- * @return fully resolved path to the library if found in search path, null otherwise
- */
- private String getLibraryPath(String library) {
- // first check the symbols folder
- String path = DEFAULT_LIBRARY_SYMBOLS_FOLDER + library;
- if (new File(path).exists()) {
- return path;
- }
-
- for (String p : mLibrarySearchPaths) {
- // try appending the full path on device
- String fullPath = p + "/" + library;
- if (new File(fullPath).exists()) {
- return fullPath;
- }
-
- // try appending basename(library)
- fullPath = p + "/" + new File(library).getName();
- if (new File(fullPath).exists()) {
- return fullPath;
- }
- }
-
- return null;
- }
-
- /**
- * Starts the command line process.
- *
- * @return true if the process was started, false if it failed to start, or
- * if there was any other errors.
- */
- private boolean start() {
- // because this is only called from getProcess() we know we don't need
- // to synchronize this code.
-
- String addr2Line = System.getenv("ANDROID_ADDR2LINE");
- if (addr2Line == null) {
- addr2Line = DdmUiPreferences.getAddr2Line();
- }
-
- // build the command line
- String[] command = new String[5];
- command[0] = addr2Line;
- command[1] = "-C";
- command[2] = "-f";
- command[3] = "-e";
-
- String fullPath = getLibraryPath(mLibrary.getLibraryName());
- if (fullPath == null) {
- String msg = String.format(LIBRARY_NOT_FOUND_MESSAGE_FORMAT, mLibrary.getLibraryName());
- Log.e("ddm-Addr2Line", msg);
- return false;
- }
-
- command[4] = fullPath;
-
- try {
- // attempt to start the process
- mProcess = Runtime.getRuntime().exec(command);
-
- if (mProcess != null) {
- // get the result reader
- InputStreamReader is = new InputStreamReader(mProcess
- .getInputStream());
- mResultReader = new BufferedReader(is);
-
- // get the outstream to write the addresses
- mAddressWriter = new BufferedOutputStream(mProcess
- .getOutputStream());
-
- // check our streams are here
- if (mResultReader == null || mAddressWriter == null) {
- // not here? stop the process and return false;
- mProcess.destroy();
- mProcess = null;
- return false;
- }
-
- // return a success
- return true;
- }
-
- } catch (IOException e) {
- // log the error
- String msg = String.format(
- "Error while trying to start %1$s process for library %2$s",
- DdmUiPreferences.getAddr2Line(), mLibrary);
- Log.e("ddm-Addr2Line", msg);
-
- // drop the process just in case
- if (mProcess != null) {
- mProcess.destroy();
- mProcess = null;
- }
- }
-
- // we can be here either cause the allocation of mProcess failed, or we
- // caught an exception
- return false;
- }
-
- /**
- * Stops the command line process.
- */
- public void stop() {
- synchronized (sProcessCache) {
- if (mProcess != null) {
- // remove the process from the list
- sProcessCache.remove(mLibrary);
-
- // then stops the process
- mProcess.destroy();
-
- // set the reference to null.
- // this allows to make sure another thread calling getAddress()
- // will not query a stopped thread
- mProcess = null;
- }
- }
- }
-
- /**
- * Stops all current running processes.
- */
- public static void stopAll() {
- // because of concurrent access (and our use of HashMap.values()), we
- // can't rely on the synchronized inside stop(). We need to put one
- // around the whole loop.
- synchronized (sProcessCache) {
- // just a basic loop on all the values in the hashmap and call to
- // stop();
- Collection<Addr2Line> col = sProcessCache.values();
- for (Addr2Line a2l : col) {
- a2l.stop();
- }
- }
- }
-
- /**
- * Looks up an address and returns method name, source file name, and line
- * number.
- *
- * @param addr the address to look up
- * @return a BacktraceInfo object containing the method/filename/linenumber
- * or null if the process we stopped before the query could be
- * processed, or if an IO exception happened.
- */
- public NativeStackCallInfo getAddress(long addr) {
- long offset = addr - mLibrary.getStartAddress();
-
- // even though we don't access the hashmap object, we need to
- // synchronized on it to prevent
- // another thread from stopping the process we're going to query.
- synchronized (sProcessCache) {
- // check the process is still alive/allocated
- if (mProcess != null) {
- // prepare to the write the address to the output buffer.
-
- // first, conversion to a string containing the hex value.
- String tmp = Long.toString(offset, 16);
-
- try {
- // write the address to the buffer
- mAddressWriter.write(tmp.getBytes());
-
- // add CR-LF
- mAddressWriter.write(sCrLf);
-
- // flush it all.
- mAddressWriter.flush();
-
- // read the result. We need to read 2 lines
- String method = mResultReader.readLine();
- String source = mResultReader.readLine();
-
- // make the backtrace object and return it
- if (method != null && source != null) {
- return new NativeStackCallInfo(addr, mLibrary.getLibraryName(), method, source);
- }
- } catch (IOException e) {
- // log the error
- Log.e("ddms",
- "Error while trying to get information for addr: "
- + tmp + " in library: " + mLibrary);
- // we'll return null later
- }
- }
- }
- return null;
- }
-}