SRADA-1035 Implemented popup menu for memory callstack table.
authorp.privalov <p.privalov@partner.samsung.com>
Mon, 12 Sep 2016 13:30:05 +0000 (16:30 +0300)
committerVladislav Eliseev <v.eliseev@samsung.com>
Fri, 16 Sep 2016 11:29:04 +0000 (20:29 +0900)
Changes:
 * Memory callstack table items now contains 2 additional portions of data:
   caller address and start address.
 * These fields filled with 0 if unknown, or with their addresses.
 * RuntimeCallstackManager.makeCallstackWithoutBacktrace(..) now fills
   function start address correctly.

Note: after probing of PLT-functions It is required to check correctness of
RuntimeCallstackManager.makeCallstackWithoutBacktrace(..),
RuntimeCallstackManager.makeUserCallstack(..)
because both of them build callstack in assumption that we have probes only on
functions from specified binary.

Conflicts:
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/memory/table/MemoryCallStackTable.java

Change-Id: I20100a5a52731685f9ac279daad1faac718b5fd0

org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/common/AnalyzerConstants.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/listeners/TableTooltipListener.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/project/callstack/BaseCallstackManager.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/project/callstack/RuntimeCallstackManager.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/swap/logparser/LogParser.java
org.tizen.dynamicanalyzer/src/org/tizen/dynamicanalyzer/ui/memory/table/MemoryCallStackTable.java

index 47df980..4cb9f09 100644 (file)
@@ -251,6 +251,9 @@ public class AnalyzerConstants {
        public final static String CALLSTACK_KEY_TIME = "time";//$NON-NLS-1$
        public final static String CALLSTACK_KEY_LIBNAME = "libName";//$NON-NLS-1$
 
+       public final static String MEM_CALLSTACK_KEY_CALLER_ADDRESS = "caller address";
+       public final static String MEM_CALLSTACK_KEY_FUNCTION_START_ADDRESS = "start address";
+
        // application list management
        public final static String APPCONTROL = "_AppControl";//$NON-NLS-1$
        public final static String RUNNING_PROCESS = "_Running process_";//$NON-NLS-1$
index 9e56d0e..8a9e731 100644 (file)
@@ -180,6 +180,17 @@ public class TableTooltipListener implements Listener {
                this.enabled = enabled;
        }
 
+       /**
+        * Search for line in source code, where specified with {@code item}
+        * instruction <b>was called</b>. This method explores {@code item.getData()}, so if
+        * no data was defined it will return {@link SourceLine} with specified
+        * error.
+        *
+        * @param item grid item with defined data
+        * @return {@link SourceLine} object encapsulates info about source line, or
+        *         description of appeared error. {@code null} returned if {@code item
+        *         == null}.
+        */
        public SourceLine getCallerSourceLine(GridItem item) {
                if (item == null) {
                        return null;
@@ -197,6 +208,12 @@ public class TableTooltipListener implements Listener {
                        pid = (Integer) item.getData(AnalyzerConstants.CALLSTACK_KEY_PID);
                        time = (Long) item.getData(AnalyzerConstants.CALLSTACK_KEY_TIME);
                        break;
+               case AnalyzerConstants.TYPE_TABLE_MEM_CALLSTACK:
+                       addr = (Long) item
+                                       .getData(AnalyzerConstants.MEM_CALLSTACK_KEY_CALLER_ADDRESS);
+                       pid = (Integer) item.getData(AnalyzerConstants.CALLSTACK_KEY_PID);
+                       time = (Long) item.getData(AnalyzerConstants.CALLSTACK_KEY_TIME);
+                       break;
                // TODO: change number to define
                case AnalyzerConstants.TYPE_TABLE_FAILED:
                        List<Object> failedData = tableData.getData();
@@ -239,6 +256,16 @@ public class TableTooltipListener implements Listener {
                return getSourceLine(addr, pid, time);
        }
 
+       /**
+        * Search for line in source code, where specified with {@code item}
+        * instruction <b>is defined</b>. This method explores {@code item.getData()}, so if
+        * no data defined it will return {@link SourceLine} with specified error.
+        *
+        * @param item grid item with defined data
+        * @return {@link SourceLine} object encapsulates info about source line, or
+        *         description of appeared error. {@code null} returned if {@code item ==
+        *         null}.
+        */
        public SourceLine getDefinitionSourceLine(GridItem item) {
                if (item == null) {
                        return null;
@@ -255,6 +282,12 @@ public class TableTooltipListener implements Listener {
                        pid = (Integer) calltraceData.get(FunctionEntryDBTable.COLUMN.PID.index);
                        time = (Long) calltraceData.get(FunctionEntryDBTable.COLUMN.START_TIME.index);
                        break;
+               case AnalyzerConstants.TYPE_TABLE_MEM_CALLSTACK:
+                       addr = (Long) item
+                                       .getData(AnalyzerConstants.MEM_CALLSTACK_KEY_FUNCTION_START_ADDRESS);
+                       pid = (Integer) item.getData(AnalyzerConstants.CALLSTACK_KEY_PID);
+                       time = (Long) item.getData(AnalyzerConstants.CALLSTACK_KEY_TIME);
+                       break;
                default:
                        /*
                         * Do Nothing.
@@ -505,6 +538,12 @@ public class TableTooltipListener implements Listener {
                }
        }
 
+       /**
+        * Extract library name from {@code item}'s data.
+        *
+        * @param item grid item that encapsulates data
+        * @return {@link String} representation of library path
+        */
        private String getLibPath(GridItem item) {
                DATableDataFormat tableData = (DATableDataFormat) item.getData();
                String libName = null;
@@ -530,6 +569,9 @@ public class TableTooltipListener implements Listener {
                        BinaryInfo binInfo = Global.getProject().getDeviceStatusInfo().getBinaryInfo(binaryId);
                        libName = binInfo.getTargetBinaryPath();
                        break;
+               case AnalyzerConstants.TYPE_TABLE_MEM_CALLSTACK:
+                       libName = (String) item.getData(AnalyzerConstants.CALLSTACK_KEY_LIBNAME);
+                       break;
                default: // normal
                        ProbeCommonData wData = (ProbeCommonData) tableData.getLogData();
                        libName = wData.getLibName();
index 926a31f..a282d7d 100644 (file)
@@ -59,6 +59,13 @@ public abstract class BaseCallstackManager {
        protected NavigableMap<Long, CallStackData> callstackDataBySeqMap = new ConcurrentSkipListMap<Long, CallStackData>();
        protected Map<Integer, List<CallStackItem>> userCallstackByTidMap = new HashMap<Integer, List<CallStackItem>>();
 
+       /**
+        * Method to create callstack for current state of program executing.
+        *
+        * @param log data that includes information about last function entry or
+        *            exit
+        * @param profiler profiler that encapsulates data preparations
+        */
        abstract public void makeUserCallstack(LogData log, ProfileDataMaker profiler);
 
        abstract public long getSeqOfUserCallstackForTime(int tid, long time);
index eb62029..0edc782 100644 (file)
@@ -109,13 +109,9 @@ public class RuntimeCallstackManager extends BaseCallstackManager {
 
                Map<Long, CallStackUnit> addrMap = getCallStackApiAddrByPidMap(pid);
 
-               long seq = log.getSeq();
-               int tid = log.getTid();
-
                long selfAddr = log.getPcAddr();
                long callerAddr = log.getCallerPcAddr();
 
-               CallStackData callstackData = new CallStackData(seq);
                CallStackUnit selfCallstackUnit = addrMap.get(selfAddr);
 
                if (null == selfCallstackUnit) {
@@ -131,9 +127,7 @@ public class RuntimeCallstackManager extends BaseCallstackManager {
                // insert call count
                profiler.makeFupDataForCallTrace(selfCallstackUnit, log);
 
-               List<CallStackItem> userCallstack = getUserCallstack(tid);
-               int size = userCallstack.size();
-               NavigableMap<Long, Long> seqByTimeMap = getSeqTimeByTidMap(tid, true);
+
 
                CallStackUnit callerCallstackUnit = addrMap.get(callerAddr);
                if (null == callerCallstackUnit) {
@@ -144,37 +138,127 @@ public class RuntimeCallstackManager extends BaseCallstackManager {
 
                int eventType = log.getMsgID();
                if (eventType == ProtocolConstants.MSG_FUNCTION_ENTRY) {
-                       if (size == 0) {
-                               userCallstack.add(new CallStackItem(selfCallstackUnit, time));
+                       proceedEntry(log, selfCallstackUnit, addrMap);
+               } else if (eventType == ProtocolConstants.MSG_FUNCTION_EXIT) {
+                       proceedExit(log, selfCallstackUnit, addrMap);
+
+               }
+       }
+
+       /**
+        * Method calculates new callstack value on function entry.
+        *
+        * @param log data that includes information about current state of
+        *            execution
+        * @param selfCallstackUnit description of function execution enter to
+        * @param addrMap map with functions assigned to caller addresses
+        */
+       private void proceedEntry(ProfileData log, CallStackUnit selfCallstackUnit,
+                       Map<Long, CallStackUnit> addrMap) {
+               int pid = log.getPid();
+               int tid = log.getTid();
+
+               long time = log.getTime();
+               long callerAddr = log.getCallerPcAddr();
+               long seq = log.getSeq();
+
+               List<CallStackItem> userCallstack = getUserCallstack(tid);
+               int size = userCallstack.size();
+               CallStackData callstackData = new CallStackData(seq);
+
+               NavigableMap<Long, Long> seqByTimeMap = getSeqTimeByTidMap(tid, true);
+               if (size == 0) {
+                       userCallstack.add(new CallStackItem(selfCallstackUnit, time));
+               } else {
+                       if (!isAddrInBinaryRange(pid, time, callerAddr)) {
+                               CallStackUnit callbackApi = addrMap
+                                               .get(LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR);
+                               if (null == callbackApi) {
+                                       callbackApi = new CallStackUnit(
+                                                       LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR,
+                                                       LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_SYMBOL,
+                                                       log);
+                                       addrMap.put(
+                                                       LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR,
+                                                       callbackApi);
+                               }
+                               userCallstack.add(new CallStackItem(callbackApi));
                        } else {
-                               if (!isAddrInBinaryRange(pid, time, callerAddr)) {
-                                       CallStackUnit callbackApi = addrMap
-                                                       .get(LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR);
-                                       if (null == callbackApi) {
-                                               callbackApi = new CallStackUnit(
-                                                               LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR,
-                                                               LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_SYMBOL, log);
-                                               addrMap.put(LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC_ADDR,
-                                                               callbackApi);
-                                       }
-                                       userCallstack.add(new CallStackItem(callbackApi));
+                               CallStackUnit callerCsa = addrMap.get(callerAddr);
+                               if (null == callerCsa) {
+                                       callerCsa = userCallstack.get(size - 1).getCallStackUnit();
+                                       callerCsa.setFunctionStartAddr(callerCsa.getAddr());
+                                       callerCsa.setAddr(callerAddr);
                                } else {
-                                       CallStackUnit callerCsa = addrMap.get(callerAddr);
-                                       if (null == callerCsa) {
-                                               callerCsa = userCallstack.get(size - 1).getCallStackUnit();
-                                               callerCsa.setFunctionStartAddr(callerCsa.getAddr());
-                                               callerCsa.setAddr(callerAddr);
-                                       } else {
-                                               CallStackItem topCallstackItem = userCallstack.get(size - 1);
-                                               callerCsa.setFunctionStartAddr(topCallstackItem.getCallStackUnit()
-                                                               .getAddr());
-                                               userCallstack.set(size - 1,
-                                                               new CallStackItem(callerCsa, topCallstackItem.getStartTime()));
-                                       }
+                                       CallStackItem topCallstackItem = userCallstack
+                                                       .get(size - 1);
+                                       callerCsa.setFunctionStartAddr(topCallstackItem
+                                                       .getCallStackUnit().getAddr());
+                                       userCallstack.set(size - 1, new CallStackItem(callerCsa,
+                                                       topCallstackItem.getStartTime()));
                                }
-                               userCallstack.add(new CallStackItem(selfCallstackUnit, time));
                        }
+                       userCallstack.add(new CallStackItem(selfCallstackUnit, time));
+               }
+               size = userCallstack.size();
+               for (int i = size - 1; i >= 0; i--) {
+                       callstackData.addAddr(userCallstack.get(i).getCallStackUnit()
+                                       .getAddr());
+               }
+               offerCallStackData(callstackData);
+               getCallStackDataBySeqMap().put(seq, callstackData);
+               seqByTimeMap.put(time, seq);
+       }
+
+       /**
+        * Method calculates new callstack value on function exit.
+        *
+        * @param log data that includes information about current state of
+        *            execution
+        * @param selfCallstackUnit description of function execution exit from
+        * @param addrMap map with functions assigned to caller addresses
+        */
+       private void proceedExit(ProfileData log, CallStackUnit selfCallstackUnit,
+                       Map<Long, CallStackUnit> addrMap) {
+               int tid = log.getTid();
+               long time = log.getTime();
+               long seq = log.getSeq();
+               List<CallStackItem> userCallstack = getUserCallstack(tid);
+               int size = userCallstack.size();
+               CallStackData callstackData = new CallStackData(seq);
+
+               NavigableMap<Long, Long> seqByTimeMap = getSeqTimeByTidMap(tid, true);
+               if (size == 0) {
+                       // if not in range profiling, this should not be reached
+                       return;
+               }
+               CallStackUnit removeCallStackUnit = userCallstack.get(size - 1)
+                               .getCallStackUnit();
+               if (selfCallstackUnit.getFunctionId() == removeCallStackUnit
+                               .getFunctionId()) {
+                       userCallstack.remove(size - 1);
                        size = userCallstack.size();
+                       if (size - 1 > 0) {
+                               CallStackUnit checkCallStackUnit = userCallstack.get(size - 1)
+                                               .getCallStackUnit();
+                               if (checkCallStackUnit.getFunctionName().equals(
+                                               LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC)) {
+                                       userCallstack.remove(size - 1);
+                               }
+                       }
+                       size = userCallstack.size();
+                       if (size > 0) {
+                               CallStackItem prevCallstackItem = userCallstack.get(size - 1);
+                               long prevSelfAddr = prevCallstackItem.getCallStackUnit()
+                                               .getFunctionStartAddr();
+                               CallStackUnit callerCsa = addrMap.get(prevSelfAddr);
+                               if (null == callerCsa) {
+                                       prevCallstackItem.getCallStackUnit().setAddr(prevSelfAddr);
+                               } else {
+                                       userCallstack.set(size - 1, new CallStackItem(callerCsa,
+                                                       prevCallstackItem.getStartTime()));
+                               }
+                       }
                        for (int i = size - 1; i >= 0; i--) {
                                callstackData.addAddr(userCallstack.get(i).getCallStackUnit()
                                                .getAddr());
@@ -182,55 +266,25 @@ public class RuntimeCallstackManager extends BaseCallstackManager {
                        offerCallStackData(callstackData);
                        getCallStackDataBySeqMap().put(seq, callstackData);
                        seqByTimeMap.put(time, seq);
-               } else if (eventType == ProtocolConstants.MSG_FUNCTION_EXIT) {
-                       if (size == 0) {
-                               // if not in range profiling, this should not be reached
-                               return;
-                       }
-                       CallStackUnit removeCallStackUnit = userCallstack.get(size - 1).getCallStackUnit();
-                       if (selfCallstackUnit.getFunctionId() == removeCallStackUnit.getFunctionId()) {
-                               userCallstack.remove(size - 1);
-                               size = userCallstack.size();
-                               if (size - 1 > 0) {
-                                       CallStackUnit checkCallStackUnit = userCallstack.get(size - 1)
-                                                       .getCallStackUnit();
-                                       if (checkCallStackUnit.getFunctionName().equals(
-                                                       LogCenterConstants.USER_FUNCTION_CALLBACK_FUNC)) {
-                                               userCallstack.remove(size - 1);
-                                       }
-                               }
-                               size = userCallstack.size();
-                               if (size > 0) {
-                                       CallStackItem prevCallstackItem = userCallstack.get(size - 1);
-                                       long prevSelfAddr = prevCallstackItem.getCallStackUnit().getFunctionStartAddr();
-                                       CallStackUnit callerCsa = addrMap.get(prevSelfAddr);
-                                       if (null == callerCsa) {
-                                               prevCallstackItem.getCallStackUnit().setAddr(prevSelfAddr);
-                                       } else {
-                                               userCallstack.set(size - 1,
-                                                               new CallStackItem(callerCsa, prevCallstackItem.getStartTime()));
-                                       }
-                               }
-                               for (int i = size - 1; i >= 0; i--) {
-                                       callstackData.addAddr(userCallstack.get(i)
-                                                       .getCallStackUnit().getAddr());
-                               }
-                               offerCallStackData(callstackData);
-                               getCallStackDataBySeqMap().put(seq, callstackData);
-                               seqByTimeMap.put(time, seq);
-                       } else {
-                               Logger.debug("makeUserCallstack : EXIT self is not the same as top of user callstack");
-                       }
+               } else {
+                       Logger.debug("makeUserCallstack : EXIT self is not the same as top of user callstack");
+               }
 
-                       String apiName = Global.getFunctionName(log.getApiId());
-                       if (apiName.equals("main")) { //$NON-NLS-1$
-                               ProcessInformation process = Global.getProject()
-                                               .getProcessInformation(log.getPid());
-                               process.setDropLog(true);
-                       }
+               String apiName = Global.getFunctionName(log.getApiId());
+               if (apiName.equals("main")) { //$NON-NLS-1$
+                       ProcessInformation process = Global.getProject()
+                                       .getProcessInformation(log.getPid());
+                       process.setDropLog(true);
                }
        }
 
+       /**
+        * Method to update callstack for current state of execution, if it is not
+        * function entry or exit.
+        *
+        * @param inputData data that includes information about current state of
+        *            execution
+        */
        public void makeCallstackWithoutBacktrace(LogData inputData) {
                if (!(inputData instanceof ProbeCommonData)) {
                        Logger.warning("failed to make callstack : log is not probe log");
@@ -285,6 +339,11 @@ public class RuntimeCallstackManager extends BaseCallstackManager {
                                String strCallerSymbol = getCallStackSymbol(callerAddr, pid, time);
                                if(strCallerSymbol != null) {
                                        callerCallstackUnit = new CallStackUnit(callerAddr, strCallerSymbol, inputData);
+
+                                       CallStackUnit topUserCallstack = addrMap.get(addrs.get(0));
+                                       if (callerCallstackUnit.getFunctionId() == topUserCallstack.getFunctionId())
+                                               callerCallstackUnit.setFunctionStartAddr(topUserCallstack.getFunctionStartAddr());
+
                                        addrMap.put(callerAddr, callerCallstackUnit);
                                }
                        }
index df4d542..b6f39bb 100644 (file)
@@ -244,6 +244,8 @@ public class LogParser extends DataThread<List<LogData>> {
                                packLog(log, logPack);
                                break;
                        default:
+                               // Currently, an only message that got to default section is
+                               // MSG_PROBE_LIFECYCLE = 0x0105
                                packLog(log, logPack);
                                Global.getRuntimeCallstackManager().makeCallstackWithoutBacktrace(log);
                                break;
index 7fbcf30..be590e3 100644 (file)
@@ -59,6 +59,13 @@ public class MemoryCallStackTable extends DATableComposite {
                super(parent, style);
        }
 
+       /**
+        * Public constructor.
+        *
+        * @param parent parent composite
+        * @param compStyle SWT composite style
+        * @param tableStyle SWT table style
+        */
        public MemoryCallStackTable(Composite parent, int compStyle, int tableStyle) {
                super(parent, compStyle, tableStyle);
 
@@ -80,9 +87,16 @@ public class MemoryCallStackTable extends DATableComposite {
                        }
                });
 
+               // Add standard right mouse button listener
+               setContextMenu(AnalyzerConstants.CONTEXT_TABLE_SOURCE);
                applyFilterImage();
        }
 
+       /**
+        * Update table data according to selected item.
+        *
+        * @param selData selected data item
+        */
        public void updateCallstackTable(DASelectionData selData) {
                long t = System.nanoTime(); // TODO: this instruction required to
                                                                        // analyze performance and must be removed.
@@ -145,10 +159,16 @@ public class MemoryCallStackTable extends DATableComposite {
                        callstackTableData.setObject(allocCallerAddr);
                        GridItem gridItem = new GridItem(table, SWT.NONE);
                        gridItem.setData(callstackTableData);
-                       gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_ADDR, allocCallerAddr);
+                       gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_ADDR, 0L);
                        gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_PID, pid);
                        gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_TIME, time);
-                       gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_LIBNAME, allocPath);
+                       gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_LIBNAME, "");
+                       gridItem.setData(
+                                       AnalyzerConstants.MEM_CALLSTACK_KEY_CALLER_ADDRESS,
+                                       allocCallerAddr);
+                       gridItem.setData(
+                                       AnalyzerConstants.MEM_CALLSTACK_KEY_FUNCTION_START_ADDRESS,
+                                       0L);
 
                        gridItem.setText(0, allocName);
                        gridItem.setText(1, UNKNOWN);
@@ -160,6 +180,11 @@ public class MemoryCallStackTable extends DATableComposite {
                        gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_PID, pid);
                        gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_TIME, time);
                        gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_LIBNAME, allocPath);
+                       gridItem.setData(
+                                       AnalyzerConstants.MEM_CALLSTACK_KEY_CALLER_ADDRESS, 0L);
+                       gridItem.setData(
+                                       AnalyzerConstants.MEM_CALLSTACK_KEY_FUNCTION_START_ADDRESS,
+                                       0L);
 
                        gridItem.setText(0, UNKNOWN);
                        String addrInput = (allocCallerAddr == 0)
@@ -190,9 +215,16 @@ public class MemoryCallStackTable extends DATableComposite {
                                if (i==0){
                                        if(allocPath.equals(Global.getLibraryName(api.getBinaryID()))){
                                                gridItem.setText(0, api.getFunctionName());
+                                               gridItem.setData(
+                                                               AnalyzerConstants.MEM_CALLSTACK_KEY_CALLER_ADDRESS,
+                                                               addrs.get(1));
+                                               gridItem.setData(
+                                                               AnalyzerConstants.MEM_CALLSTACK_KEY_FUNCTION_START_ADDRESS,
+                                                               api.getFunctionStartAddr());
                                                continue;
                                        }else{
-                                                       address = 0;
+                                               if (addrs.size() > 1)
+                                                       address = 0L;
                                        }
                                }
 
@@ -206,6 +238,15 @@ public class MemoryCallStackTable extends DATableComposite {
                                gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_PID, pid);
                                gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_TIME, time);
                                gridItem.setData(AnalyzerConstants.CALLSTACK_KEY_LIBNAME, path);
+                               if (i + 1 < addrs.size())
+                                       gridItem.setData(AnalyzerConstants.MEM_CALLSTACK_KEY_CALLER_ADDRESS, addrs.get(i+1));
+                               else
+                                       gridItem.setData(
+                                                       AnalyzerConstants.MEM_CALLSTACK_KEY_CALLER_ADDRESS,
+                                                       0L);
+                               gridItem.setData(
+                                               AnalyzerConstants.MEM_CALLSTACK_KEY_FUNCTION_START_ADDRESS,
+                                               api.getFunctionStartAddr());
 
                                addrInput = (address == 0) ? UNKNOWN : hexAddr; //$NON-NLS-1$
                                gridItem.setText(1, addrInput.toLowerCase());