package com.oracle.objectfile.elf;
import static java.lang.Math.toIntExact;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
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.StringTable;
import com.oracle.objectfile.SymbolTable;
import com.oracle.objectfile.debuginfo.DebugInfoProvider;
import com.oracle.objectfile.elf.dwarf.DwarfARangesSectionImpl;
import com.oracle.objectfile.elf.dwarf.DwarfAbbrevSectionImpl;
import com.oracle.objectfile.elf.dwarf.DwarfFrameSectionImpl;
import com.oracle.objectfile.elf.dwarf.DwarfInfoSectionImpl;
import com.oracle.objectfile.elf.dwarf.DwarfLineSectionImpl;
import com.oracle.objectfile.elf.dwarf.DwarfDebugInfo;
import com.oracle.objectfile.elf.dwarf.DwarfStrSectionImpl;
import com.oracle.objectfile.io.AssemblyBuffer;
import com.oracle.objectfile.io.OutputAssembler;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
public class ELFObjectFile extends ObjectFile {
public static final int IDENT_LENGTH = 16;
public static final char[] IDENT_MAGIC = new char[]{0x7f, 'E', 'L', 'F'};
@SuppressWarnings("unused") private final ELFHeader ;
private final ELFStrtab shstrtab;
private final SectionHeaderTable sht;
protected ELFSection interp;
private ELFEncoding dataEncoding = ELFEncoding.getSystemNativeValue();
private char version;
private ELFOsAbi osabi = ELFOsAbi.getSystemNativeValue();
private char abiVersion;
private ELFClass fileClass = ELFClass.getSystemNativeValue();
private ELFMachine machine;
private long processorSpecificFlags;
private final boolean runtimeDebugInfoGeneration;
private ELFObjectFile(int pageSize, ELFMachine machine, boolean runtimeDebugInfoGeneration) {
super(pageSize);
this.runtimeDebugInfoGeneration = runtimeDebugInfoGeneration;
header = new ELFHeader("ELFHeader");
this.machine = machine;
shstrtab = new SectionHeaderStrtab();
sht = new SectionHeaderTable();
}
public ELFObjectFile(int pageSize, ELFMachine machine) {
this(pageSize, machine, false);
}
public ELFObjectFile(int pageSize) {
this(pageSize, false);
}
public ELFObjectFile(int pageSize, boolean runtimeDebugInfoGeneration) {
this(pageSize, ELFMachine.from(ImageSingletons.lookup(Platform.class).getArchitecture()), runtimeDebugInfoGeneration);
}
@Override
public Format getFormat() {
return Format.ELF;
}
public void setFileClass(ELFClass fileClass) {
this.fileClass = fileClass;
}
protected class extends ELFStrtab {
() {
super(ELFObjectFile.this, ".shstrtab", SectionType.STRTAB);
}
@Override
public boolean () {
return false;
}
{
addContentProvider(new Iterable<String>() {
@Override
public Iterator<String> () {
final Iterator<Section> underlyingIterator = elements.sectionsIterator();
return new Iterator<String>() {
@Override
public boolean () {
return underlyingIterator.hasNext();
}
@Override
public String () {
return underlyingIterator.next().getName();
}
@Override
public void () {
throw new UnsupportedOperationException();
}
};
}
});
}
}
@SuppressWarnings("unused")
private ELFSymtab getSymtab(boolean isDynamic) {
ELFSymtab symtab = (ELFSymtab) (isDynamic ? elementForName(".dynsym") : elementForName(".symtab"));
if (symtab == null) {
throw new IllegalStateException("no appropriate symtab");
}
return symtab;
}
@Override
protected ELFSymtab createSymbolTable() {
String name = ".symtab";
ELFSymtab symtab = (ELFSymtab) elementForName(".symtab");
if (symtab == null) {
symtab = new ELFSymtab(this, name, false);
}
return symtab;
}
@Override
public Symbol createDefinedSymbol(String name, Element baseSection, long position, int size, boolean isCode, boolean isGlobal) {
ELFSymtab symtab = createSymbolTable();
return symtab.newDefinedEntry(name, (Section) baseSection, position, size, isGlobal, isCode);
}
@Override
public Symbol createUndefinedSymbol(String name, int size, boolean isCode) {
ELFSymtab symtab = createSymbolTable();
return symtab.newUndefinedEntry(name, isCode);
}
@Override
protected Segment getOrCreateSegment(String maybeSegmentName, String sectionName, boolean writable, boolean executable) {
return null;
}
@Override
public ELFUserDefinedSection newUserDefinedSection(Segment segment, String name, int alignment, ElementImpl impl) {
ELFUserDefinedSection userDefined = new ELFUserDefinedSection(this, name, alignment, SectionType.PROGBITS, impl);
assert userDefined.getImpl() == impl;
if (segment != null) {
getOrCreateSegment(segment.getName(), name, true, false).add(userDefined);
}
if (impl != null) {
impl.setElement(userDefined);
}
return userDefined;
}
@Override
public ELFProgbitsSection newProgbitsSection(Segment segment, String name, int alignment, boolean writable, boolean executable, ProgbitsSectionImpl impl) {
EnumSet<ELFSectionFlag> flags = EnumSet.noneOf(ELFSectionFlag.class);
flags.add(ELFSectionFlag.ALLOC);
if (executable) {
flags.add(ELFSectionFlag.EXECINSTR);
}
if (writable) {
flags.add(ELFSectionFlag.WRITE);
}
ELFProgbitsSection progbits = new ELFProgbitsSection(this, name, alignment, impl, flags);
impl.setElement(progbits);
return progbits;
}
@Override
public ELFNobitsSection newNobitsSection(Segment segment, String name, NobitsSectionImpl impl) {
ELFNobitsSection nobits = new ELFNobitsSection(this, name, impl);
impl.setElement(nobits);
return nobits;
}
public ELFSection getSectionByIndex(int i) {
return (ELFSection) elements.get(elements.sectionIndexToElementIndex(i - 1));
}
public int getIndexForSection(ELFSection s) {
return elements.elementIndexToSectionIndex(elements.indexOf(s)) + 1;
}
@Override
protected boolean elementsCanSharePage(Element s1, Element s2, int off1, int off2) {
assert s1 instanceof ELFSection;
assert s2 instanceof ELFSection;
ELFSection es1 = (ELFSection) s1;
ELFSection es2 = (ELFSection) s2;
boolean flagsCompatible = ELFSectionFlag.flagSetAsIfSegmentFlags(es1.getFlags()).equals(ELFSectionFlag.flagSetAsIfSegmentFlags(es2.getFlags()));
return flagsCompatible && super.elementsCanSharePage(es1, es2, off1, off2);
}
public abstract class ELFSection extends ObjectFile.Section {
final SectionType type;
EnumSet<ELFSectionFlag> flags;
public ELFSection(String name, SectionType type) {
this(name, type, EnumSet.noneOf(ELFSectionFlag.class));
}
public ELFSection(String name, SectionType type, EnumSet<ELFSectionFlag> flags) {
this(name, getWordSizeInBytes(), type, flags, -1);
}
public ELFSection(String name, int alignment, SectionType type, EnumSet<ELFSectionFlag> flags, int sectionIndex) {
super(name, alignment, (sectionIndex == -1) ? -1 : elements.sectionIndexToElementIndex(sectionIndex - 1));
this.type = type;
this.flags = flags;
}
@Override
public ELFObjectFile getOwner() {
return ELFObjectFile.this;
}
public SectionType getType() {
return type;
}
@Override
public boolean isLoadable() {
if (getImpl() == this) {
return flags.contains(ELFSectionFlag.ALLOC);
}
boolean implIsLoadable = getImpl().isLoadable();
assert implIsLoadable == flags.contains(ELFSectionFlag.ALLOC);
return implIsLoadable;
}
@Override
public boolean isReferenceable() {
if (getImpl() == this) {
return isLoadable();
}
return getImpl().isReferenceable();
}
public ELFSection getLinkedSection() {
return null;
}
public long getLinkedInfo() {
return 0;
}
public int getEntrySize() {
return 0;
}
public EnumSet<ELFSectionFlag> getFlags() {
return flags;
}
public void setFlags(EnumSet<ELFSectionFlag> flags) {
this.flags = flags;
}
}
public enum ELFType {
NONE,
REL,
EXEC,
DYN,
CORE,
LOOS,
HIOS,
LOPROC,
HIPROC;
public short toShort() {
if (ordinal() < 5) {
return (short) ordinal();
} else {
switch (this) {
case LOOS:
return (short) 0xFE00;
case HIOS:
return (short) 0xFEFF;
case LOPROC:
return (short) 0xFF00;
case HIPROC:
return (short) 0xFFFF;
}
}
throw new IllegalStateException("should not reach here");
}
}
public enum ELFEncoding {
ELFDATA2LSB(1),
ELFDATA2MSB(2);
private final int value;
ELFEncoding(int value) {
this.value = value;
}
public byte value() {
return (byte) value;
}
public ByteOrder toByteOrder() {
return (this == ELFEncoding.ELFDATA2LSB) ? ByteOrder.LITTLE_ENDIAN : (this == ELFEncoding.ELFDATA2MSB) ? ByteOrder.BIG_ENDIAN : ByteOrder.nativeOrder();
}
public static ELFEncoding getSystemNativeValue() {
return ELFDATA2LSB;
}
}
public enum ELFOsAbi {
ELFOSABI_SYSV(0),
ELFOSABI_HPUX(1),
ELFOSABI_STANDALONE(255);
private final int value;
ELFOsAbi(int value) {
this.value = value;
}
public byte value() {
return (byte) value;
}
public static ELFOsAbi getSystemNativeValue() {
return ELFOSABI_SYSV;
}
}
public enum ELFClass {
ELFCLASS32(1),
ELFCLASS64(2);
private final int value;
ELFClass(int value) {
this.value = value;
}
public byte value() {
return (byte) value;
}
public static ELFClass getSystemNativeValue() {
return ELFCLASS64;
}
}
public class extends ObjectFile.Header {
class {
IdentStruct = new IdentStruct();
ELFType ;
ELFMachine ;
int ;
long ;
long ;
long ;
int ;
short ;
short ;
short ;
short ;
short ;
short ;
() {
ident = new IdentStruct();
type = ELFType.NONE;
machine = ELFMachine.NONE;
}
class {
public char[] = new char[4];
public ELFClass = ELFClass.getSystemNativeValue();
public ELFEncoding = ELFEncoding.getSystemNativeValue();
public char ;
public ELFOsAbi = ELFOsAbi.getSystemNativeValue();
public char ;
(char[] magic, ELFClass fileClass, ELFEncoding dataEncoding, char version, ELFOsAbi osabi, char abiVersion) {
this.magic = magic;
this.fileClass = fileClass;
this.dataEncoding = dataEncoding;
this.version = version;
this.osabi = osabi;
this.abiVersion = abiVersion;
}
() {
this.magic = Arrays.copyOf(IDENT_MAGIC, IDENT_MAGIC.length);
assert Arrays.equals(IDENT_MAGIC, magic);
}
void (OutputAssembler out) {
int pos = out.pos();
byte[] magicBlob = new byte[IDENT_MAGIC.length];
for (int i = 0; i < IDENT_MAGIC.length; ++i) {
magicBlob[i] = (byte) magic[i];
}
out.writeBlob(magicBlob);
out.writeByte(fileClass.value());
out.writeByte(dataEncoding.value());
out.writeByte((byte) version);
out.writeByte(osabi.value());
out.writeByte((byte) abiVersion);
int nWritten = out.pos() - pos;
for (int i = 0; i < IDENT_LENGTH - nWritten; ++i) {
out.writeByte((byte) 0);
}
}
@Override
public String () {
return String.format("ELF Ident:\n\t[class %s, encoding %s, version %d, OS/ABI %s, ABI version %d]", fileClass, dataEncoding, (int) version, osabi, (int) abiVersion);
}
}
public void (OutputAssembler out) {
ident.write(out);
out.write2Byte(type.toShort());
out.write2Byte(machine.toShort());
out.write4Byte(version);
switch (getFileClass()) {
case ELFCLASS32:
out.write4Byte(toIntExact(entry));
out.write4Byte(toIntExact(phoff));
out.write4Byte(toIntExact(shoff));
break;
case ELFCLASS64:
out.write8Byte(entry);
out.write8Byte(phoff);
out.write8Byte(shoff);
break;
default:
throw new RuntimeException(getFileClass().toString());
}
out.write4Byte(flags);
out.write2Byte(ehsize);
out.write2Byte(phentsize);
out.write2Byte(phnum);
out.write2Byte(shentsize);
out.write2Byte(shnum);
out.write2Byte(shstrndx);
}
public int () {
OutputAssembler oa = AssemblyBuffer.createOutputAssembler();
write(oa);
return oa.pos();
}
}
public (String name) {
super(name);
ELFObjectFile.this.version = 1;
ELFObjectFile.this.processorSpecificFlags = 0;
}
@Override
public Iterable<BuildDependency> (Map<Element, LayoutDecisionMap> decisions) {
HashSet<BuildDependency> dependencies = new HashSet<>();
LayoutDecision ourContent = decisions.get(this).getDecision(LayoutDecision.Kind.CONTENT);
LayoutDecision ourOffset = decisions.get(this).getDecision(LayoutDecision.Kind.OFFSET);
LayoutDecision ourSize = decisions.get(this).getDecision(LayoutDecision.Kind.SIZE);
LayoutDecision shtSize = decisions.get(sht).getDecision(LayoutDecision.Kind.SIZE);
LayoutDecision shtOffset = decisions.get(sht).getDecision(LayoutDecision.Kind.OFFSET);
dependencies.add(BuildDependency.createOrGet(ourOffset, ourSize));
dependencies.add(BuildDependency.createOrGet(ourContent, shtSize));
dependencies.add(BuildDependency.createOrGet(ourContent, shtOffset));
return dependencies;
}
@Override
public byte[] (Map<Element, LayoutDecisionMap> alreadyDecided, byte[] contentHint) {
OutputAssembler oa = AssemblyBuffer.createOutputAssembler(getDataEncoding().toByteOrder());
Struct contents = new Struct();
contents.ident.fileClass = getFileClass();
contents.ident.dataEncoding = getDataEncoding();
contents.ident.version = getVersion();
contents.ident.osabi = getOsAbi();
contents.ident.abiVersion = (char) getAbiVersion();
contents.type = getType();
contents.machine = getMachine();
contents.version = getVersion();
contents.entry = 0;
contents.shoff = (int) alreadyDecided.get(sht).getDecidedValue(LayoutDecision.Kind.OFFSET);
contents.flags = (int) getFlags();
contents.ehsize = (short) contents.getWrittenSize();
contents.shentsize = (short) (new SectionHeaderEntryStruct()).getWrittenSize();
int shtSize = (int) alreadyDecided.get(sht).getDecidedValue(LayoutDecision.Kind.SIZE);
assert shtSize % contents.shentsize == 0;
contents.shnum = (short) (shtSize / contents.shentsize);
Iterator<?> i = getSections().iterator();
short index = 1;
boolean sawShStrTab = false;
for (; i.hasNext(); ++index) {
if (i.next() == ELFObjectFile.this.shstrtab) {
sawShStrTab = true;
break;
}
}
contents.shstrndx = sawShStrTab ? index : 0;
contents.write(oa);
if (contentHint != null) {
}
return oa.getBlob();
}
@Override
public int (Map<Element, LayoutDecisionMap> alreadyDecided, int offsetHint) {
return 0;
}
@Override
public int (Map<Element, LayoutDecisionMap> alreadyDecided, int sizeHint) {
int size = (new Struct()).getWrittenSize();
assert sizeHint == -1 || sizeHint == size;
return size;
}
public short () {
return (short) ELFObjectFile.this.elements.sectionsCount();
}
public ELFType () {
return ELFType.REL;
}
}
public enum SectionType {
NULL,
PROGBITS,
SYMTAB,
STRTAB,
RELA,
HASH,
DYNAMIC,
NOTE,
NOBITS,
REL,
SHLIB,
DYNSYM,
LOOS,
HIOS,
LOPROC,
HIPROC;
public int toInt() {
if (ordinal() < 12) {
return ordinal();
} else {
switch (this) {
case LOOS:
return 0x60000000;
case HIOS:
return 0x6fffffff;
case LOPROC:
return 0x70000000;
case HIPROC:
return 0x7fffffff;
}
}
throw new IllegalStateException("should not reach here");
}
}
public enum SegmentType {
NULL,
LOAD,
DYNAMIC,
INTERP,
NOTE,
SHLIB,
PHDR,
TLS,
NUM;
}
public enum ELFSectionFlag implements ValueEnum {
WRITE(0x01),
ALLOC(0x2),
EXECINSTR(0x4),
MASKPROC(0xf0000000);
private final int value;
ELFSectionFlag(int value) {
this.value = value;
}
@Override
public long value() {
return value;
}
public static EnumSet<ELFSegmentFlag> flagSetAsIfSegmentFlags(EnumSet<ELFSectionFlag> flags) {
EnumSet<ELFSegmentFlag> out = EnumSet.of(ELFSegmentFlag.R);
if (flags.contains(ELFSectionFlag.WRITE)) {
out.add(ELFSegmentFlag.W);
}
if (flags.contains(ELFSectionFlag.EXECINSTR)) {
out.add(ELFSegmentFlag.X);
}
return out;
}
}
public enum ELFSegmentFlag {
X,
W,
R;
public static EnumSet<ELFSegmentFlag> flagSetFromLong(long flags) {
EnumSet<ELFSegmentFlag> working = EnumSet.noneOf(ELFSegmentFlag.class);
for (ELFSegmentFlag f : values()) {
if ((flags & (1 << (f.ordinal()))) != 0) {
working.add(f);
}
}
return working;
}
public static long flagSetToLong(EnumSet<ELFSegmentFlag> flags) {
long working = 0;
for (int i = 0; i < values().length; ++i) {
if (flags.contains(values()[i])) {
working |= (1 << i);
}
}
return working;
}
}
class implements Cloneable {
int ;
SectionType = SectionType.NULL;
long ;
long ;
long ;
long ;
int ;
int ;
long = 0L;
long ;
() {
}
private (int namePtr, SectionType type, long flags, long virtualAddress, long fileOffset, long sectionSize, int link, int info, long addrAlign, long entrySize) {
this.namePtr = namePtr;
assert type != null;
this.type = type;
this.flags = flags;
this.virtualAddress = virtualAddress;
this.fileOffset = fileOffset;
this.sectionSize = sectionSize;
this.link = link;
this.info = info;
this.addrAlign = addrAlign;
this.entrySize = entrySize;
}
@Override
public SectionHeaderEntryStruct () {
return new SectionHeaderEntryStruct(namePtr, type, flags, virtualAddress, fileOffset, sectionSize, link, info, addrAlign, entrySize);
}
private void (OutputAssembler db) {
switch (getFileClass()) {
case ELFCLASS32:
db.write4Byte(isNullEntry() ? 0 : namePtr);
db.write4Byte(type.toInt());
db.write4Byte(toIntExact(flags));
db.write4Byte(toIntExact(virtualAddress));
db.write4Byte(toIntExact(fileOffset));
db.write4Byte(toIntExact(sectionSize));
db.write4Byte(link);
db.write4Byte(info);
db.write4Byte(toIntExact(addrAlign));
db.write4Byte(toIntExact(entrySize));
break;
case ELFCLASS64:
db.write4Byte(isNullEntry() ? 0 : namePtr);
db.write4Byte(type.toInt());
db.write8Byte(flags);
db.write8Byte(virtualAddress);
db.write8Byte(fileOffset);
db.write8Byte(sectionSize);
db.write4Byte(link);
db.write4Byte(info);
db.write8Byte(addrAlign);
db.write8Byte(entrySize);
break;
default:
throw new RuntimeException(getFileClass().toString());
}
}
public int () {
OutputAssembler temp = AssemblyBuffer.createOutputAssembler(ByteOrder.nativeOrder());
write(temp);
return temp.pos();
}
@Override
public String () {
if (isNullEntry()) {
return "SHT NULL Entry";
}
return new StringBuilder("SHT Entry: ").
append(String.format("\n %s", type)).
append(String.format("\n flags %#x", flags)).
append(String.format("\n virtual address %#x", virtualAddress)).
append(String.format("\n offset %#x (%1$d), size %d", fileOffset, sectionSize)).
append(String.format("\n link %#x, info %#x, align %#x, entry size %#x (%4$d)", link, info, addrAlign, entrySize)).
append("\n").toString();
}
public boolean () {
return namePtr == 0 && type == SectionType.NULL && flags == 0L && virtualAddress == 0L &&
link == 0 && info == 0 && addrAlign == 0L && entrySize == 0L;
}
}
public class extends ObjectFile.Element {
@Override
public ElementImpl () {
return this;
}
@Override
public boolean () {
return false;
}
public () {
super("ELFSectionHeaderTable");
assert elements.sectionsCount() == 1;
}
@Override
public Iterable<BuildDependency> (Map<Element, LayoutDecisionMap> decisions) {
HashSet<BuildDependency> deps = ObjectFile.defaultDependencies(decisions, this);
LayoutDecision ourContent = decisions.get(this).getDecision(LayoutDecision.Kind.CONTENT);
deps.add(BuildDependency.createOrGet(ourContent, decisions.get(shstrtab).getDecision(LayoutDecision.Kind.SIZE)));
deps.add(BuildDependency.createOrGet(ourContent, decisions.get(shstrtab).getDecision(LayoutDecision.Kind.OFFSET)));
deps.add(BuildDependency.createOrGet(ourContent, decisions.get(shstrtab).getDecision(LayoutDecision.Kind.CONTENT)));
decisions.get(shstrtab).getDecision(LayoutDecision.Kind.OFFSET);
decisions.get(shstrtab).getDecision(LayoutDecision.Kind.CONTENT);
for (Element e : getElements()) {
if (e != this && e != shstrtab) {
deps.add(BuildDependency.createOrGet(ourContent, decisions.get(e).getDecision(LayoutDecision.Kind.OFFSET)));
deps.add(BuildDependency.createOrGet(ourContent, decisions.get(e).getDecision(LayoutDecision.Kind.SIZE)));
}
}
return deps;
}
@Override
public int (Map<Element, LayoutDecisionMap> alreadyDecided, int sizeHint) {
SectionHeaderEntryStruct s = new SectionHeaderEntryStruct();
OutputAssembler oa = AssemblyBuffer.createOutputAssembler(getDataEncoding().toByteOrder());
s.write(oa);
int entrySize = oa.pos();
return (elements.sectionsCount() + 1) * entrySize;
}
@Override
public byte[] (Map<Element, LayoutDecisionMap> alreadyDecided, byte[] contentHint) {
OutputAssembler oa = AssemblyBuffer.createOutputAssembler(getDataEncoding().toByteOrder());
write(oa, alreadyDecided);
if (contentHint != null) {
}
return oa.getBlob();
}
@Override
public LayoutDecisionMap (LayoutDecisionMap copyingIn) {
return defaultDecisions(this, copyingIn);
}
@Override
public int (Map<Element, LayoutDecisionMap> alreadyDecided, int offsetHint) {
return defaultGetOrDecideOffset(alreadyDecided, this, offsetHint);
}
@Override
public int (Map<Element, LayoutDecisionMap> alreadyDecided, int vaddrHint) {
return defaultGetOrDecideVaddr(alreadyDecided, this, vaddrHint);
}
public void (OutputAssembler out, Map<Element, LayoutDecisionMap> alreadyDecided) {
LayoutDecision shstrtabDecision = alreadyDecided.get(shstrtab).getDecision(LayoutDecision.Kind.CONTENT);
byte[] shstrtabContents = (byte[]) shstrtabDecision.getValue();
StringTable strings = new StringTable(shstrtabContents);
SectionHeaderEntryStruct ent = new SectionHeaderEntryStruct();
assert ent.isNullEntry();
ent.write(out);
HashMap<Section, Integer> sectionIndices = new HashMap<>();
Iterable<Section> sections = getSections();
Iterator<Section> iter = sections.iterator();
int currentSectionIndex = 0;
while (iter.hasNext()) {
++currentSectionIndex;
Section s = iter.next();
sectionIndices.put(s, currentSectionIndex);
assert getSectionByIndex(currentSectionIndex) == s;
}
assert elements.sectionsCount() == currentSectionIndex;
for (Section s : getSections()) {
ELFSection es = (ELFSection) s;
ent.namePtr = strings.indexFor(nameForElement(s));
ent.type = es.getType();
assert s.getImpl().isLoadable() == es.getFlags().contains(ELFSectionFlag.ALLOC);
ent.flags = ObjectFile.flagSetAsLong(es.getFlags());
ent.fileOffset = (int) alreadyDecided.get(es).getDecidedValue(LayoutDecision.Kind.OFFSET);
if (es.getFlags().contains(ELFSectionFlag.ALLOC) && runtimeDebugInfoGeneration) {
ent.virtualAddress = (int) alreadyDecided.get(es).getDecidedValue(LayoutDecision.Kind.VADDR);
} else {
ent.virtualAddress = 0L;
}
ent.sectionSize = (int) alreadyDecided.get(es).getDecidedValue(LayoutDecision.Kind.SIZE);
if (ent.sectionSize == 0) {
ent.sectionSize = es.getMemSize(alreadyDecided);
}
Section linkedSection = es.getLinkedSection();
ent.link = (linkedSection == null) ? 0 : sectionIndices.get(linkedSection);
ent.info = (int) es.getLinkedInfo();
ent.addrAlign = es.getAlignment();
ent.entrySize = es.getEntrySize();
ent.write(out);
}
}
}
@Override
public Set<Segment> getSegments() {
return new HashSet<>();
}
public ELFEncoding getDataEncoding() {
return dataEncoding;
}
@Override
public ByteOrder getByteOrder() {
return getDataEncoding().toByteOrder();
}
@Override
public void setByteOrder(ByteOrder byteOrder) {
dataEncoding = byteOrder == ByteOrder.LITTLE_ENDIAN ? ELFEncoding.ELFDATA2LSB : ELFEncoding.ELFDATA2MSB;
}
public char getVersion() {
return version;
}
public ELFOsAbi getOsAbi() {
return osabi;
}
public int getAbiVersion() {
return abiVersion;
}
public ELFClass getFileClass() {
return fileClass;
}
@Override
public int getWordSizeInBytes() {
return fileClass == ELFClass.ELFCLASS64 ? 8 : 4;
}
@Override
public boolean shouldRecordDebugRelocations() {
return true;
}
public ELFMachine getMachine() {
return machine;
}
public void setMachine(ELFMachine machine) {
this.machine = machine;
}
public long getFlags() {
return processorSpecificFlags;
}
@SuppressWarnings("unused")
public ELFRelocationSection getOrCreateDynamicRelocSection(ELFSymtab syms, boolean withExplicitAddends) {
throw new AssertionError("can't create dynamic relocations in this kind of ELF file");
}
public ELFRelocationSection getOrCreateRelocSection(ELFUserDefinedSection elfUserDefinedSection, ELFSymtab syms, boolean withExplicitAddends) {
String nameStem = withExplicitAddends ? ".rela" : ".rel";
String name = nameStem + elfUserDefinedSection.getName();
Element el = elementForName(name);
ELFRelocationSection rs;
if (el == null) {
rs = new ELFRelocationSection(this, name, elfUserDefinedSection, syms, withExplicitAddends);
} else if (el instanceof ELFRelocationSection) {
rs = (ELFRelocationSection) el;
} else {
throw new IllegalStateException(name + " section exists but is not an ELFRelocationSection");
}
return rs;
}
@Override
public SymbolTable getSymbolTable() {
return (SymbolTable) elementForName(".symtab");
}
@Override
protected int getMinimumFileSize() {
return 0;
}
@Override
public void installDebugInfo(DebugInfoProvider debugInfoProvider) {
DwarfDebugInfo dwarfSections = new DwarfDebugInfo(getMachine(), getByteOrder());
DwarfStrSectionImpl elfStrSectionImpl = dwarfSections.getStrSectionImpl();
DwarfAbbrevSectionImpl elfAbbrevSectionImpl = dwarfSections.getAbbrevSectionImpl();
DwarfFrameSectionImpl frameSectionImpl = dwarfSections.getFrameSectionImpl();
DwarfInfoSectionImpl elfInfoSectionImpl = dwarfSections.getInfoSectionImpl();
DwarfARangesSectionImpl elfARangesSectionImpl = dwarfSections.getARangesSectionImpl();
DwarfLineSectionImpl elfLineSectionImpl = dwarfSections.getLineSectionImpl();
newUserDefinedSection(elfStrSectionImpl.getSectionName(), elfStrSectionImpl);
newUserDefinedSection(elfAbbrevSectionImpl.getSectionName(), elfAbbrevSectionImpl);
newUserDefinedSection(frameSectionImpl.getSectionName(), frameSectionImpl);
newUserDefinedSection(elfInfoSectionImpl.getSectionName(), elfInfoSectionImpl);
newUserDefinedSection(elfARangesSectionImpl.getSectionName(), elfARangesSectionImpl);
newUserDefinedSection(elfLineSectionImpl.getSectionName(), elfLineSectionImpl);
elfStrSectionImpl.getOrCreateRelocationElement(false);
elfAbbrevSectionImpl.getOrCreateRelocationElement(false);
frameSectionImpl.getOrCreateRelocationElement(false);
elfInfoSectionImpl.getOrCreateRelocationElement(false);
elfARangesSectionImpl.getOrCreateRelocationElement(false);
elfLineSectionImpl.getOrCreateRelocationElement(false);
dwarfSections.installDebugInfo(debugInfoProvider);
}
}