diff options
author | Christopher Ferris <cferris@google.com> | 2015-08-01 00:11:30 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2015-08-01 00:11:30 +0000 |
commit | 9b5e3253ff1732f76e4f1a53b4c591b2d0a6af69 (patch) | |
tree | 3c37c13afa49f7aa8d60c60d8f3e7eeea94340b7 | |
parent | 6645bc56799790c3f5f07f7e63d755a9759b0084 (diff) | |
parent | f48582b1ddfe2db038042e6ec82d87dd391d5be5 (diff) | |
download | swt-9b5e3253ff1732f76e4f1a53b4c591b2d0a6af69.tar.gz |
Merge "Add load base to relative pcs computed." into studio-1.4-dev
automerge: f48582b
* commit 'f48582b1ddfe2db038042e6ec82d87dd391d5be5':
Add load base to relative pcs computed.
-rw-r--r-- | ddms/ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeSymbolResolverTask.java | 124 |
1 files changed, 123 insertions, 1 deletions
diff --git a/ddms/ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeSymbolResolverTask.java b/ddms/ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeSymbolResolverTask.java index b74a3d0..5936bbd 100644 --- a/ddms/ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeSymbolResolverTask.java +++ b/ddms/ddmuilib/src/main/java/com/android/ddmuilib/heap/NativeSymbolResolverTask.java @@ -29,8 +29,10 @@ import org.eclipse.jface.operation.IRunnableWithProgress; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; +import java.io.RandomAccessFile; import java.io.OutputStreamWriter; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -55,6 +57,11 @@ public class NativeSymbolResolverTask implements IRunnableWithProgress { private static final String ADDR2LINE64; private static final String DEFAULT_SYMBOLS_FOLDER; + private static final int ELF_CLASS32 = 1; + private static final int ELF_CLASS64 = 2; + private static final int ELF_DATA2LSB = 1; + private static final int ELF_PT_LOAD = 1; + static { String addr2lineEnv = System.getenv("ANDROID_ADDR2LINE"); String addr2line64Env = System.getenv("ANDROID_ADDR2LINE64"); @@ -174,6 +181,120 @@ public class NativeSymbolResolverTask implements IRunnableWithProgress { } } + private long unsigned(byte value, long shift) { + return ((long) value & 0xFF) << shift; + } + + private short elfGetHalfWord(RandomAccessFile file, long offset) throws IOException { + byte[] buf = new byte[2]; + file.seek(offset); + file.readFully(buf, 0, 2); + return (short) (unsigned(buf[0], 0) | unsigned(buf[1], 8)); + } + + private int elfGetWord(RandomAccessFile file, long offset) throws IOException { + byte[] buf = new byte[4]; + file.seek(offset); + file.readFully(buf, 0, 4); + return (int) (unsigned(buf[0], 0) | unsigned(buf[1], 8) | + unsigned(buf[2], 16) | unsigned(buf[3], 24)); + } + + private long elfGetDoubleWord(RandomAccessFile file, long offset) throws IOException { + byte[] buf = new byte[8]; + file.seek(offset); + file.readFully(buf, 0, 8); + return unsigned(buf[0], 0) | unsigned(buf[1], 8) | + unsigned(buf[2], 16) | unsigned(buf[3], 24) | + unsigned(buf[4], 32) | unsigned(buf[5], 40) | + unsigned(buf[6], 48) | unsigned(buf[7], 56); + } + + private long getLoadBase(String libPath) { + RandomAccessFile file; + try { + file = new RandomAccessFile(libPath, "r"); + } catch (FileNotFoundException e) { + return 0; + } + byte[] buffer = new byte[8]; + try { + file.readFully(buffer, 0, 6); + } catch (IOException e) { + return 0; + } + if (buffer[0] != 0x7f || buffer[1] != 'E' || buffer[2] != 'L' || + buffer[3] != 'F' || buffer[5] != ELF_DATA2LSB) { + return 0; + } + + boolean elf32; + long elfPhdrSize; + long ePhnumOffset; + long ePhoffOffset; + long pTypeOffset; + long pOffsetOffset; + long pVaddrOffset; + if (buffer[4] == ELF_CLASS32) { + // ELFCLASS32 + elf32 = true; + elfPhdrSize = 32; + + ePhnumOffset = 44; + ePhoffOffset = 28; + pTypeOffset = 0; + pOffsetOffset = 4; + pVaddrOffset = 8; + } else if (buffer[4] == ELF_CLASS64) { + // ELFCLASS64 + elf32 = false; + elfPhdrSize = 56; + + ePhnumOffset = 56; + ePhoffOffset = 32; + pTypeOffset = 0; + pOffsetOffset = 8; + pVaddrOffset = 16; + } else { + // Unknown class type. + return 0; + } + + try { + int ePhnum = elfGetHalfWord(file, ePhnumOffset); + long offset; + if (elf32) { + offset = elfGetWord(file, ePhoffOffset); + } else { + offset = elfGetDoubleWord(file, ePhoffOffset); + } + for (int i = 0; i < ePhnum; i++) { + int pType = elfGetWord(file, offset + pTypeOffset); + + long pOffset; + if (elf32) { + pOffset = elfGetWord(file, offset + pOffsetOffset); + } else { + pOffset = elfGetDoubleWord(file, offset + pOffsetOffset); + } + // Assume all offsets are zero. + if (pType == ELF_PT_LOAD && pOffset == 0) { + long pVaddr; + if (elf32) { + pVaddr = elfGetWord(file, offset + pVaddrOffset); + } else { + pVaddr = elfGetDoubleWord(file, offset + pVaddrOffset); + } + return pVaddr; + } + offset += elfPhdrSize; + } + } catch (IOException e) { + return 0; + } + return 0; + } + private void resolveAddresses(NativeLibraryMapInfo lib, String libPath, Set<Long> addressesToResolve) { Process addr2line; @@ -196,9 +317,10 @@ public class NativeSymbolResolverTask implements IRunnableWithProgress { addr2line.getOutputStream())); long libStartAddress = isExecutable(lib) ? 0 : lib.getStartAddress(); + long libLoadBase = isExecutable(lib) ? 0 : getLoadBase(libPath); try { for (Long addr : addressesToResolve) { - long offset = addr - libStartAddress; + long offset = addr - libStartAddress + libLoadBase; addressWriter.write(Long.toHexString(offset)); addressWriter.newLine(); addressWriter.flush(); |