package com.oracle.objectfile.pecoff;
import java.nio.ByteBuffer;
import java.util.EnumSet;
import java.util.Map;
import com.oracle.objectfile.BuildDependency;
import com.oracle.objectfile.ElementImpl;
import com.oracle.objectfile.LayoutDecisionMap;
import com.oracle.objectfile.ObjectFile;
import com.oracle.objectfile.ObjectFile.Element;
import com.oracle.objectfile.ObjectFile.RelocationRecord;
import com.oracle.objectfile.io.AssemblyBuffer;
import com.oracle.objectfile.pecoff.PECoffObjectFile.PECoffSection;
import com.oracle.objectfile.pecoff.PECoffObjectFile.PECoffSectionFlag;
public class PECoffUserDefinedSection extends PECoffSection implements ObjectFile.RelocatableSectionImpl {
private PECoffRelocationTable rel;
private PECoffRelocationTable rela;
protected ElementImpl impl;
@Override
public ElementImpl getImpl() {
return impl;
}
PECoffUserDefinedSection(PECoffObjectFile owner, String name, int alignment, ElementImpl impl) {
this(owner, name, alignment, impl, EnumSet.noneOf(PECoffSectionFlag.class));
}
PECoffUserDefinedSection(PECoffObjectFile owner, String name, int alignment, ElementImpl impl, EnumSet<PECoffSectionFlag> flags) {
this(owner, name, alignment, impl, flags, -1);
}
PECoffUserDefinedSection(PECoffObjectFile owner, String name, int alignment, ElementImpl impl, EnumSet<PECoffSectionFlag> flags, int sectionIndex) {
owner.super(name, alignment, flags, sectionIndex);
this.impl = impl;
}
public void setImpl(ElementImpl impl) {
assert impl == null;
this.impl = impl;
if (impl.isLoadable()) {
flags.add(PECoffSectionFlag.READ);
} else {
flags.remove(PECoffSectionFlag.READ);
}
}
@Override
public Iterable<BuildDependency> getDependencies(Map<Element, LayoutDecisionMap> decisions) {
return impl.getDependencies(decisions);
}
@Override
public int getOrDecideOffset(Map<Element, LayoutDecisionMap> alreadyDecided, int offsetHint) {
return impl.getOrDecideOffset(alreadyDecided, offsetHint);
}
@Override
public int getOrDecideSize(Map<Element, LayoutDecisionMap> alreadyDecided, int sizeHint) {
return impl.getOrDecideSize(alreadyDecided, sizeHint);
}
@Override
public byte[] getOrDecideContent(Map<Element, LayoutDecisionMap> alreadyDecided, byte[] contentHint) {
return impl.getOrDecideContent(alreadyDecided, contentHint);
}
@Override
public int getOrDecideVaddr(Map<Element, LayoutDecisionMap> alreadyDecided, int vaddrHint) {
return impl.getOrDecideVaddr(alreadyDecided, vaddrHint);
}
@Override
public int getMemSize(Map<Element, LayoutDecisionMap> alreadyDecided) {
return impl.getMemSize(alreadyDecided);
}
@Override
public LayoutDecisionMap getDecisions(LayoutDecisionMap copyingIn) {
return impl.getDecisions(copyingIn);
}
@Override
public Element getOrCreateRelocationElement(boolean useImplicitAddend) {
PECoffSymtab syms = (PECoffSymtab) getOwner().elementForName(".symtab");
if (syms == null) {
throw new IllegalStateException("cannot create a relocation section without corresponding symtab");
}
boolean withExplicitAddends = !useImplicitAddend;
PECoffRelocationTable rs = withExplicitAddends ? rela : rel;
if (rs == null) {
rs = getOwner().getOrCreateRelocSection(syms, withExplicitAddends);
assert rs != null;
if (withExplicitAddends) {
rela = rs;
} else {
rel = rs;
}
}
return rs;
}
@Override
public RelocationRecord markRelocationSite(int offset, ByteBuffer bb, ObjectFile.RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) {
if (useImplicitAddend != (explicitAddend == null)) {
throw new IllegalArgumentException("must have either an explicit or implicit addend");
}
PECoffSymtab syms = (PECoffSymtab) getOwner().elementForName(".symtab");
PECoffRelocationTable rs = (PECoffRelocationTable) getOrCreateRelocationElement(useImplicitAddend);
assert symbolName != null;
PECoffSymtab.Entry ent = syms.getSymbol(symbolName);
assert ent != null;
AssemblyBuffer sbb = new AssemblyBuffer(bb);
sbb.setByteOrder(getOwner().getByteOrder());
sbb.pushSeek(offset);
int length = ObjectFile.RelocationKind.getRelocationSize(k);
long currentInlineAddendValue = sbb.readTruncatedLong(length);
long desiredInlineAddendValue;
if (explicitAddend != null) {
assert currentInlineAddendValue == 0;
desiredInlineAddendValue = explicitAddend;
} else {
desiredInlineAddendValue = currentInlineAddendValue;
}
if (ObjectFile.RelocationKind.isPCRelative(k)) {
desiredInlineAddendValue += length;
}
sbb.seek(offset);
sbb.writeTruncatedLong(desiredInlineAddendValue, length);
sbb.pop();
return rs.addEntry(this, offset, PECoffMachine.getRelocation(getOwner().getMachine(), k), ent, explicitAddend);
}
}