Show thread class name for Tizen Thread.
Show thread function name for other thread (e.g. pthread).
Change-Id: I6a1f8312f3cda5527e4c04dfb543453753f2f0f0
Signed-off-by: woojin <woojin2.jung@samsung.com>
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProviderFactory;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.tizen.dynamicanalyzer.nl.AnalyzerLabels;
+import org.tizen.dynamicanalyzer.nl.InformationViewLabels;
+import org.tizen.dynamicanalyzer.swap.channel.control.BinaryInfo;
+import org.tizen.dynamicanalyzer.swap.channel.data.ApiNameManager;
+import org.tizen.dynamicanalyzer.swap.channel.data.LibraryObject;
+import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfo;
+import org.tizen.dynamicanalyzer.swap.channel.data.ProcessInfoPackage;
+import org.tizen.dynamicanalyzer.swap.model.data.ProfileData;
+import org.tizen.dynamicanalyzer.swap.platform.BinarySettingManager;
import org.tizen.dynamicanalyzer.util.DALogger;
public class SymbolManager {
}
return demangled;
}
+
+
+ /**
+ * getFuncName : returns function name from pc address, pid, time
+ * and set build type and binary path for ProfileData
+ * @param input : can be null. If not null, set build type and binary path for ProfileData
+ * @param address : pc address
+ * @param pid : process id
+ * @param time : time stamp of the function call
+ * @return : function name
+ */
+ // TODO: remove unnecessary code
+ public static String getFuncName(ProfileData input, long address, int pid, long time) {
+ HashMap<Long, String> funcNameMap = AnalyzerManager
+ .getFuncNameMapByPid(pid);
+ String functionName = funcNameMap.get(address);
+ if (null != functionName) {
+ return functionName;
+ }
+
+ ProcessInfoPackage processInfoPkg = AnalyzerManager.getProject()
+ .getProcessInfoPackage(pid);
+ ProcessInfo processInfo = processInfoPkg
+ .getProcessInfo(time);
+
+ /** for debug */
+ BinaryInfo binInfo1 = processInfo.getTargetBinary(address);
+ if (binInfo1 == null) {
+ // System.out.println("[Get functino name bug : "
+ // + "Can't find binary info]");
+ // System.out
+ // .println("msg id : "
+ // + AnalyzerUtil.toHexdecimal(input.getId())
+ // + " pid : "
+ // + processInfo.getPid()
+ // + " low : "
+ // + AnalyzerUtil.toHexdecimal(processInfo
+ // .getLowestAddress())
+ // + " input addr : "
+ // + AnalyzerUtil.toHexdecimal(input.getPcAddr())
+ // + " high : "
+ // + AnalyzerUtil.toHexdecimal(processInfo
+ // .getHighestAddress()));
+ return null;
+ }
+ // String binPath1 = binInfo1.getTargetBinaryPath();
+ // System.out.print("binary : " + binPath1 + " ==> ");
+ // AnalyzerUtil.printHexdecimal(processInfo.getLowestAddress());
+ // System.out.print(" < ");
+ // AnalyzerUtil.printHexdecimal(pcAddr);
+ // System.out.print(" < ");
+ // AnalyzerUtil.printHexdecimal(processInfo.getHighestAddress());
+ // System.out.println();
+
+ if (address >= processInfo.getLowestAddress()
+ && address <= processInfo.getHighestAddress()) {
+ String baseAddr = Long.toString(processInfo.getLowestAddress());
+ String pcStr = Long.toString(address);
+ BinaryInfo binInfo = processInfo.getTargetBinary(address);
+ String localPath = binInfo.getTempBinaryPath();
+ if (null != input) {
+ input.setBuildType(binInfo.getType());
+ input.setBinaryPath(binInfo.getTargetBinaryPath());
+ }
+ boolean isPieBuild = true;
+ if (binInfo.getType() != 1) {
+ isPieBuild = false;
+ }
+ functionName = addr2func(localPath, pcStr, isPieBuild, baseAddr);
+ } else {
+ HashMap<String, BinaryInfo> binInfoMap = BinarySettingManager
+ .getInstance().getTargetBinInfoMap();
+ List<String> binPaths = new ArrayList<String>();
+ binPaths.addAll(binInfoMap.keySet());
+
+ HashMap<String, LibraryObject> libHash = processInfo
+ .getLibObjHash();
+ LibraryObject libraryObject = null;
+ int size = binPaths.size();
+ for (int i = 0; i < size; i++) {
+ String binPath = binPaths.get(i);
+ LibraryObject libObj = libHash.get(binPath);
+ if (null == libObj) {
+ continue;
+ }
+ long lowAddr = libObj.getLowestAddress();
+ long highAddr = libObj.getHighestAddress();
+
+ /** for debug */
+ // if (lowAddr > pcAddr || highAddr < pcAddr) {
+ // System.out.print(input.getId() + " lib : " + binPath
+ // + " ==> ");
+ // AnalyzerUtil.printHexdecimal(lowAddr);
+ // System.out.print(" < ");
+ // AnalyzerUtil.printHexdecimal(pcAddr);
+ // System.out.print(" < ");
+ // AnalyzerUtil.printHexdecimal(highAddr);
+ // System.out.println();
+ // }
+
+ if (address >= lowAddr && address <= highAddr) {
+ libraryObject = libObj;
+ break;
+ }
+ }
+ if (null != libraryObject) {
+ String path = libraryObject.getLibPath();
+ BinaryInfo binInfo = binInfoMap.get(path);
+ if (null != binInfo) {
+ String localPath = binInfo.getTempBinaryPath();
+ String baseAddr = Long.toString(libraryObject
+ .getLowestAddress());
+ String pcStr = Long.toString(address);
+ if (null != input) {
+ input.setBinaryPath(binInfo.getTargetBinaryPath());
+ }
+ boolean isPieBuild = true;
+ if (binInfo.getType() != 1) {
+ isPieBuild = false;
+ }
+ functionName = addr2func(localPath, pcStr, isPieBuild, baseAddr);
+ }
+ }
+ }
+
+ if (null == functionName || functionName.isEmpty()
+ || functionName.equals("_end")) { //$NON-NLS-1$
+ functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION;
+ ApiNameManager.getApiId(functionName);
+ } else {
+ String prevFunctionName = functionName;
+ functionName = demanglingFunctionName(prevFunctionName);
+ ApiNameManager.getApiId(functionName);
+ }
+ funcNameMap.put(address, functionName);
+ return functionName;
+ }
}
public static String THREAD_DETAILS_TID;
public static String THREAD_DETAILS_TTYPE;
public static String THREAD_DETAILS_TATTRTYPE;
+ public static String THREAD_DETAILS_FUNCNAME;
+ public static String THREAD_DETAILS_CLASSNAME;
public static String THREAD_DETAILS_STARTTIME;
public static String THREAD_DETAILS_ENDTIME;
THREAD_API_LIST_VIEW_RETURN=Return
THREAD_API_LIST_VIEW_ERRNO=Error Code
-THREAD_DETAILS_TID=Thread ID :
+THREAD_DETAILS_TID=Thread ID :
THREAD_DETAILS_TTYPE=Type :
THREAD_DETAILS_TATTRTYPE=Attr Type :
+THREAD_DETAILS_FUNCNAME=Thread Function :
+THREAD_DETAILS_CLASSNAME=Thread Class :
THREAD_DETAILS_STARTTIME=Start Time :
THREAD_DETAILS_ENDTIME=End Time :
}
LogData log = logLumb.get(i);
int id = log.getId();
- int seqNum = log.getSeq();
if (log instanceof SystemData) {
// System.out
// .println("=========systemData is slicing===========\n");
.getProject().getProcessInfoPackage(pData.getPid());
String apiName = pData.getApiName();
+ // _end indicates end of BSS (uninitialized data) section
+ // function entry of _end is considered as bad data
+ // TODO: test and remove _end condition
if (null == apiName || apiName.isEmpty()
|| apiName.equals("_end")) { //$NON-NLS-1$
- apiName = getFuncName(pData);
+ apiName = SymbolManager.getFuncName(pData, pData.getPcAddr(),
+ pData.getPid(), pData.getTime());
if (apiName == null
|| apiName.equals("<unknown function>")) {
continue;
// + " time " + input.getTime());
// System.out.println(" ]");
// }
-
- // TODO: remove unnecessary code
- private String getFuncName(ProfileData input) {
- long pcAddr = input.getPcAddr();
- HashMap<Long, String> funcNameMap = AnalyzerManager
- .getFuncNameMapByPid(input.getPid());
- String functionName = funcNameMap.get(pcAddr);
- if (null != functionName) {
- return functionName;
- }
-
- // String functionName = null;
- ProcessInfoPackage processInfoPkg = AnalyzerManager.getProject()
- .getProcessInfoPackage(input.getPid());
- ProcessInfo processInfo = processInfoPkg
- .getProcessInfo(input.getTime());
-
- /** for debug */
- BinaryInfo binInfo1 = processInfo.getTargetBinary(input.getPcAddr());
- if (binInfo1 == null) {
- // System.out.println("[Get functino name bug : "
- // + "Can't find binary info]");
- // System.out
- // .println("msg id : "
- // + AnalyzerUtil.toHexdecimal(input.getId())
- // + " pid : "
- // + processInfo.getPid()
- // + " low : "
- // + AnalyzerUtil.toHexdecimal(processInfo
- // .getLowestAddress())
- // + " input addr : "
- // + AnalyzerUtil.toHexdecimal(input.getPcAddr())
- // + " high : "
- // + AnalyzerUtil.toHexdecimal(processInfo
- // .getHighestAddress()));
- return null;
- }
- // String binPath1 = binInfo1.getTargetBinaryPath();
- // System.out.print("binary : " + binPath1 + " ==> ");
- // AnalyzerUtil.printHexdecimal(processInfo.getLowestAddress());
- // System.out.print(" < ");
- // AnalyzerUtil.printHexdecimal(pcAddr);
- // System.out.print(" < ");
- // AnalyzerUtil.printHexdecimal(processInfo.getHighestAddress());
- // System.out.println();
-
- if (pcAddr >= processInfo.getLowestAddress()
- && pcAddr <= processInfo.getHighestAddress()) {
- String baseAddr = Long.toString(processInfo.getLowestAddress());
- String pcStr = Long.toString(pcAddr);
- BinaryInfo binInfo = processInfo.getTargetBinary(pcAddr);
- String localPath = binInfo.getTempBinaryPath();
- input.setBuildType(binInfo.getType());
- input.setBinaryPath(binInfo.getTargetBinaryPath());
- boolean isPieBuild = true;
- if (binInfo.getType() != 1) {
- isPieBuild = false;
- }
- functionName = SymbolManager.addr2func(localPath, pcStr,
- isPieBuild, baseAddr);
- } else {
- HashMap<String, BinaryInfo> binInfoMap = BinarySettingManager
- .getInstance().getTargetBinInfoMap();
- List<String> binPaths = new ArrayList<String>();
- binPaths.addAll(binInfoMap.keySet());
-
- HashMap<String, LibraryObject> libHash = processInfo
- .getLibObjHash();
- LibraryObject libraryObject = null;
- int size = binPaths.size();
- for (int i = 0; i < size; i++) {
- String binPath = binPaths.get(i);
- LibraryObject libObj = libHash.get(binPath);
- if (null == libObj) {
- continue;
- }
- long lowAddr = libObj.getLowestAddress();
- long highAddr = libObj.getHighestAddress();
-
- /** for debug */
- // if (lowAddr > pcAddr || highAddr < pcAddr) {
- // System.out.print(input.getId() + " lib : " + binPath
- // + " ==> ");
- // AnalyzerUtil.printHexdecimal(lowAddr);
- // System.out.print(" < ");
- // AnalyzerUtil.printHexdecimal(pcAddr);
- // System.out.print(" < ");
- // AnalyzerUtil.printHexdecimal(highAddr);
- // System.out.println();
- // }
-
- if (pcAddr >= lowAddr && pcAddr <= highAddr) {
- libraryObject = libObj;
- break;
- }
- }
- if (null != libraryObject) {
- String path = libraryObject.getLibPath();
- BinaryInfo binInfo = binInfoMap.get(path);
- if (null != binInfo) {
- String localPath = binInfo.getTempBinaryPath();
- String baseAddr = Long.toString(libraryObject
- .getLowestAddress());
- String pcStr = Long.toString(pcAddr);
- input.setBinaryPath(binInfo.getTargetBinaryPath());
- boolean isPieBuild = true;
- if (binInfo.getType() != 1) {
- isPieBuild = false;
- }
- functionName = SymbolManager.addr2func(localPath, pcStr,
- isPieBuild, baseAddr);
- }
- }
- }
-
- if (null == functionName || functionName.isEmpty()
- || functionName.equals("_end")) { //$NON-NLS-1$
- functionName = InformationViewLabels.CALLSTACK_TABLE_UNKNOWN_FUNCTION;
- ApiNameManager.getApiId(functionName);
- } else {
- String prevFunctionName = functionName;
- functionName = SymbolManager
- .demanglingFunctionName(prevFunctionName);
- ApiNameManager.getApiId(functionName);
- }
- funcNameMap.put(pcAddr, functionName);
- return functionName;
- }
}
long ospThreadId = 0;
int threadType = 0; // TODO: short
int apiType = 0;// TODO: short
+ String className = null;
public ThreadData(){}
index += INT_SIZE;
apiType = ByteUtil.toInt(data, index);
+ index += INT_SIZE;
+
+ className = ByteUtil.getString(data, index);
}
public long getPThreadId() {
this.apiType = apiType;
}
+ public String getClassName() {
+ return className;
+ }
+
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
@Override
public void makePreparedStatement(PreparedStatement prep)
throws SQLException {
private Canvas canvas = null;
private String tid = AnalyzerLabels.EMPTY_STRING;
private String type = AnalyzerLabels.EMPTY_STRING;
+ private String funcName = AnalyzerLabels.EMPTY_STRING;
+ private String className = AnalyzerLabels.EMPTY_STRING;
private String startTime = AnalyzerLabels.EMPTY_STRING;
private String endTime = AnalyzerLabels.EMPTY_STRING;
private String attrType = AnalyzerLabels.EMPTY_STRING;
private void init() {
tid = AnalyzerLabels.EMPTY_STRING;
type = AnalyzerLabels.EMPTY_STRING;
+ funcName = AnalyzerLabels.EMPTY_STRING;
+ className = AnalyzerLabels.EMPTY_STRING;
startTime = AnalyzerLabels.EMPTY_STRING;
endTime = AnalyzerLabels.EMPTY_STRING;
attrType = AnalyzerLabels.EMPTY_STRING;
p = e.gc.textExtent(tid, SWT.DRAW_MNEMONIC);
y += (p.y + HEIGHT_MARGIN);
}
+ // tizen thread : show thread class name
+ // other thread (e.g. pthread) : show thread function name
+ if (type.equals(ThreadPageLabels.THREAD_ITEM_TYPE_TIZEN)) {
+ if (null != className && !(className.equals(CommonConstants.EMPTY))) {
+ e.gc.drawText(ThreadPageLabels.THREAD_DETAILS_CLASSNAME + className,
+ LEFT_MARGIN, y);
+ p = e.gc.textExtent(tid, SWT.DRAW_MNEMONIC);
+ y += (p.y + HEIGHT_MARGIN);
+ }
+ } else {
+ if (null != funcName && !(funcName.equals(CommonConstants.EMPTY))) {
+ e.gc.drawText(ThreadPageLabels.THREAD_DETAILS_FUNCNAME + funcName,
+ LEFT_MARGIN, y);
+ p = e.gc.textExtent(tid, SWT.DRAW_MNEMONIC);
+ y += (p.y + HEIGHT_MARGIN);
+ }
+ }
if (null != startTime
&& !(startTime.equals(CommonConstants.EMPTY))) {
if (item instanceof ThreadPageThreadData) {
tid = item.getTid();
type = item.getType();
+ str = ((ThreadPageThreadData) item).getThreadFuncName();
+ if (null != str && !(str.equals(CommonConstants.EMPTY))) {
+ funcName = str;
+ }
+ str = ((ThreadPageThreadData) item).getThreadClassName();
+ if (null != str && !(str.equals(CommonConstants.EMPTY))) {
+ className = str;
+ }
str = ((ThreadPageThreadData) item).getStartTime();
if (null != str && !(str.equals(CommonConstants.EMPTY))) {
startTime = str;
if (!type.equals(item.getType())) {
return true;
}
+ if (!funcName.equals(((ThreadPageThreadData) item).getThreadFuncName())) {
+ return true;
+ }
+ if (!className.equals(((ThreadPageThreadData) item).getThreadClassName())) {
+ return true;
+ }
if (!startTime.equals(((ThreadPageThreadData) item).getStartTime())) {
return true;
}
private List<ThreadPageSyncData> syncs = new ArrayList<ThreadPageSyncData>();
private String StartTime;
private String EndTime;
+ private String threadFuncName;
+ private String threadClassName;
private DAChartSeries loadSeries;
private DAChartSeries eventSeries;
private DAChartSeries apiSeries;
- public ThreadPageThreadData(String type, String pid, String tid, String attrType) {
+ public ThreadPageThreadData(String type, String pid, String tid, String attrType,
+ String funcName) {
super(type, String.valueOf(tid), pid, tid, attrType);
+ this.threadFuncName = funcName;
}
public void addDataEvent(ThreadPageThreadDataEvent dataEvent) {
contentsQueue.add(dataEvent);
}
+
+ public String getThreadFuncName() {
+ return threadFuncName;
+ }
+
+ public String getThreadClassName() {
+ return threadClassName;
+ }
+
+ public void setThreadClassName(String className) {
+ threadClassName = className;
+ }
public void setItem(DAChartBoardItem item) {
this.item = item;
import java.util.Comparator;
import org.tizen.dynamicanalyzer.common.AnalyzerManager;
+import org.tizen.dynamicanalyzer.common.SymbolManager;
import org.tizen.dynamicanalyzer.constant.CommonConstants;
import org.tizen.dynamicanalyzer.logparser.LogCenterConstants;
import org.tizen.dynamicanalyzer.nl.ThreadPageLabels;
private List<ThreadPageThreadDataEvent> callEventQueue = new ArrayList<ThreadPageThreadDataEvent>();
private HashMap<String, Integer> threadAttrMap = new HashMap<String, Integer>();
private HashMap<String, Integer> syncAttrMap = new HashMap<String, Integer>();
+ // threadFuncMap : (pthreadId, function address)
+ private HashMap<String, Long> threadFuncMap = new HashMap<String, Long>();
private int preSelectionPid = -1;
public static final int PTHREAD_CREATE_JOINABLE = 0;
public void createMainThreadItem(int tid) {
ThreadPageThreadData mainData = new ThreadPageThreadData(
ThreadPageLabels.THREAD_ITEM_TYPE_MAIN, String.valueOf(tid),
- String.valueOf(tid), CommonConstants.EMPTY);
+ String.valueOf(tid), CommonConstants.EMPTY, "main");
pushRow(mainData);
}
case LogCenterConstants.THREAD_API_TYPE_START:
if (apiName.equals(ThreadPageLabels.THREAD_API_PTHREAD_CREATE)) {
checkThreadType(input.getArgs(), pthreadId);
+ checkThreadFunc(input.getArgs(), pthreadId);
}
event = new ThreadPageThreadDataEvent(
ThreadPageThreadDataEvent.TYPE_API,
case LogCenterConstants.THREAD_API_TYPE_INTERNAL_START:
Integer threadAttrTypeInt = threadAttrMap.get(pthreadId);
String threadAttrType;
+ String funcName;
if (null != threadAttrTypeInt) {
threadAttrType = getAttrTypeByTypeInt(threadAttrTypeInt);
} else {
threadAttrType = ThreadPageLabels.THREAD_ATTR_TYPE_JOINABLE;
}
+ // get thread function name for this pthread
+ funcName = SymbolManager.getFuncName(null, threadFuncMap.get(pthreadId),
+ input.getPid(), input.getTime());
ThreadPageThreadData data = new ThreadPageThreadData(
ThreadPageLabels.THREAD_ITEM_TYPE_PTHREAD, pid, tid,
- threadAttrType);
+ threadAttrType, funcName);
pushRow(data);
event = new ThreadPageThreadDataEvent(
ThreadPageThreadDataEvent.TYPE_EVENT,
int apiType = input.getApiType();
String apiName = input.getApiName();
String callID = Long.toString(input.getOspThreadId());
+ String className = null;
ThreadPageThreadData data;
ThreadPageThreadDataEvent event;
long errorNum = input.getErrno();
event.setCallID(callID);
data = findCallQueue(callID);
if (null != data) {
+ data.setThreadClassName(input.getClassName());
pushRow(data);
}
pushEvent(event);
case LogCenterConstants.THREAD_API_TYPE_INTERNAL_START:
data = new ThreadPageThreadData(
ThreadPageLabels.THREAD_ITEM_TYPE_TIZEN, pid, tid,
- ThreadPageLabels.THREAD_ATTR_TYPE_JOINABLE);
+ ThreadPageLabels.THREAD_ATTR_TYPE_JOINABLE, CommonConstants.EMPTY);
// TIZEN thread includes the internal thread
- if (true == checkCalledThread(callID)) {
- pushRow(data);
+ if ((className = checkCalledThread(callID)) != null) {
+ data.setThreadClassName(className);
+ pushRow(data);
} else {
pushCallRow(data);
}
}
public void parseAPI(LogData input) {
-
if (null == input) {
return;
}
parseSync(logPack);
hasUpdate = true;
}
-
- private boolean checkCalledThread(String callId) {
+ // when INTERNAL_START log comes after START log,
+ // this method finds matching START log (for TIZEN thread only)
+ // return class name from the START log
+ private String checkCalledThread(String callId) {
if (null == callId) {
- return false;
+ return null;
}
int callEventQueueSize = callEventQueue.size();
ThreadPageThreadDataEvent callEvent;
continue;
}
if (callId.equals(callEvent.getCallID())) {
- return true;
+ ThreadData threadData = (ThreadData) callEvent.getContents();
+ return threadData.getClassName();
}
}
- return false;
+ return null;
}
private String getCallEventID(String callID) {
threadAttrMap.put(pthreadId, attrType);
}
}
+ // extract function address from arguments of thread create function,
+ // (e.g. int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); )
+ // put (pthreadId, function address) in the map
+ private void checkThreadFunc(String args, String pthreadId) {
+ String[] temp = args.split(",");
+ if (temp.length != 4) {
+ return;
+ }
+ // 3rd argument is function address
+ String strFuncAddr = temp[2].trim();
+ Long funcAddr = Long.decode(strFuncAddr);
+
+ threadFuncMap.put(pthreadId, funcAddr);
+ }
private void checkMutexAttrType(String input) {
String[] temp = input.split(",");