package com.oracle.objectfile.macho;
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.LayoutDecision;
import com.oracle.objectfile.LayoutDecisionMap;
import com.oracle.objectfile.ObjectFile;
import com.oracle.objectfile.ObjectFile.Element;
import com.oracle.objectfile.ObjectFile.RelocationKind;
import com.oracle.objectfile.ObjectFile.RelocationRecord;
import com.oracle.objectfile.ObjectFile.Segment;
import com.oracle.objectfile.ObjectFile.Symbol;
import com.oracle.objectfile.io.AssemblyBuffer;
import com.oracle.objectfile.macho.MachOObjectFile.MachOSection;
import com.oracle.objectfile.macho.MachOObjectFile.SectionFlag;
import com.oracle.objectfile.macho.MachOObjectFile.SectionType;
import com.oracle.objectfile.macho.MachOObjectFile.Segment64Command;
public class MachOUserDefinedSection extends MachOSection implements ObjectFile.RelocatableSectionImpl {
protected ElementImpl impl;
@Override
public ElementImpl getImpl() {
return impl;
}
MachOUserDefinedSection(MachOObjectFile owner, String name, int alignment, Segment64Command segment, SectionType type, ElementImpl impl) {
this(owner, name, alignment, segment, type, impl, EnumSet.noneOf(SectionFlag.class));
this.impl = impl;
}
MachOUserDefinedSection(MachOObjectFile owner, String name, int alignment, Segment64Command segment, SectionType type, ElementImpl impl, EnumSet<SectionFlag> flags) {
owner.super(name, alignment, segment, type, flags);
this.impl = impl;
}
public void setImpl(ElementImpl impl) {
this.impl = impl;
}
@Override
public Iterable<BuildDependency> getDependencies(Map<Element, LayoutDecisionMap> decisions) {
return impl.getDependencies(decisions);
}
@Override
public int getOrDecideOffset(Map<Element, LayoutDecisionMap> alreadyDecided, int offsetHint) {
int implOffset = impl.getOrDecideOffset(alreadyDecided, offsetHint);
Segment ourSegment = getSegment();
Segment prevSegment = null;
Segment firstSegment = getOwner().getSegments().iterator().next();
for (Segment s : getOwner().getSegments()) {
if (s == ourSegment) {
break;
}
prevSegment = s;
}
if (getSegment().get(0) == this && prevSegment != null && prevSegment.getName().equals("__TEXT")) {
assert prevSegment == firstSegment;
if (implOffset < getOwner().getPageSize()) {
return ObjectFile.nextIntegerMultipleWithCongruence(getOwner().getPageSize(), impl.getAlignment(), implOffset, getOwner().getPageSize());
}
} else if (getSegment().get(0) == this && ourSegment == firstSegment) {
if (implOffset < getOwner().getPageSize()) {
return getOwner().getPageSize();
}
}
return implOffset;
}
@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) {
int implVaddr = impl.getOrDecideVaddr(alreadyDecided, vaddrHint);
Object offsetObj = alreadyDecided.get(this).getDecidedValue(LayoutDecision.Kind.OFFSET);
assert offsetObj != null;
assert offsetObj instanceof Integer;
if (getSegment() == getOwner().getSegments().iterator().next() && getSegment().get(0) == this) {
if (implVaddr < getOwner().getPageSize()) {
return ObjectFile.nextIntegerMultipleWithCongruence(getOwner().getPageSize(), impl.getAlignment(), (int) offsetObj, getOwner().getPageSize());
}
}
return implVaddr;
}
@Override
public int getMemSize(Map<Element, LayoutDecisionMap> alreadyDecided) {
return impl.getMemSize(alreadyDecided);
}
@Override
public LayoutDecisionMap getDecisions(LayoutDecisionMap copyingIn) {
return impl.getDecisions(copyingIn);
}
@Override
public MachORelocationElement getOrCreateRelocationElement(boolean useImplicitAddend) {
return getOwner().getOrCreateRelocationElement(useImplicitAddend);
}
@Override
public RelocationRecord markRelocationSite(int offset, ByteBuffer bb, RelocationKind k, String symbolName, boolean useImplicitAddend, Long explicitAddend) {
MachORelocationElement el = getOrCreateRelocationElement(useImplicitAddend);
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 (RelocationKind.isPCRelative(k)) {
desiredInlineAddendValue += length;
}
sbb.seek(offset);
sbb.writeTruncatedLong(desiredInlineAddendValue, length);
assert symbolName != null;
Symbol sym = getOwner().getSymbolTable().getSymbol(symbolName);
boolean symbolIsDefinedLocally = (sym != null && sym.isDefined());
boolean createAsLocalReloc = false;
assert !createAsLocalReloc || symbolIsDefinedLocally;
flags.add(createAsLocalReloc ? SectionFlag.LOC_RELOC : SectionFlag.EXT_RELOC);
sbb.pop();
RelocationInfo rec = new RelocationInfo(el, this, offset, length, k, symbolName, createAsLocalReloc);
el.add(rec);
return rec;
}
}