blob: db5c162893af8781e5c8150a0ea8e93475dbd6f4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.incubator.internal.uftrace.core.trace;
import java.io.File;
import java.io.IOException;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
/**
* The session id a random 16-character string (or 8-byte hex number) and it's
* used as a file name of the map file (e.g. sid-5951ceee0be7fb17.map). A
* session contains memory mapping of tasks which provides base address of each
* module (library or executable). It's actually a copy of a /proc/<TID>/maps
* file.
*
* TODO: put in an in memory ht
*
* @author Matthew Khouzam
*
*/
public class MapParser {
private static final String SESSION_PATTERN_STRING = "sid\\-([a-fA-F0-9]+)\\.map"; //$NON-NLS-1$
private static final Pattern SESSION_PATTERN = Pattern.compile(SESSION_PATTERN_STRING);
private static final Pattern MAPFILE_PATTERN = Pattern.compile(
"^\\s*([a-fA-F0-9]+)\\-([a-fA-F0-9]+)\\s+([rxwps-]+)\\s+([a-fA-F0-9]+)\\s+([a-fA-F0-9]+)\\:([a-fA-F0-9]+)\\s+([a-fA-F0-9]+)\\s*(\\S+)?$"); //$NON-NLS-1$
private final long fSessionId;
private final NavigableMap<Long, MapEntry> fData;
/**
* Map parser builder
*
* @param file
* the file to read
* @return the map parser
* @throws IOException
* error reading the file
*/
public static MapParser create(File file) throws IOException {
String name = file.getName();
Matcher sessionName = SESSION_PATTERN.matcher(name);
if (!sessionName.matches()) {
return null;
}
long sessionId = Long.parseUnsignedLong(sessionName.group(1), 16);
LineIterator iter = FileUtils.lineIterator(file);
NavigableMap<Long, MapEntry> entries = new TreeMap<>();
while (iter.hasNext()) {
String line = iter.next();
Matcher matcher = MAPFILE_PATTERN.matcher(line);
matcher.matches();
long addrLow = Long.parseUnsignedLong(matcher.group(1), 16);
long addrHigh = Long.parseUnsignedLong(matcher.group(2), 16);
Perms perms = Perms.create(matcher.group(3));
long offset = Long.parseLong(matcher.group(4), 16);
char deviceHigh = (char) Integer.parseInt(matcher.group(5), 16);
char deviceLow = (char) Integer.parseInt(matcher.group(6), 16);
long iNode = Long.parseLong(matcher.group(7), 16);
String pathName = matcher.group(8);
entries.put(addrLow,
new MapEntry(addrLow, addrHigh, perms, offset, deviceLow, deviceHigh, iNode, pathName));
}
return new MapParser(sessionId, entries);
}
private MapParser(long sessionId, NavigableMap<Long, MapEntry> data) {
fSessionId = sessionId;
fData = data;
}
/**
* Get the map data
*
* @return the map data
*/
public NavigableMap<Long, MapEntry> getData() {
return fData;
}
/**
* Get the session ID
*
* @return the session ID
*/
public long getSessionId() {
return fSessionId;
}
}