blob: e710fdbb3ce1f1c32debcb4133ee97533cd24014 [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
*
* Contributors:
* Mikael Ferland - Initial API and implementation
*
*******************************************************************************/
package org.eclipse.tracecompass.internal.tmf.core.callstack;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.TreeMap;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.tmf.core.symbols.IMappingFile;
import org.eclipse.tracecompass.tmf.core.symbols.TmfResolvedSymbol;
/**
* This class maps addresses to their symbol text. The mappings may contain
* several areas of addresses. Each area should end with a symbol with suffix
* 'END__', so that if the requested symbol is not an exact match to one of the
* mapped symbol, it will return the closest symbol that is lesser than the
* requested address, unless that symbol has the end suffix, it is out of the
* area of this mapping.
*
* @author Mikael Ferland
*/
public final class MappingFile implements IMappingFile {
private static final String DEFAULT_END_SUFFIX = "END__"; //$NON-NLS-1$
private static Comparator<@NonNull Long> MAP_COMPARATOR = Long::compareUnsigned;
private final String fFullPath;
private final boolean fIsBinaryFile;
private final NavigableMap<Long, TmfResolvedSymbol> fSymbolMapping;
private final int fPid;
/**
* Create a new {@link MappingFile}
*
* @param path
* Path leading to the mapping file
* @param isBinaryFile
* Type of the mapping file
* @param results
* Resolved symbols for the given mapping file
* @param pid
* The ID of the process this mapping applies to. A negative value
* means it applies to all processes
*/
public MappingFile(String path, boolean isBinaryFile, Map<Long, TmfResolvedSymbol> results, int pid) {
fFullPath = path;
fIsBinaryFile = isBinaryFile;
fSymbolMapping = new TreeMap<>(MAP_COMPARATOR);
fSymbolMapping.putAll(results);
fPid = pid;
}
@Override
public String getFullPath() {
return fFullPath;
}
@Override
public boolean isBinaryFile() {
return fIsBinaryFile;
}
private long getLastAddress() {
return fSymbolMapping.lastKey();
}
@Override
public @Nullable TmfResolvedSymbol getSymbolEntry(long address) {
Entry<Long, TmfResolvedSymbol> floorEntry = fSymbolMapping.floorEntry(address);
if (floorEntry == null) {
return null;
}
// See if the symbol returned is the end of a block or the last symbol. In this
// case, don't use the floor unless it hits the exact address
TmfResolvedSymbol symbol = Objects.requireNonNull(floorEntry.getValue());
long floorValue = symbol.getBaseAddress();
return ((symbol.getSymbolName().endsWith(getEndSuffix()) || floorValue == getLastAddress())
&& floorValue != address) ? null : symbol;
}
/**
* Get the suffix for symbols that mark the end of address blocks in the file
*
* @return The suffix for symbols that end blocks of mapping addresses
*/
private static String getEndSuffix() {
return DEFAULT_END_SUFFIX;
}
@Override
public int getPid() {
return fPid;
}
@Override
public int hashCode() {
return Objects.hash(fFullPath, fIsBinaryFile, fSymbolMapping);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
MappingFile other = (MappingFile) obj;
return (fFullPath.equals(other.fFullPath)) && (fIsBinaryFile == other.fIsBinaryFile) && (fSymbolMapping.equals(other.fSymbolMapping));
}
}