/*******************************************************************************
* Copyright (c) 2016 Ericsson.
* 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
*******************************************************************************/
package org.eclipse.cdt.llvm.dsf.lldb.core.internal.service;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IProcessInfo;
import org.eclipse.cdt.core.IProcessList;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_4;
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
import org.eclipse.cdt.dsf.gdb.service.SessionType;
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.CoreException;
/**
* Provides processes information see {@link IProcesses}
*
* This LLDB specific implementation was initially created in order to be able
* to get the list of processes in the absence of the MI command
*
* <pre>
* -list-thread-groups --available
* </pre>
*
* This is used notably when attaching to processes.
*/
public class LLDBProcesses extends GDBProcesses_7_4 {
// A map of pid to names. It is filled when we get all the
// processes that are running
private Map<Integer, String> fProcessNames = new HashMap<Integer, String>();
/**
* Constructs the {@link LLDBProcesses} service.
*
* @param session
* The debugging session
*/
public LLDBProcesses(DsfSession session) {
super(session);
}
@Override
public void getRunningProcesses(IDMContext dmc, DataRequestMonitor<IProcessDMContext[]> rm) {
// '-list-thread-groups --available' is not supported by lldm-mi so we
// fall back to CDT Core's implementation of listing running processes.
// This works just like GDBProcesses#getRunningProcesses.
final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
if (backend.getSessionType() == SessionType.LOCAL) {
IProcessList list = null;
try {
list = CCorePlugin.getDefault().getProcessList();
} catch (CoreException e) {
}
if (list == null) {
// If the list is null, the prompter will deal with it
fProcessNames.clear();
rm.setData(null);
} else {
fProcessNames.clear();
IProcessInfo[] procInfos = list.getProcessList();
for (IProcessInfo procInfo : procInfos) {
fProcessNames.put(procInfo.getPid(), procInfo.getName());
}
rm.setData(makeProcessDMCs(controlDmc, procInfos));
}
rm.done();
} else {
// Remote not supported for now
fProcessNames.clear();
rm.setData(new IProcessDMContext[0]);
rm.done();
}
}
private IProcessDMContext[] makeProcessDMCs(ICommandControlDMContext controlDmc, IProcessInfo[] processes) {
IProcessDMContext[] procDmcs = new IMIProcessDMContext[processes.length];
for (int i = 0; i < procDmcs.length; i++) {
procDmcs[i] = createProcessContext(controlDmc, Integer.toString(processes[i].getPid()));
}
return procDmcs;
}
@Override
public void getExecutionData(IThreadDMContext dmc, DataRequestMonitor<IThreadDMData> rm) {
if (dmc instanceof IMIProcessDMContext) {
String pidStr = ((IMIProcessDMContext) dmc).getProcId();
int pid = -1;
try {
pid = Integer.parseInt(pidStr);
} catch (NumberFormatException e) {
}
// It's possible that we get here without getRunningProcesses called
// yet so the process names map will be empty. This can happen when
// doing local debugging but not attach mode.
if (fProcessNames.isEmpty()) {
getRunningProcesses(dmc, new DataRequestMonitor<>(getExecutor(), rm));
}
String name = fProcessNames.get(pid);
if (name == null) {
name = Messages.LLDBProcesses_unknown_process_name;
}
rm.setData(new LLDBMIThreadDMData(name, pidStr));
rm.done();
} else {
super.getExecutionData(dmc, rm);
}
}
private static class LLDBMIThreadDMData implements IThreadDMData {
final String fName;
final String fId;
public LLDBMIThreadDMData(String name, String id) {
fName = name;
fId = id;
}
@Override
public String getId() {
return fId;
}
@Override
public String getName() {
return fName;
}
@Override
public boolean isDebuggerAttached() {
return true;
}
}
}