/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.objectfile.elf;
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.elf.ELFObjectFile.ELFSection;
import com.oracle.objectfile.elf.ELFObjectFile.ELFSectionFlag;
import com.oracle.objectfile.elf.ELFObjectFile.SectionType;
Clients defining their own kinds of section typically want to do so in a way that is agnostic
w.r.t. ELF, Mach-O or other object file formats. "User-defined section" means a section whose
implementation delegates to an ElementImpl implementation. By implementing this interface,
clients can breaks out of the ELF/Mach-O class hierarchy and implement common functionality (e.g.
DWARF debugging sections) in a format-agnostic way. ELFUserDefinedSection is the glue layer that
forwards calls to the ElementImpl.
TODO: details like flags and segment membership are somewhat format-specific. These need to be
specifiable by the client, in a format-agnostic way.
TODO: treatment of alignment needs to be squared with ELF-specific logic. I have removed the
getAlignment() / setAlignment() methods for now (even from ElementImpl).
TODO: default implementations of many ElementImpl can be factored out of existing code in
ELFSection and/or ObjectFile.{Section,Element}. In particular,
/**
* Clients defining their own kinds of section typically want to do so in a way that is agnostic
* w.r.t. ELF, Mach-O or other object file formats. "User-defined section" means a section whose
* implementation delegates to an ElementImpl implementation. By implementing this interface,
* clients can breaks out of the ELF/Mach-O class hierarchy and implement common functionality (e.g.
* DWARF debugging sections) in a format-agnostic way. ELFUserDefinedSection is the glue layer that
* forwards calls to the ElementImpl.
*
* TODO: details like flags and segment membership are somewhat format-specific. These need to be
* specifiable by the client, in a format-agnostic way.
*
* TODO: treatment of alignment needs to be squared with ELF-specific logic. I have removed the
* getAlignment() / setAlignment() methods for now (even from ElementImpl).
*
* TODO: default implementations of many ElementImpl can be factored out of existing code in
* ELFSection and/or ObjectFile.{Section,Element}. In particular,
*/
public class ELFUserDefinedSection extends ELFSection implements ObjectFile.RelocatableSectionImpl {
private ELFRelocationSection rel; // the section holding our relocations without addends
private ELFRelocationSection rela; // the section holding our relocations with addends
protected ElementImpl impl;
@Override
public ElementImpl getImpl() {
return impl;
}
ELFUserDefinedSection(ELFObjectFile owner, String name, int alignment, SectionType type, ElementImpl impl) {
this(owner, name, alignment, type, impl, EnumSet.noneOf(ELFSectionFlag.class));
}
ELFUserDefinedSection(ELFObjectFile owner, String name, int alignment, SectionType type, ElementImpl impl, EnumSet<ELFSectionFlag> flags) {
this(owner, name, alignment, type, impl, flags, -1);
}
ELFUserDefinedSection(ELFObjectFile owner, String name, int alignment, SectionType type, ElementImpl impl, EnumSet<ELFSectionFlag> flags, int sectionIndex) {
owner.super(name, alignment, type, flags, sectionIndex);
this.impl = impl;
}
public void setImpl(ElementImpl impl) {
assert impl == null;
this.impl = impl;
if (impl.isLoadable()) {
flags.add(ELFSectionFlag.ALLOC);
} else {
flags.remove(ELFSectionFlag.ALLOC);
}
}
@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) {
ELFSymtab syms = (ELFSymtab) getOwner().elementForName(".symtab");
if (syms == null) {
throw new IllegalStateException("cannot create a relocation section without corresponding symtab");
}
boolean withExplicitAddends = !useImplicitAddend;
ELFRelocationSection rs = withExplicitAddends ? rela : rel;
if (rs == null) {
// we have to create the section if it doesn't exist
rs = getOwner().getOrCreateRelocSection(this, 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");
}
ELFSymtab syms = (ELFSymtab) getOwner().elementForName(".symtab");
ELFRelocationSection rs = (ELFRelocationSection) getOrCreateRelocationElement(useImplicitAddend);
assert symbolName != null;
ELFSymtab.Entry ent = syms.getSymbol(symbolName);
assert ent != null;
return rs.addEntry(this, offset, ELFMachine.getRelocation(getOwner().getMachine(), k), ent, explicitAddend);
}
}