Skip to content

Commit

Permalink
Merge pull request #1580 from matthiasblaesing/elf_without_section_he…
Browse files Browse the repository at this point in the history
…ader_table

Handle ELF binaries without section header table
  • Loading branch information
matthiasblaesing committed Jan 2, 2024
2 parents eda004a + ab99f2e commit 1dd63c8
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 17 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Expand Up @@ -11,7 +11,7 @@ Features

Bug Fixes
---------

* [#1579](https://github.com/java-native-access/jna/issues/1579): Fix analysis of ELF binary on arm systems running with a java ELF binary without section table headers (java8 on armv7 NAS) - [@matthiasblaesing](https://github.com/matthiasblaesing).

Release 5.14.0
==============
Expand Down
94 changes: 78 additions & 16 deletions src/com/sun/jna/ELFAnalyser.java
Expand Up @@ -62,6 +62,18 @@ class ELFAnalyser {
private static final int EI_DATA_BIG_ENDIAN = 2;
private static final int E_MACHINE_ARM = 0x28;
private static final int EI_CLASS_64BIT = 2;
/**
* An undefined, missing, irrelevant, or otherwise meaningless section
* reference. For example, a symbol defined relative to section number
* SHN_UNDEF is an undefined symbol.
*/
private static final int SHN_UNDEF = 0;
/**
* An escape value indicating that the actual section header index is too
* large to fit in the containing field. The header section index is found
* in another location specific to the structure where it appears.
*/
private static final int SHN_XINDEX = 0xffff;

public static ELFAnalyser analyse(String filename) throws IOException {
ELFAnalyser res = new ELFAnalyser(filename);
Expand Down Expand Up @@ -203,7 +215,7 @@ private void parseEabiAapcsVfp(ByteBuffer headerData, RandomAccessFile raf) thro

for (ELFSectionHeaderEntry eshe : sectionHeaders.getEntries()) {
if(".ARM.attributes".equals(eshe.getName())) {
ByteBuffer armAttributesBuffer = ByteBuffer.allocate(eshe.getSize());
ByteBuffer armAttributesBuffer = ByteBuffer.allocate((int) eshe.getSize());
armAttributesBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
raf.getChannel().read(armAttributesBuffer, eshe.getOffset());
armAttributesBuffer.rewind();
Expand Down Expand Up @@ -236,7 +248,8 @@ public ELFSectionHeaders(boolean _64bit, boolean bigEndian, ByteBuffer headerDat
long shoff;
int shentsize;
int shnum;
short shstrndx;
int shstrndx;
int sectionCount;
if (_64bit) {
shoff = headerData.getLong(0x28);
shentsize = headerData.getShort(0x3A);
Expand All @@ -249,7 +262,27 @@ public ELFSectionHeaders(boolean _64bit, boolean bigEndian, ByteBuffer headerDat
shstrndx = headerData.getShort(0x32);
}

int tableLength = shnum * shentsize;
ByteBuffer sectionBuffer = ByteBuffer.allocate(shentsize);
raf.getChannel().read(sectionBuffer, shoff);
ELFSectionHeaderEntry section0 = new ELFSectionHeaderEntry(_64bit, sectionBuffer);

if (shnum == 0 && shoff != 0) {
sectionCount = (int) section0.getSize();
} else {
sectionCount = shnum;
}

if (shstrndx == SHN_XINDEX) {
shstrndx = section0.getLink();
}

int tableLength = sectionCount * shentsize;

if (tableLength == 0 || shstrndx == SHN_UNDEF) {
// There is either no section header table or no section name
// string table.
return;
}

ByteBuffer data = ByteBuffer.allocate(tableLength);
data.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
Expand All @@ -264,7 +297,7 @@ public ELFSectionHeaders(boolean _64bit, boolean bigEndian, ByteBuffer headerDat
}

ELFSectionHeaderEntry stringTable = entries.get(shstrndx);
ByteBuffer stringBuffer = ByteBuffer.allocate(stringTable.getSize());
ByteBuffer stringBuffer = ByteBuffer.allocate((int) stringTable.getSize());
stringBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
raf.getChannel().read(stringBuffer, stringTable.getOffset());
stringBuffer.rewind();
Expand Down Expand Up @@ -297,16 +330,20 @@ static class ELFSectionHeaderEntry {
private final int nameOffset;
private String name;
private final int type;
private final int flags;
private final int offset;
private final int size;
private final long flags;
private final long addr;
private final long offset;
private final long size;
private final int link;

public ELFSectionHeaderEntry(boolean _64bit, ByteBuffer sectionHeaderData) {
this.nameOffset = sectionHeaderData.getInt(0x0);
this.type = sectionHeaderData.getInt(0x4);
this.flags = (int) (_64bit ? sectionHeaderData.getLong(0x8) : sectionHeaderData.getInt(0x8));
this.offset = (int) (_64bit ? sectionHeaderData.getLong(0x18) : sectionHeaderData.getInt(0x10));
this.size = (int) (_64bit ? sectionHeaderData.getLong(0x20) : sectionHeaderData.getInt(0x14));
this.nameOffset = sectionHeaderData.getInt(0);
this.type = sectionHeaderData.getInt(4);
this.flags = _64bit ? sectionHeaderData.getLong(8) : sectionHeaderData.getInt(8);
this.addr = _64bit ? sectionHeaderData.getLong(16) : sectionHeaderData.getInt(12);
this.offset = _64bit ? sectionHeaderData.getLong(24) : sectionHeaderData.getInt(16);
this.size = _64bit ? sectionHeaderData.getLong(32) : sectionHeaderData.getInt(20);
this.link = sectionHeaderData.getInt(_64bit ? 40 : 24);
}

public String getName() {
Expand All @@ -325,21 +362,46 @@ public int getType() {
return type;
}

public int getFlags() {
public long getFlags() {
return flags;
}

public int getOffset() {
public long getOffset() {
return offset;
}

public int getSize() {
public long getSize() {
return size;
}

public long getAddr() {
return addr;
}

public int getLink() {
return link;
}

@Override
public String toString() {
return "ELFSectionHeaderEntry{" + "nameIdx=" + nameOffset + ", name=" + name + ", type=" + type + ", flags=" + flags + ", offset=" + offset + ", size=" + size + '}';
return String.format("ELFSectionHeaderEntry{"
+ "nameOffset=%1$d (0x%1$x)"
+ ", name=%2$s"
+ ", type=%3$d (0x%3$x)"
+ ", flags=%4$d (0x%4$x)"
+ ", addr=%5$d (0x%5$x)"
+ ", offset=%6$d (0x%6$x)"
+ ", size=%7$d (0x%7$x)"
+ ", link=%8$d (0x%8$x)}",
nameOffset,
name,
type,
flags,
addr,
offset,
size,
link
);
}
}

Expand Down

0 comments on commit 1dd63c8

Please sign in to comment.