blob: 9f6876439123ec7295bb658edce71673b92478d6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
public class Addr2line {
private String[] args;
private Process addr2line;
private BufferedReader stdout;
private BufferedWriter stdin;
private String lastaddr, lastsymbol, lastline;
private static final Pattern OUTPUT_PATTERN = Pattern.compile("(.*)( \\(discriminator.*\\))"); //$NON-NLS-1$
//private boolean isDisposed = false;
public Addr2line(String command, String[] params, String file) throws IOException {
init(command, params, file);
}
public Addr2line(String command, String file) throws IOException {
this(command, new String[0], file);
}
public Addr2line(String file) throws IOException {
this("addr2line", file); //$NON-NLS-1$
}
protected void init(String command, String[] params, String file) throws IOException {
if (params == null || params.length == 0) {
args = new String[] {command, "-C", "-f", "-e", file}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else {
args = new String[params.length + 1];
args[0] = command;
System.arraycopy(params, 0, args, 1, params.length);
}
addr2line = ProcessFactory.getFactory().exec(args);
stdin = new BufferedWriter(new OutputStreamWriter(addr2line.getOutputStream()));
stdout = new BufferedReader(new InputStreamReader(addr2line.getInputStream()));
}
protected void getOutput(String address) throws IOException {
if ( address.equals(lastaddr) == false ) {
stdin.write(address + "\n"); //$NON-NLS-1$
stdin.flush();
lastsymbol = stdout.readLine();
lastline = stdout.readLine();
lastaddr = address;
}
}
public String getLine(IAddress address) throws IOException {
getOutput(address.toString(16));
return lastline;
}
public String getFunction(IAddress address) throws IOException {
getOutput(address.toString(16));
return lastsymbol;
}
/**
* The format of the output:
* addr2line -C -f -e hello
* 08048442
* main
* hello.c:39
*/
public String getFileName(IAddress address) throws IOException {
String filename = null;
String line = getLine(address);
int index1, index2;
if (line != null && (index1 = line.lastIndexOf(':')) != -1) {
// we do this because addr2line on win produces
// <cygdrive/pathtoexc/C:/pathtofile:##>
index2 = line.indexOf(':');
if (index1 == index2) {
index2 = 0;
} else {
index2--;
}
filename = line.substring(index2, index1);
}
return filename;
}
/**
* The format of the output:
* addr2line -C -f -e hello
* 08048442
* main
* hello.c:39
*/
public int getLineNumber(IAddress address) throws IOException {
// We try to get the nearest match
// since the symbol may not exactly align with debug info.
// In C line number 0 is invalid, line starts at 1 for file, we use
// this for validation.
//IPF_TODO: check
for (int i = 0; i <= 20; i += 4, address = address.add(i)) {
String line = getLine(address);
line = parserOutput(line);
if (line != null) {
int colon = line.lastIndexOf(':');
String number = line.substring(colon + 1);
if (!number.startsWith("0")) { //$NON-NLS-1$
try {
return Integer.parseInt(number);
} catch(Exception ex) {
return -1;
}
}
}
}
return -1;
}
public void dispose() {
try {
stdout.close();
stdin.close();
addr2line.getErrorStream().close();
} catch (IOException e) {
}
addr2line.destroy();
//isDisposed = true;
}
private String parserOutput(String line) {
Matcher matcher = OUTPUT_PATTERN.matcher(line);
if (matcher.matches() && matcher.groupCount() > 1) {
line = matcher.group(1);
}
return line;
}
}