├── .github
└── workflows
│ └── gradle.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
├── main
└── java
│ └── net
│ └── fornwall
│ └── jelf
│ ├── BackingFile.java
│ ├── ByteArrayAsFile.java
│ ├── ElfDynamicSection.java
│ ├── ElfException.java
│ ├── ElfFile.java
│ ├── ElfGnuHashTable.java
│ ├── ElfHashTable.java
│ ├── ElfNoteSection.java
│ ├── ElfParser.java
│ ├── ElfRelocation.java
│ ├── ElfRelocationAddend.java
│ ├── ElfRelocationAddendSection.java
│ ├── ElfRelocationSection.java
│ ├── ElfRelocationTypes.java
│ ├── ElfSection.java
│ ├── ElfSectionHeader.java
│ ├── ElfSegment.java
│ ├── ElfStringTable.java
│ ├── ElfSymbol.java
│ ├── ElfSymbolTableSection.java
│ ├── MappedFile.java
│ └── MemoizedObject.java
└── test
├── java
└── net
│ └── fornwall
│ └── jelf
│ ├── BasicTest.java
│ ├── ElfGnuHashTableTest.java
│ ├── ElfHashTableTest.java
│ ├── EndianProblemTest.java
│ ├── ReadmeTest.java
│ └── TestHelper.java
└── resources
├── .swp
├── android_arm_libncurses
├── android_arm_tset
├── linux_amd64_bindash
├── little-endian-test
├── objectFile-64.o
├── objectFile.o
└── usr-bin-yes
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | strategy:
11 | matrix:
12 | java: [8, 11, 17]
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 | - name: Set up JDK ${{ matrix.java }}
17 | uses: actions/setup-java@v3
18 | with:
19 | distribution: 'zulu'
20 | java-version: ${{ matrix.java }}
21 | - name: Build with Gradle
22 | run: ./gradlew build
23 |
24 | actionlint:
25 | runs-on: ubuntu-latest
26 | steps:
27 | - uses: actions/checkout@v3
28 | - name: Download actionlint
29 | id: get_actionlint
30 | run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
31 | - name: Check workflow files
32 | run: ${{ steps.get_actionlint.outputs.executable }} -color
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Intellij project files
2 | *.iml
3 | *.ipr
4 | *.iws
5 | .idea/
6 |
7 | #Gradle
8 | .gradletasknamecache
9 | .gradle/
10 | build/
11 | bin/
12 | gradle.properties
13 |
14 | # Eclipse
15 | .classpath
16 | .project
17 | .settings
18 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## v0.9.0 (2023-07-30)
4 | - Make BackingData public and add ElfFile.from(BackingData). [#20](https://github.com/fornwall/jelf/pull/20)
5 |
6 | ## v0.8.0 (2023-07-21)
7 | - Add a `getData` method to `ElfSection` for getting the bytes of an ELF section. [#17](https://github.com/fornwall/jelf/issues/17)
8 | - Make the `getSymbol` and `getSymbolIndex` methods in `ElfRelocation` respect `EI_CLASS`. [#18](https://github.com/fornwall/jelf/issues/18)
9 | - Fix `getELFSymbol(symbolName)` not working in certain cases. [#19](https://github.com/fornwall/jelf/issues/19)
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-2020 Fredrik Fornwall.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JElf
2 | Java library for parsing [Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) files.
3 |
4 | [](https://github.com/fornwall/jelf/actions?query=workflow%3A%22Java+CI%22)
5 | [](LICENSE.txt)
6 | [](https://search.maven.org/artifact/net.fornwall/jelf/)
7 | [](https://www.javadoc.io/doc/net.fornwall/jelf)
8 |
9 | ## Adding JElf to your build
10 |
11 | JElf's Maven group ID is `net.fornwall` and its artifact ID is `jelf`.
12 |
13 | To add a dependency on JElf using Maven, use the following:
14 |
15 | ```xml
16 |
9 | * Given an {@link ElfFile}, use {@link ElfFile#getDynamicSection()} to obtain the dynamic section for it if one exists, 10 | * which it only does if the ELF file is an object file participating in dynamic linking. 11 | *
12 | * This dynamic linking section contains a list of {@link ElfDynamicStructure}:s. 13 | *
14 | * Name Value d_un Executable Shared Object 15 | * ---------------------------------------------------------------------- 16 | * DT_NULL 0 ignored mandatory mandatory 17 | * DT_NEEDED 1 d_val optional optional 18 | * DT_PLTRELSZ 2 d_val optional optional 19 | * DT_PLTGOT 3 d_ptr optional optional 20 | * DT_HASH 4 d_ptr mandatory mandatory 21 | * DT_STRTAB 5 d_ptr mandatory mandatory 22 | * DT_SYMTAB 6 d_ptr mandatory mandatory 23 | * DT_RELA 7 d_ptr mandatory optional 24 | * DT_RELASZ 8 d_val mandatory optional 25 | * DT_RELAENT 9 d_val mandatory optional 26 | * DT_STRSZ 10 d_val mandatory mandatory 27 | * DT_SYMENT 11 d_val mandatory mandatory 28 | * DT_INIT 12 d_ptr optional optional 29 | * DT_FINI 13 d_ptr optional optional 30 | * DT_SONAME 14 d_val ignored optional 31 | * DT_RPATH* 15 d_val optional ignored 32 | * DT_SYMBOLIC* 16 ignored ignored optional 33 | * DT_REL 17 d_ptr mandatory optional 34 | * DT_RELSZ 18 d_val mandatory optional 35 | * DT_RELENT 19 d_val mandatory optional 36 | * DT_PLTREL 20 d_val optional optional 37 | * DT_DEBUG 21 d_ptr optional ignored 38 | * DT_TEXTREL* 22 ignored optional optional 39 | * DT_JMPREL 23 d_ptr optional optional 40 | * DT_BIND_NOW* 24 ignored optional optional 41 | * DT_INIT_ARRAY 25 d_ptr optional optional 42 | * DT_FINI_ARRAY 26 d_ptr optional optional 43 | * DT_INIT_ARRAYSZ 27 d_val optional optional 44 | * DT_FINI_ARRAYSZ 28 d_val optional optional 45 | * DT_RUNPATH 29 d_val optional optional 46 | * DT_FLAGS 30 d_val optional optional 47 | * DT_ENCODING 32 unspecified unspecified unspecified 48 | * DT_PREINIT_ARRAY 32 d_ptr optional ignored 49 | * DT_PREINIT_ARRAYSZ 33 d_val optional ignored 50 | * DT_LOOS 0x6000000D unspecified unspecified unspecified 51 | * DT_HIOS 0x6ffff000 unspecified unspecified unspecified 52 | * DT_LOPROC 0x70000000 unspecified unspecified unspecified 53 | * DT_HIPROC 0x7fffffff unspecified unspecified unspecified 54 | * "*" Signifies an entry that is at level 2. 55 | *56 | *
57 | * Read more about dynamic sections at Dynamic Section. 58 | */ 59 | public class ElfDynamicSection extends ElfSection { 60 | 61 | /** 62 | * An entry with a DT_NULL tag marks the end of the _DYNAMIC array. 63 | */ 64 | public static final int DT_NULL = 0; 65 | /** 66 | * This element holds the string table offset of a null-terminated string, giving the 67 | * name of a needed library. The offset is an index into the table recorded in the 68 | * {@link #DT_STRTAB} code. 69 | *
70 | * See Shared Object Dependencies for more information about these names. 71 | *
72 | * The dynamic array may contain multiple entries with this type. 73 | *
74 | * These entries' relative order is significant, though their relation to entries of other types is not.
75 | */
76 | public static final int DT_NEEDED = 1;
77 | public static final int DT_PLTRELSZ = 2;
78 | public static final int DT_PLTGOT = 3;
79 | public static final int DT_HASH = 4;
80 | /**
81 | * DT_STRTAB entry holds the address, not offset, of the dynamic string table.
82 | */
83 | public static final int DT_STRTAB = 5;
84 | public static final int DT_SYMTAB = 6;
85 | public static final int DT_RELA = 7;
86 | public static final int DT_RELASZ = 8;
87 | public static final int DT_RELAENT = 9;
88 | /**
89 | * The size in bytes of the {@link #DT_STRTAB} string table.
90 | */
91 | public static final int DT_STRSZ = 10;
92 | public static final int DT_SYMENT = 11;
93 | public static final int DT_INIT = 12;
94 | public static final int DT_FINI = 13;
95 | public static final int DT_SONAME = 14;
96 | public static final int DT_RPATH = 15;
97 | public static final int DT_SYMBOLIC = 16;
98 | public static final int DT_REL = 17;
99 | public static final int DT_RELSZ = 18;
100 | public static final int DT_RELENT = 19;
101 | public static final int DT_PLTREL = 20;
102 | public static final int DT_DEBUG = 21;
103 | public static final int DT_TEXTREL = 22;
104 | public static final int DT_JMPREL = 23;
105 | public static final int DT_BIND_NOW = 24;
106 | public static final int DT_INIT_ARRAY = 25;
107 | public static final int DT_FINI_ARRAY = 26;
108 | public static final int DT_INIT_ARRAYSZ = 27;
109 | public static final int DT_FINI_ARRAYSZ = 28;
110 | public static final int DT_RUNPATH = 29;
111 | public static final int DT_FLAGS = 30;
112 | public static final int DT_PREINIT_ARRAY = 32;
113 | public static final int DT_GNU_HASH = 0x6ffffef5;
114 | public static final int DT_FLAGS_1 = 0x6ffffffb;
115 | public static final int DT_VERDEF = 0x6ffffffc; /* Address of version definition */
116 | public static final int DT_VERDEFNUM = 0x6ffffffd; /* Number of version definitions */
117 | public static final int DT_VERNEEDED = 0x6ffffffe;
118 | public static final int DT_VERNEEDNUM = 0x6fffffff;
119 |
120 | public static final int DF_ORIGIN = 0x1;
121 | public static final int DF_SYMBOLIC = 0x2;
122 | public static final int DF_TEXTREL = 0x4;
123 | public static final int DF_BIND_NOW = 0x8;
124 |
125 | /**
126 | * Set RTLD_NOW for this object.
127 | */
128 | public static final int DF_1_NOW = 0x00000001;
129 | /**
130 | * Set RTLD_GLOBAL for this object.
131 | */
132 | public static final int DF_1_GLOBAL = 0x00000002;
133 | /**
134 | * Set RTLD_GROUP for this object.
135 | */
136 | public static final int DF_1_GROUP = 0x00000004;
137 | /**
138 | * Set RTLD_NODELETE for this object.
139 | */
140 | public static final int DF_1_NODELETE = 0x00000008;
141 | public static final int DF_1_LOADFLTR = 0x00000010;
142 | public static final int DF_1_INITFIRST = 0x00000020;
143 | /**
144 | * Object can not be used with dlopen(3)
145 | */
146 | public static final int DF_1_NOOPEN = 0x00000040;
147 | public static final int DF_1_ORIGIN = 0x00000080;
148 | public static final int DF_1_DIRECT = 0x00000100;
149 | public static final int DF_1_TRANS = 0x00000200;
150 | public static final int DF_1_INTERPOSE = 0x00000400;
151 | public static final int DF_1_NODEFLIB = 0x00000800;
152 | /**
153 | * Object cannot be dumped with dldump(3)
154 | */
155 | public static final int DF_1_NODUMP = 0x00001000;
156 | public static final int DF_1_CONFALT = 0x00002000;
157 | public static final int DF_1_ENDFILTEE = 0x00004000;
158 | public static final int DF_1_DISPRELDNE = 0x00008000;
159 | public static final int DF_1_DISPRELPND = 0x00010000;
160 | public static final int DF_1_NODIRECT = 0x00020000;
161 | public static final int DF_1_IGNMULDEF = 0x00040000;
162 | public static final int DF_1_NOKSYMS = 0x00080000;
163 | public static final int DF_1_NOHDR = 0x00100000;
164 | public static final int DF_1_EDITED = 0x00200000;
165 | public static final int DF_1_NORELOC = 0x00400000;
166 | public static final int DF_1_SYMINTPOSE = 0x00800000;
167 | public static final int DF_1_GLOBAUDIT = 0x01000000;
168 | public static final int DF_1_SINGLETON = 0x02000000;
169 | public static final int DF_1_STUB = 0x04000000;
170 | public static final int DF_1_PIE = 0x08000000;
171 |
172 | /**
173 | * For the {@link #DT_STRTAB}. Mandatory.
174 | */
175 | public long dt_strtab_offset;
176 |
177 | /**
178 | * For the {@link #DT_STRSZ}. Mandatory.
179 | */
180 | public int dt_strtab_size;
181 |
182 | private MemoizedObject
188 | * In the elf.h header file this represents either of the following structures:
189 | *
190 | *
218 | * One of the DT_* constants in {@link ElfDynamicSection}.
219 | */
220 | public final long d_tag;
221 | /**
222 | * A field whose value is to be interpreted as specified by the {@link #d_tag}.
223 | */
224 | public final long d_val_or_ptr;
225 |
226 | @Override
227 | public int hashCode() {
228 | final int prime = 31;
229 | int result = 1;
230 | result = prime * result + (int) (d_tag ^ (d_tag >>> 32));
231 | result = prime * result + (int) (d_val_or_ptr ^ (d_val_or_ptr >>> 32));
232 | return result;
233 | }
234 |
235 | @Override
236 | public boolean equals(Object obj) {
237 | if (this == obj) return true;
238 | if (obj == null) return false;
239 | if (getClass() != obj.getClass()) return false;
240 | ElfDynamicStructure other = (ElfDynamicStructure) obj;
241 | if (d_tag != other.d_tag) return false;
242 | return d_val_or_ptr == other.d_val_or_ptr;
243 | }
244 |
245 | @Override
246 | public String toString() {
247 | return "ElfDynamicSectionEntry{tag=" + d_tag + ", d_val_or_ptr=" + d_val_or_ptr + "}";
248 | }
249 | }
250 |
251 | public ElfDynamicSection(final ElfParser parser, ElfSectionHeader header) {
252 | super(parser, header);
253 |
254 | parser.seek(header.sh_offset);
255 | int numEntries = (int) (header.sh_size / 8);
256 |
257 | // Except for the DT_NULL element at the end of the array, and the relative order of DT_NEEDED elements, entries
258 | // may appear in any order. So important to use lazy evaluation to only evaluating e.g. DT_STRTAB after the
259 | // necessary DT_STRSZ is read.
260 | loop:
261 | for (int i = 0; i < numEntries; i++) {
262 | long d_tag = parser.readIntOrLong();
263 | final long d_val_or_ptr = parser.readIntOrLong();
264 | entries.add(new ElfDynamicStructure(d_tag, d_val_or_ptr));
265 | switch ((int) d_tag) {
266 | case DT_NULL:
267 | // A DT_NULL element ends the array (may be following DT_NULL values, but no need to look at them).
268 | break loop;
269 | case DT_STRTAB: {
270 | dtStringTable = new MemoizedObject
16 | * Use one of the following methods to parse input to get an instance of this class:
17 | *
24 | * Resources about ELF files:
25 | *
12 | * The descriptor begins with two words:
13 | * word 0: number of entries
14 | * word 1: bitmask of enabled entries
15 | * Then follow variable-length entries, one byte followed by a '\0'-terminated hwcap name string. The byte gives the bit
16 | * number to test if enabled,
22 | * The descriptor consists of any nonzero number of bytes.
23 | */
24 | public static final int NT_GNU_BUILD_ID = 3;
25 |
26 | /**
27 | * A possible value of the {@link #n_type} for a note containing a version string generated by GNU gold.
28 | */
29 | public static final int NT_GNU_GOLD_VERSION = 4;
30 |
31 | /**
32 | * The descriptor content of a link {@link #NT_GNU_ABI_TAG} type note.
33 | *
34 | * Accessible in {@link #descriptorAsGnuAbi()}.
35 | */
36 | public final static class GnuAbiDescriptor {
37 |
38 | /**
39 | * A possible value of {@link #operatingSystem}.
40 | */
41 | public static final int ELF_NOTE_OS_LINUX = 0;
42 | /**
43 | * A possible value of {@link #operatingSystem}.
44 | */
45 | public static final int ELF_NOTE_OS_GNU = 1;
46 | /**
47 | * A possible value of {@link #operatingSystem}.
48 | */
49 | public static final int ELF_NOTE_OS_SOLARIS2 = 2;
50 | /**
51 | * A possible value of {@link #operatingSystem}.
52 | */
53 | public static final int ELF_NOTE_OS_FREEBSD = 3;
54 |
55 | /**
56 | * One of the ELF_NOTE_OS_* constants in this class.
57 | */
58 | public final int operatingSystem;
59 | /**
60 | * Major version of the required ABI.
61 | */
62 | public final int majorVersion;
63 | /**
64 | * Minor version of the required ABI.
65 | */
66 | public final int minorVersion;
67 | /**
68 | * Subminor version of the required ABI.
69 | */
70 | public final int subminorVersion;
71 |
72 | public GnuAbiDescriptor(int operatingSystem, int majorVersion, int minorVersion, int subminorVersion) {
73 | this.operatingSystem = operatingSystem;
74 | this.majorVersion = majorVersion;
75 | this.minorVersion = minorVersion;
76 | this.subminorVersion = subminorVersion;
77 | }
78 | }
79 |
80 | public final /* uint32_t */ int n_namesz;
81 | public final /* uint32_t */ int n_descsz;
82 | public final /* uint32_t */ int n_type;
83 | private final String n_name;
84 | private final byte[] descriptorBytes;
85 | private final GnuAbiDescriptor gnuAbiDescriptor;
86 |
87 | ElfNoteSection(ElfParser parser, ElfSectionHeader header) throws ElfException {
88 | super(parser, header);
89 |
90 | parser.seek(header.sh_offset);
91 | n_namesz = parser.readInt();
92 | n_descsz = parser.readInt();
93 | n_type = parser.readInt();
94 | byte[] nameBytes = new byte[n_namesz];
95 | descriptorBytes = new byte[n_descsz];
96 | int bytesRead = parser.read(nameBytes);
97 | if (bytesRead != n_namesz) {
98 | throw new ElfException("Error reading note name (read=" + bytesRead + ", expected=" + n_namesz + ")");
99 | }
100 | parser.skip(bytesRead % 4);
101 |
102 | switch (n_type) {
103 | case NT_GNU_ABI_TAG:
104 | gnuAbiDescriptor = new GnuAbiDescriptor(parser.readInt(), parser.readInt(), parser.readInt(), parser.readInt());
105 | break;
106 | default:
107 | gnuAbiDescriptor = null;
108 | }
109 |
110 | bytesRead = parser.read(descriptorBytes);
111 | if (bytesRead != n_descsz) {
112 | throw new ElfException("Error reading note name (read=" + bytesRead + ", expected=" + n_descsz + ")");
113 | }
114 |
115 | n_name = new String(nameBytes, 0, n_namesz - 1); // unnecessary trailing 0
116 | }
117 |
118 | public String getName() {
119 | return n_name;
120 | }
121 |
122 | public byte[] descriptorBytes() {
123 | return descriptorBytes;
124 | }
125 |
126 | public String descriptorAsString() {
127 | return new String(descriptorBytes);
128 | }
129 |
130 | public GnuAbiDescriptor descriptorAsGnuAbi() {
131 | return gnuAbiDescriptor;
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfParser.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /** Package internal class used for parsing ELF files. */
4 | class ElfParser {
5 |
6 | final ElfFile elfFile;
7 | private final BackingFile backingFile;
8 |
9 | ElfParser(ElfFile elfFile, BackingFile backingFile) {
10 | this.elfFile = elfFile;
11 | this.backingFile = backingFile;
12 | }
13 |
14 | public void seek(long offset) {
15 | backingFile.seek(offset);
16 | }
17 |
18 | public void skip(int bytesToSkip) {
19 | backingFile.skip(bytesToSkip);
20 | }
21 |
22 | short readUnsignedByte() {
23 | return backingFile.readUnsignedByte();
24 | }
25 |
26 | short readShort() throws ElfException {
27 | int ch1 = readUnsignedByte();
28 | int ch2 = readUnsignedByte();
29 | if (elfFile.ei_data == ElfFile.DATA_LSB) {
30 | return (short) (((short) ch2 & 0xff) << 8 | ((short) ch1 & 0xff));
31 | } else {
32 | return (short) (((short) ch1 & 0xff) << 8 | ((short) ch2 & 0xff));
33 | }
34 | }
35 |
36 | int readInt() throws ElfException {
37 | int ch1 = readUnsignedByte();
38 | int ch2 = readUnsignedByte();
39 | int ch3 = readUnsignedByte();
40 | int ch4 = readUnsignedByte();
41 | if (elfFile.ei_data == ElfFile.DATA_LSB) {
42 | return ((int) ch4 & 0xff) << 24 | ((int) ch3 & 0xff) << 16 | ((int) ch2 & 0xff) << 8 | ((int) ch1 & 0xff);
43 | } else {
44 | return ((int) ch1 & 0xff) << 24 | ((int) ch2 & 0xff) << 16 | ((int) ch3 & 0xff) << 8 | ((int) ch4 & 0xff);
45 | }
46 | }
47 |
48 | long readLong() {
49 | int ch1 = readUnsignedByte();
50 | int ch2 = readUnsignedByte();
51 | int ch3 = readUnsignedByte();
52 | int ch4 = readUnsignedByte();
53 | int ch5 = readUnsignedByte();
54 | int ch6 = readUnsignedByte();
55 | int ch7 = readUnsignedByte();
56 | int ch8 = readUnsignedByte();
57 |
58 | if (elfFile.ei_data == ElfFile.DATA_LSB) {
59 | return ((long) ch8 << 56) | ((long) ch7 & 0xff) << 48 | ((long) ch6 & 0xff) << 40
60 | | ((long) ch5 & 0xff) << 32 | ((long) ch4 & 0xff) << 24 | ((long) ch3 & 0xff) << 16
61 | | ((long) ch2 & 0xff) << 8 | ((long) ch1 & 0xff);
62 | } else {
63 | return ((long) ch1 << 56) | ((long) ch2 & 0xff) << 48 | ((long) ch3 & 0xff) << 40
64 | | ((long) ch4 & 0xff) << 32 | ((long) ch5 & 0xff) << 24 | ((long) ch6 & 0xff) << 16
65 | | ((long) ch7 & 0xff) << 8 | ((long) ch8 & 0xff);
66 | }
67 | }
68 |
69 | /** Read four-byte int or eight-byte long depending on if {@link ElfFile#ei_class}. */
70 | long readIntOrLong() {
71 | return elfFile.ei_class == ElfFile.CLASS_32 ? readInt() : readLong();
72 | }
73 |
74 | /** Returns a big-endian unsigned representation of the int. */
75 | long unsignedByte(int arg) {
76 | long val;
77 | if (arg >= 0) {
78 | val = arg;
79 | } else {
80 | val = (unsignedByte((short) (arg >>> 16)) << 16) | ((short) arg);
81 | }
82 | return val;
83 | }
84 |
85 | /**
86 | * Find the file offset from a virtual address by looking up the {@link ElfSegment} segment containing the
87 | * address and computing the resulting file offset.
88 | */
89 | long virtualMemoryAddrToFileOffset(long address) {
90 | for (int i = 0; i < elfFile.e_phnum; i++) {
91 | ElfSegment ph = elfFile.getProgramHeader(i);
92 | if (address >= ph.p_vaddr && address < (ph.p_vaddr + ph.p_memsz)) {
93 | long relativeOffset = address - ph.p_vaddr;
94 | if (relativeOffset >= ph.p_filesz)
95 | throw new ElfException("Can not convert virtual memory address " + Long.toHexString(address) + " to file offset -" + " found segment " + ph
96 | + " but address maps to memory outside file range");
97 | return ph.p_offset + relativeOffset;
98 | }
99 | }
100 | throw new ElfException("Cannot find segment for address " + Long.toHexString(address));
101 | }
102 |
103 | public int read(byte[] data) {
104 | return backingFile.read(data);
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfRelocation.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * A relocation connects a symbolic reference with its actual definition.
5 | * Relocatable files must have information that describes how to modify their
6 | * section contents, thus allowing executable and shared object files to hold
7 | * the right information for a process's program image. Relocation entries are
8 | * these data.
9 | *
10 | * These elf relocation entries can be obtained from {@link ElfRelocationSection}:s.
11 | *
12 | * Corresponds to the below C structs:
13 | *
62 | * Corresponds to the ELF32_R_SYM / ELF64_R_SYM macros.
63 | */
64 | public int getSymbolIndex() {
65 | return (int) (r_info >> (elfFile.is32Bits() ? 8 : 32));
66 | }
67 |
68 | /**
69 | * The symbol with respect to which the relocation must be made.
70 | * Use {@link #getSymbolIndex()}} to get the resolved {@link ElfSymbol} from this index.
71 | */
72 | public ElfSymbol getSymbol() {
73 | return elfFile.getSymbolTableSection().symbols[getSymbolIndex()];
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfRelocationAddend.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * Relocation is the process of connecting symbolic references with symbolic definitions.
5 | * For example, when a program calls a function, the associated call instruction must transfer
6 | * control to the proper destination address at execution. Relocatable files must have
7 | * information that describes how to modify their section contents. This information allows
8 | * executable and shared object files to hold the right information for a process's program
9 | * image. Relocation entries are these data.
10 | *
11 | * These elf relocation entries can be obtained from {@link ElfRelocationAddend}:s.
12 | *
13 | * Corresponds to the below C structs:
14 | *
79 | * Corresponds to the ELF32_R_SYM / ELF64_R_SYM macros.
80 | */
81 | public int getSymbolIndex() {
82 | return (int) (r_info >> (elfFile.is32Bits() ? 8 : 32));
83 | }
84 |
85 | /**
86 | * The symbol table index, with respect to which the relocation must be made.
87 | * Use {@link #getSymbolIndex()}} to get the resolved {@link ElfSymbol} from this index.
88 | */
89 | public ElfSymbol getSymbol() {
90 | return elfFile.getSymbolTableSection().symbols[getSymbolIndex()];
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfRelocationAddendSection.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | public final class ElfRelocationAddendSection extends ElfSection {
4 | public final ElfRelocationAddend[] relocations;
5 |
6 | public ElfRelocationAddendSection(ElfParser parser, ElfSectionHeader header) {
7 | super(parser, header);
8 |
9 | int num_entries = (int) (header.sh_size / header.sh_entsize);
10 | relocations = new ElfRelocationAddend[num_entries];
11 | for (int i = 0; i < num_entries; i++) {
12 | final long relOffset = header.sh_offset + (i * header.sh_entsize);
13 | relocations[i] = new ElfRelocationAddend(parser, relOffset);
14 | }
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfRelocationSection.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | public final class ElfRelocationSection extends ElfSection {
4 | public final ElfRelocation[] relocations;
5 |
6 | public ElfRelocationSection(ElfParser parser, ElfSectionHeader header) {
7 | super(parser, header);
8 |
9 | int num_entries = (int) (header.sh_size / header.sh_entsize);
10 | relocations = new ElfRelocation[num_entries];
11 | for (int i = 0; i < num_entries; i++) {
12 | final long relOffset = header.sh_offset + (i * header.sh_entsize);
13 | relocations[i] = new ElfRelocation(parser, relOffset);
14 | }
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfRelocationTypes.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * @see ElfRelocation#getType()
5 | * @see ElfRelocationAddend#getType()
6 | */
7 | public final class ElfRelocationTypes {
8 | /**
9 | * AMD x86-64: No reloc
10 | */
11 | public static final int R_X86_64_NONE = 0;
12 | /**
13 | * AMD x86-64: Direct 64 bit.
14 | */
15 | public static final int R_X86_64_64 = 1;
16 | /**
17 | * AMD x86-64: PC relative 32 bit signed.
18 | */
19 | public static final int R_X86_64_PC32 = 2;
20 | /**
21 | * AMD x86-64: 32 bit GOT entry.
22 | */
23 | public static final int R_X86_64_GOT32 = 3;
24 | /**
25 | * AMD x86-64: 32 bit PLT address.
26 | */
27 | public static final int R_X86_64_PLT32 = 4;
28 | /**
29 | * AMD x86-64: Copy symbol at runtime.
30 | */
31 | public static final int R_X86_64_COPY = 5;
32 | /**
33 | * AMD x86-64: Create GOT entry.
34 | */
35 | public static final int R_X86_64_GLOB_DAT = 6;
36 | /**
37 | * AMD x86-64: Create PLT entry.
38 | */
39 | public static final int R_X86_64_JUMP_SLOT = 7;
40 | /**
41 | * AMD x86-64: Adjust by program base.
42 | */
43 | public static final int R_X86_64_RELATIVE = 8;
44 | /**
45 | * AMD x86-64: 32 bit signed PC relative offset to GOT.
46 | */
47 | public static final int R_X86_64_GOTPCREL = 9;
48 | /**
49 | * AMD x86-64: Direct 32 bit zero extended.
50 | */
51 | public static final int R_X86_64_32 = 10;
52 | /**
53 | * AMD x86-64: Direct 32 bit sign extended.
54 | */
55 | public static final int R_X86_64_32S = 11;
56 | /**
57 | * AMD x86-64: Direct 16 bit zero extended.
58 | */
59 | public static final int R_X86_64_16 = 12;
60 | /**
61 | * AMD x86-64: 16 bit sign extended pc relative.
62 | */
63 | public static final int R_X86_64_PC16 = 13;
64 | /**
65 | * AMD x86-64: Direct 8 bit sign extended.
66 | */
67 | public static final int R_X86_64_8 = 14;
68 | /**
69 | * AMD x86-64: 8 bit sign extended pc relative.
70 | */
71 | public static final int R_X86_64_PC8 = 15;
72 | /**
73 | * AMD x86-64: ID of module containing symbol.
74 | */
75 | public static final int R_X86_64_DTPMOD64 = 16;
76 | /**
77 | * AMD x86-64: Offset in module's TLS block.
78 | */
79 | public static final int R_X86_64_DTPOFF64 = 17;
80 | /**
81 | * AMD x86-64: Offset in initial TLS block
82 | */
83 | public static final int R_X86_64_TPOFF64 = 18;
84 | /**
85 | * AMD x86-64: 32 bit signed PC relative offset to two GOT entries for GD symbol.
86 | */
87 | public static final int R_X86_64_TLSGD = 19;
88 | /**
89 | * AMD x86-64: 32 bit signed PC relative offset to two GOT entries for LD symbol.
90 | */
91 | public static final int R_X86_64_TLSLD = 20;
92 | /**
93 | * AMD x86-64: Offset in TLS block.
94 | */
95 | public static final int R_X86_64_DTPOFF32 = 21;
96 | /**
97 | * AMD x86-64: 32 bit signed PC relative offset to GOT entry for IE symbol.
98 | */
99 | public static final int R_X86_64_GOTTPOFF = 22;
100 | /**
101 | * AMD x86-64: Offset in initial TLS block.
102 | */
103 | public static final int R_X86_64_TPOFF32 = 23;
104 | /**
105 | * AMD x86-64: PC relative 64 bit.
106 | */
107 | public static final int R_X86_64_PC64 = 24;
108 | /**
109 | * AMD x86-64: 64 bit offset to GOT.
110 | */
111 | public static final int R_X86_64_GOTOFF64 = 25;
112 | /**
113 | * AMD x86-64: 32 bit signed pc relative offset to GOT.
114 | */
115 | public static final int R_X86_64_GOTPC32 = 26;
116 | /**
117 | * AMD x86-64: 64-bit GOT entry offset.
118 | */
119 | public static final int R_X86_64_GOT64 = 27;
120 | /**
121 | * AMD x86-64:64-bit PC relative offset to GOT entry.
122 | */
123 | public static final int R_X86_64_GOTPCREL64 = 28;
124 | /**
125 | * AMD x86-64:64-bit PC relative offset to GOT.
126 | */
127 | public static final int R_X86_64_GOTPC64 = 29;
128 | /**
129 | * AMD x86-64:like GOT64, says PLT entry needed.
130 | */
131 | public static final int R_X86_64_GOTPLT64 = 30;
132 | /**
133 | * AMD x86-64:64-bit GOT relative offset to PLT entry.
134 | */
135 | public static final int R_X86_64_PLTOFF64 = 31;
136 | /**
137 | * AMD x86-64:Size of symbol plus 32-bit addend.
138 | */
139 | public static final int R_X86_64_SIZE32 = 32;
140 | /**
141 | * AMD x86-64:Size of symbol plus 64-bit addend.
142 | */
143 | public static final int R_X86_64_SIZE64 = 33;
144 | /**
145 | * AMD x86-64:GOT offset for TLS descriptor.
146 | */
147 | public static final int R_X86_64_GOTPC32_TLSDESC = 34;
148 | /**
149 | * AMD x86-64:Marker for call through TLS descriptor.
150 | */
151 | public static final int R_X86_64_TLSDESC_CALL = 35;
152 | /**
153 | * AMD x86-64:TLS descriptor.
154 | */
155 | public static final int R_X86_64_TLSDESC = 36;
156 | /**
157 | * AMD x86-64:Adjust indirectly by program base
158 | */
159 | public static final int R_X86_64_IRELATIVE = 37;
160 | /**
161 | * AMD x86-64:64-bit adjust by program base.
162 | */
163 | public static final int R_X86_64_RELATIVE64 = 38;
164 | /**
165 | * AMD x86-64:Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable.
166 | */
167 | public static final int R_X86_64_GOTPCRELX = 41;
168 | /**
169 | * AMD x86-64:Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable.
170 | */
171 | public static final int R_X86_64_REX_GOTPCRELX = 42;
172 | public static final int R_X86_64_NUM = 43;
173 |
174 | public static final int R_ARM_NONE = 0;
175 | public static final int R_ARM_PC24 = 1;
176 | public static final int R_ARM_ABS32 = 2;
177 | public static final int R_ARM_REL32 = 3;
178 | public static final int R_ARM_THM_CALL = 10;
179 | public static final int R_ARM_CALL = 28;
180 | public static final int R_ARM_JUMP24 = 29;
181 | public static final int R_ARM_THM_JUMP24 = 30;
182 | public static final int R_ARM_TARGET1 = 38;
183 | public static final int R_ARM_V4BX = 40;
184 | public static final int R_ARM_PREL31 = 42;
185 | public static final int R_ARM_MOVW_ABS_NC = 43;
186 | public static final int R_ARM_MOVT_ABS = 44;
187 | public static final int R_ARM_MOVW_PREL_NC = 45;
188 | public static final int R_ARM_MOVT_PREL = 46;
189 | public static final int R_ARM_THM_MOVW_ABS_NC = 47;
190 | public static final int R_ARM_THM_MOVT_ABS = 48;
191 | public static final int R_ARM_THM_MOVW_PREL_NC = 49;
192 | public static final int R_ARM_THM_MOVT_PREL = 50;
193 |
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfSection.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | public class ElfSection {
4 | public final ElfSectionHeader header;
5 | protected final ElfParser parser;
6 |
7 | ElfSection(ElfParser parser, ElfSectionHeader header) {
8 | this.header = header;
9 | this.parser = parser;
10 | }
11 |
12 | /**
13 | * Get the bytes contained in this ELF section.
14 | */
15 | public byte[] getData() {
16 | if (header.sh_size == 0 || header.sh_type == ElfSectionHeader.SHT_NOBITS || header.sh_type == ElfSectionHeader.SHT_NULL) {
17 | return new byte[0];
18 | } else if (header.sh_size > (long) Integer.MAX_VALUE) {
19 | throw new ElfException("Too big section: " + header.sh_size);
20 | }
21 |
22 | byte[] result = new byte[(int) header.sh_size];
23 | parser.seek(header.sh_offset);
24 | parser.read(result);
25 | return result;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfSectionHeader.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * Class corresponding to the Elf32_Shdr/Elf64_Shdr struct.
5 | *
6 | *
7 | * An object file's section header table lets one locate all the file's sections. The section header table is an array
8 | * of Elf32_Shdr or Elf64_Shdr structures. A section header table index is a subscript into this array. The ELF header's
9 | * {@link ElfFile#e_shoff e_shoff member} gives the byte offset from the beginning of the file to the section header
10 | * table with each section header entry being {@link ElfFile#e_shentsize e_shentsize} bytes big.
11 | *
12 | *
13 | * {@link ElfFile#e_shnum e_shnum} normally tells how many entries the section header table contains, but if the number
14 | * of sections is greater than or equal to SHN_LORESERVE (0xff00), e_shnum has the value SHN_UNDEF (0) and the actual
15 | * number of section header table entries is contained in the sh_size field of the section header at index 0 (otherwise,
16 | * the sh_size member of the initial entry contains 0).
17 | *
18 | *
19 | * Some section header table indexes are reserved in contexts where index size is restricted, for example, the st_shndx
20 | * member of a symbol table entry and the e_shnum and e_shstrndx members of the ELF header. In such contexts, the
21 | * reserved values do not represent actual sections in the object file. Also in such contexts, an escape value indicates
22 | * that the actual section index is to be found elsewhere, in a larger field.
23 | */
24 | public class ElfSectionHeader {
25 |
26 | /**
27 | * Marks the section header as inactive; it does not have an associated section. Other members of the section header
28 | * have undefined values.
29 | */
30 | public static final int SHT_NULL = 0;
31 | /**
32 | * Section holds information defined by the program.
33 | */
34 | public static final int SHT_PROGBITS = 1;
35 | /**
36 | * The {@link #sh_type} value for a section containing complete symbol table information necessary for link editing.
37 | *
38 | * See {@link ElfSymbolTableSection}, which is the class representing sections of this type, for more information.
39 | */
40 | public static final int SHT_SYMTAB = 2;
41 | /**
42 | * Section holds string table information.
43 | */
44 | public static final int SHT_STRTAB = 3;
45 | /**
46 | * Section holds relocation entries with explicit addends.
47 | */
48 | public static final int SHT_RELA = 4;
49 | /**
50 | * Section holds symbol hash table.
51 | */
52 | public static final int SHT_HASH = 5;
53 | /**
54 | * Section holds information for dynamic linking. Only one per ELF file. The dynsym is allocable, and contains the
55 | * symbols needed to support runtime operation.
56 | */
57 | public static final int SHT_DYNAMIC = 6;
58 | /**
59 | * Section holds information that marks the file.
60 | */
61 | public static final int SHT_NOTE = 7;
62 | /**
63 | * Section occupies no space but resembles TYPE_PROGBITS.
64 | */
65 | public static final int SHT_NOBITS = 8;
66 | /**
67 | * Section holds relocation entries without explicit addends.
68 | */
69 | public static final int SHT_REL = 9;
70 | /**
71 | * Section is reserved but has unspecified semantics.
72 | */
73 | public static final int SHT_SHLIB = 10;
74 | /**
75 | * The {@link #sh_type} value for a section containing a minimal set of symbols needed for dynamic linking at runtime.
76 | *
77 | * See {@link ElfSymbolTableSection}, which is the class representing sections of this type, for more information.
78 | */
79 | public static final int SHT_DYNSYM = 11;
80 | public static final int SHT_INIT_ARRAY = 14;
81 | public static final int SHT_FINI_ARRAY = 15;
82 | public static final int SHT_PREINIT_ARRAY = 16;
83 | public static final int SHT_GROUP = 17;
84 | public static final int SHT_SYMTAB_SHNDX = 18;
85 |
86 | /**
87 | * A hash table for fast lookup of dynamic symbols.
88 | *
89 | * See {@link ElfGnuHashTable}.
90 | */
91 | public static final int SHT_GNU_HASH = 0x6ffffff6;
92 | public static final int SHT_GNU_verdef = 0x6ffffffd;
93 | public static final int SHT_GNU_verneed = 0x6ffffffe;
94 | public static final int SHT_GNU_versym = 0x6fffffff;
95 |
96 | /**
97 | * Lower bound of the range of indexes reserved for operating system-specific semantics.
98 | */
99 | public static final int SHT_LOOS = 0x60000000;
100 | /**
101 | * Upper bound of the range of indexes reserved for operating system-specific semantics.
102 | */
103 | public static final int SHT_HIOS = 0x6fffffff;
104 | /**
105 | * Lower bound of the range of indexes reserved for processor-specific semantics.
106 | */
107 | public static final int SHT_LOPROC = 0x70000000;
108 | /**
109 | * Upper bound of the range of indexes reserved for processor-specific semantics.
110 | */
111 | public static final int SHT_HIPROC = 0x7fffffff;
112 | /**
113 | * Lower bound of the range of indexes reserved for application programs.
114 | */
115 | public static final int SHT_LOUSER = 0x80000000;
116 | /**
117 | * Upper bound of the range of indexes reserved for application programs.
118 | */
119 | public static final int SHT_HIUSER = 0xffffffff;
120 |
121 | /**
122 | * Flag informing that this section contains data that should be writable during process execution.
123 | */
124 | public static final int FLAG_WRITE = 0x1;
125 | /**
126 | * Flag informing that section occupies memory during process execution.
127 | */
128 | public static final int FLAG_ALLOC = 0x2;
129 | /**
130 | * Flag informing that section contains executable machine instructions.
131 | */
132 | public static final int FLAG_EXEC_INSTR = 0x4;
133 | /**
134 | * Flag informing that all the bits in the mask are reserved for processor specific semantics.
135 | */
136 | public static final int FLAG_MASK = 0xf0000000;
137 |
138 | /**
139 | * Name for the section containing the string table.
140 | *
141 | * This section contains a string table which contains names for symbol structures
142 | * by being indexed by the {@link ElfSymbol#st_name} field.
143 | */
144 | public static final String NAME_STRTAB = ".strtab";
145 | /**
146 | * Name for the section containing the dynamic string table.
147 | */
148 | public static final String NAME_DYNSTR = ".dynstr";
149 | /**
150 | * Name for the section containing read-only initialized data.
151 | */
152 | public static final String NAME_RODATA = ".rodata";
153 |
154 | /**
155 | * Index into the section header string table which gives the name of the section.
156 | */
157 | public final int sh_name; // Elf32_Word or Elf64_Word - 4 bytes in both.
158 | /**
159 | * Section content and semantics.
160 | */
161 | public final int sh_type; // Elf32_Word or Elf64_Word - 4 bytes in both.
162 | /**
163 | * Flags.
164 | */
165 | public final long sh_flags; // Elf32_Word or Elf64_Xword.
166 | /**
167 | * sh_addr. If the section will be in the memory image of a process this will be the address at which the first byte
168 | * of section will be loaded. Otherwise, this value is 0.
169 | */
170 | public final long sh_addr; // Elf32_Addr
171 | /**
172 | * Offset from beginning of file to first byte of the section.
173 | */
174 | public final long sh_offset; // Elf32_Off
175 | /**
176 | * Size in bytes of the section. TYPE_NOBITS is a special case.
177 | */
178 | public final /* uint32_t */ long sh_size;
179 | /**
180 | * Section header table index link.
181 | */
182 | public final /* uint32_t */ int sh_link;
183 | /**
184 | * Extra information determined by the section type.
185 | */
186 | public final /* uint32_t */ int sh_info;
187 | /**
188 | * Address alignment constraints for the section.
189 | */
190 | public final /* uint32_t */ long sh_addralign;
191 | /**
192 | * Size of a fixed-size entry, 0 if none.
193 | */
194 | public final long sh_entsize; // Elf32_Word
195 |
196 | private final ElfFile elfHeader;
197 |
198 | /**
199 | * Reads the section header information located at offset.
200 | */
201 | ElfSectionHeader(final ElfParser parser, long offset) {
202 | this.elfHeader = parser.elfFile;
203 | parser.seek(offset);
204 |
205 | sh_name = parser.readInt();
206 | sh_type = parser.readInt();
207 | sh_flags = parser.readIntOrLong();
208 | sh_addr = parser.readIntOrLong();
209 | sh_offset = parser.readIntOrLong();
210 | sh_size = parser.readIntOrLong();
211 | sh_link = parser.readInt();
212 | sh_info = parser.readInt();
213 | sh_addralign = parser.readIntOrLong();
214 | sh_entsize = parser.readIntOrLong();
215 | }
216 |
217 | /**
218 | * Returns the name of the section or null if the section has no name.
219 | *
220 | * @return the name of the section, if any
221 | */
222 | public String getName() {
223 | if (sh_name == 0) return null;
224 | ElfStringTable tbl = elfHeader.getSectionNameStringTable();
225 | return tbl.get(sh_name);
226 | }
227 |
228 | @Override
229 | public String toString() {
230 | return "ElfSectionHeader[name=" + getName() + ", type=0x" + Long.toHexString(sh_type) + "]";
231 | }
232 |
233 | }
234 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfSegment.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * Class corresponding to the Elf32_Phdr/Elf64_Phdr struct.
5 | *
6 | * An executable or shared object file's program header table is an array of structures, each describing a segment or
7 | * other information the system needs to prepare the program for execution. An object file segment contains one or more
8 | * sections. Program headers are meaningful only for executable and shared object files. A file specifies its own
9 | * program header size with the ELF header's {@link ElfFile#e_phentsize e_phentsize} and {@link ElfFile#e_phnum
10 | * e_phnum} members.
11 | *
12 | * http://www.sco.com/developers/gabi/latest/ch5.pheader.html#p_type
13 | * http://stackoverflow.com/questions/22612735/how-can-i-find-the-dynamic-libraries-required-by-an-elf-binary-in-c
14 | */
15 | public class ElfSegment {
16 |
17 | /**
18 | * Type defining that the array element is unused. Other member values are undefined.
19 | */
20 | public static final int PT_NULL = 0;
21 | /**
22 | * Type defining that the array element specifies a loadable segment.
23 | */
24 | public static final int PT_LOAD = 1;
25 | /**
26 | * The array element specifies dynamic linking information.
27 | */
28 | public static final int PT_DYNAMIC = 2;
29 | /**
30 | * The array element specifies the location and size of a null-terminated path name to invoke as an interpreter.
31 | * Meaningful only for executable files (though it may occur for shared objects); it may not occur more than once in
32 | * a file. If it is present, it must precede any loadable segment entry.
33 | */
34 | public static final int PT_INTERP = 3;
35 | /**
36 | * The array element specifies the location and size of auxiliary information.
37 | */
38 | public static final int PT_NOTE = 4;
39 | /**
40 | * This segment type is reserved but has unspecified semantics.
41 | */
42 | public static final int PT_SHLIB = 5;
43 | /**
44 | * The array element, if present, specifies the location and size of the program header table itself, both in the
45 | * file and in the memory image of the program. This segment type may not occur more than once in a file.
46 | */
47 | public static final int PT_PHDR = 6;
48 | /**
49 | * The array element specifies the Thread-Local Storage template.
50 | */
51 | public static final int PT_TLS = 7;
52 |
53 | /**
54 | * Lower bound of the range reserved for operating system-specific semantics.
55 | */
56 | public static final int PT_LOOS = 0x60000000;
57 | /**
58 | * Upper bound of the range reserved for operating system-specific semantics.
59 | */
60 | public static final int PT_HIOS = 0x6fffffff;
61 | /**
62 | * Lower bound of the range reserved for processor-specific semantics.
63 | */
64 | public static final int PT_LOPROC = 0x70000000;
65 | /**
66 | * Upper bound of the range reserved for processor-specific semantics.
67 | */
68 | public static final int PT_HIPROC = 0x7fffffff;
69 |
70 | /**
71 | * Elf{32,64}_Phdr#p_type. Kind of segment this element describes.
72 | */
73 | public final int p_type; // Elf32_Word/Elf64_Word - 4 bytes in both.
74 | /**
75 | * Flags relevant to this segment. Values for flags are defined in ELFSectionHeader.
76 | */
77 | public final int p_flags; // Elf32_Word
78 | /**
79 | * Elf{32,64}_Phdr#p_offset. File offset at which the first byte of the segment resides.
80 | */
81 | public final long p_offset; // Elf32_Off/Elf64_Off - 4 or 8 bytes.
82 | /**
83 | * Elf{32,64}_Phdr#p_vaddr. Virtual address at which the first byte of the segment resides in memory.
84 | */
85 | public final long p_vaddr; // Elf32_Addr/Elf64_Addr - 4 or 8 bytes.
86 | /**
87 | * Reserved for the physical address of the segment on systems where physical addressing is relevant.
88 | */
89 | public final long p_paddr; // Elf32_addr/Elf64_Addr - 4 or 8 bytes.
90 | /**
91 | * Elf{32,64}_Phdr#p_filesz. File image size of segment in bytes, may be 0.
92 | */
93 | public final long p_filesz; // Elf32_Word/Elf64_Xword -
94 | /**
95 | * Elf{32,64}_Phdr#p_memsz. Memory image size of segment in bytes, may be 0.
96 | */
97 | public final long p_memsz; // Elf32_Word
98 | /**
99 | * Elf{32,64}_Phdr#p_align. The value to which the segments are aligned in memory and in the file.
100 | */
101 | public final long p_align; // Elf32_Word
102 |
103 | private MemoizedObject
6 | * In the elf.h header file the struct definitions are:
7 | *
8 | *
34 | * That is, global and weak symbols are visible outside of their defining component, the executable file or shared object.
35 | * Local symbols are hidden. Global and weak symbols can also be preempted, that is, they may by interposed by definitions
36 | * of the same name in another component.
37 | */
38 | STV_DEFAULT,
39 | /**
40 | * This visibility attribute is currently reserved.
41 | */
42 | STV_INTERNAL,
43 | /**
44 | * A symbol defined in the current component is hidden if its name is not visible to other components. Such a symbol is necessarily protected.
45 | *
46 | * This attribute is used to control the external interface of a component. An object named by such a symbol may still be referenced from another component if its address is passed outside.
47 | *
48 | * A hidden symbol contained in a relocatable object is either removed or converted to STB_LOCAL binding by the link-editor when the relocatable object is included in an executable file or shared object.
49 | */
50 | STV_HIDDEN,
51 | /**
52 | * A symbol defined in the current component is protected if it is visible in other components but cannot be preempted.
53 | *
54 | * Any reference to such a symbol from within the defining component must be resolved to the definition in that component, even if there is a definition in another component that would interpose by the default rules. A symbol with STB_LOCAL binding will not have STV_PROTECTED visibility.
55 | */
56 | STV_PROTECTED
57 | }
58 |
59 | /**
60 | * Binding specifying that local symbols are not visible outside the object file that contains its definition.
61 | */
62 | public static final int BINDING_LOCAL = 0;
63 | /**
64 | * Binding specifying that global symbols are visible to all object files being combined.
65 | */
66 | public static final int BINDING_GLOBAL = 1;
67 | /**
68 | * Binding specifying that the symbol resembles a global symbol, but has a lower precedence.
69 | */
70 | public static final int BINDING_WEAK = 2;
71 | /**
72 | * Lower bound binding values reserved for processor specific semantics.
73 | */
74 | public static final int BINDING_LOPROC = 13;
75 | /**
76 | * Upper bound binding values reserved for processor specific semantics.
77 | */
78 | public static final int BINDING_HIPROC = 15;
79 |
80 | /**
81 | * Type specifying that the symbol is unspecified.
82 | */
83 | public static final byte STT_NOTYPE = 0;
84 | /**
85 | * Type specifying that the symbol is associated with an object.
86 | */
87 | public static final byte STT_OBJECT = 1;
88 | /**
89 | * Type specifying that the symbol is associated with a function or other executable code.
90 | */
91 | public static final byte STT_FUNC = 2;
92 | /**
93 | * Type specifying that the symbol is associated with a section. Symbol table entries of this type exist for
94 | * relocation and normally have the binding BINDING_LOCAL.
95 | */
96 | public static final byte STT_SECTION = 3;
97 | /**
98 | * Type defining that the symbol is associated with a file.
99 | */
100 | public static final byte STT_FILE = 4;
101 | /**
102 | * The symbol labels an uninitialized common block.
103 | */
104 | public static final byte STT_COMMON = 5;
105 | /**
106 | * The symbol specifies a Thread-Local Storage entity.
107 | */
108 | public static final byte STT_TLS = 6;
109 |
110 | /**
111 | * Lower bound for range reserved for operating system-specific semantics.
112 | */
113 | public static final byte STT_LOOS = 10;
114 | /**
115 | * Upper bound for range reserved for operating system-specific semantics.
116 | */
117 | public static final byte STT_HIOS = 12;
118 | /**
119 | * Lower bound for range reserved for processor-specific semantics.
120 | */
121 | public static final byte STT_LOPROC = 13;
122 | /**
123 | * Upper bound for range reserved for processor-specific semantics.
124 | */
125 | public static final byte STT_HIPROC = 15;
126 |
127 | /**
128 | * Index into the symbol string table that holds the character representation of the symbols. 0 means the symbol has
129 | * no character name.
130 | */
131 | public final int st_name; // Elf32_Word
132 | /**
133 | * Value of the associated symbol. This may be a relative address for .so or absolute address for other ELFs.
134 | */
135 | public final long st_value; // Elf32_Addr
136 | /**
137 | * Size of the symbol. 0 if the symbol has no size or the size is unknown.
138 | */
139 | public final long st_size; // Elf32_Word
140 | /**
141 | * Specifies the symbol type and binding attributes.
142 | */
143 | public final short st_info; // unsigned char
144 | /**
145 | * Currently holds the value of 0 and has no meaning.
146 | */
147 | public final short st_other; // unsigned char
148 | /**
149 | * Index to the associated section header. This value will need to be read as an unsigned short if we compare it to
150 | * ELFSectionHeader.NDX_LORESERVE and ELFSectionHeader.NDX_HIRESERVE.
151 | */
152 | public final /* Elf32_Half */ short st_shndx;
153 |
154 | public final int section_type;
155 |
156 | /**
157 | * Offset from the beginning of the file to this symbol.
158 | */
159 | public final long offset;
160 |
161 | private final ElfFile elfHeader;
162 |
163 | ElfSymbol(ElfParser parser, long offset, int section_type) {
164 | this.elfHeader = parser.elfFile;
165 | parser.seek(offset);
166 | this.offset = offset;
167 | if (parser.elfFile.ei_class == ElfFile.CLASS_32) {
168 | st_name = parser.readInt();
169 | st_value = parser.readInt();
170 | st_size = parser.readInt();
171 | st_info = parser.readUnsignedByte();
172 | st_other = parser.readUnsignedByte();
173 | st_shndx = parser.readShort();
174 | } else {
175 | st_name = parser.readInt();
176 | st_info = parser.readUnsignedByte();
177 | st_other = parser.readUnsignedByte();
178 | st_shndx = parser.readShort();
179 | st_value = parser.readLong();
180 | st_size = parser.readLong();
181 | }
182 |
183 | this.section_type = section_type;
184 |
185 | switch (getType()) {
186 | case STT_NOTYPE:
187 | break;
188 | case STT_OBJECT:
189 | break;
190 | case STT_FUNC:
191 | break;
192 | case STT_SECTION:
193 | break;
194 | case STT_FILE:
195 | break;
196 | case STT_LOPROC:
197 | break;
198 | case STT_HIPROC:
199 | break;
200 | default:
201 | break;
202 | }
203 | }
204 |
205 | /**
206 | * Returns the binding for this symbol, extracted from the {@link #st_info} field.
207 | *
208 | * @return the binding for this symbol
209 | */
210 | public int getBinding() {
211 | return st_info >> 4;
212 | }
213 |
214 | /**
215 | * Returns the symbol type, extracted from the {@link #st_info} field.
216 | *
217 | * @return the type of this symbol
218 | */
219 | public int getType() {
220 | return st_info & 0x0F;
221 | }
222 |
223 | /**
224 | * Returns the name of the symbol or null if the symbol has no name.
225 | *
226 | * @return the name of this symbol, if any
227 | */
228 | public String getName() throws ElfException {
229 | // Check to make sure this symbol has a name.
230 | if (st_name == 0) return null;
231 |
232 | // Retrieve the name of the symbol from the correct string table.
233 | String symbol_name = null;
234 | if (section_type == ElfSectionHeader.SHT_SYMTAB) {
235 | symbol_name = elfHeader.getStringTable().get(st_name);
236 | } else if (section_type == ElfSectionHeader.SHT_DYNSYM) {
237 | symbol_name = elfHeader.getDynamicStringTable().get(st_name);
238 | }
239 | return symbol_name;
240 | }
241 |
242 | public Visibility getVisibility() {
243 | if (st_other < 0 || st_other > 3) throw new ElfException("Unsupported st_other=" + st_other);
244 | return Visibility.values()[st_other];
245 | }
246 |
247 | @Override
248 | public String toString() {
249 | String typeString;
250 | int typeInt = getType();
251 | switch (typeInt) {
252 | case STT_NOTYPE:
253 | typeString = "unspecified";
254 | break;
255 | case STT_OBJECT:
256 | typeString = "object";
257 | break;
258 | case STT_FUNC:
259 | typeString = "function";
260 | break;
261 | case STT_SECTION:
262 | typeString = "section";
263 | break;
264 | case STT_FILE:
265 | typeString = "file";
266 | break;
267 | case STT_LOPROC:
268 | typeString = "loproc";
269 | break;
270 | case STT_HIPROC:
271 | typeString = "hiproc";
272 | break;
273 | default:
274 | typeString = Integer.toString(typeInt);
275 | break;
276 | }
277 |
278 | return "ElfSymbol[name=" + getName() + ", type=" + typeString + ", size=" + st_size + "]";
279 | }
280 | }
281 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/ElfSymbolTableSection.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * An ELF section with symbol information.
5 | *
6 | * This class represents either of two section types:
7 | *
191 | * typedef struct {
192 | * Elf32_Sword d_tag;
193 | * union {
194 | * Elf32_Word d_val;
195 | * Elf32_Addr d_ptr;
196 | * Elf32_Off d_off;
197 | * } d_un;
198 | * } Elf32_Dyn;
199 | *
200 | * typedef struct {
201 | * Elf64_Xword d_tag;
202 | * union {
203 | * Elf64_Xword d_val;
204 | * Elf64_Addr d_ptr;
205 | * } d_un;
206 | * } Elf64_Dyn;
207 | *
208 | */
209 | public static class ElfDynamicStructure {
210 | public ElfDynamicStructure(long d_tag, long d_val_or_ptr) {
211 | this.d_tag = d_tag;
212 | this.d_val_or_ptr = d_val_or_ptr;
213 | }
214 |
215 | /**
216 | * A tag value whose value defines how to interpret {@link #d_val_or_ptr}.
217 | *
18 | *
23 | *
26 | *
30 | */
31 | public final class ElfFile {
32 |
33 | /**
34 | * Relocatable file type. A possible value of {@link #e_type}.
35 | */
36 | public static final int ET_REL = 1;
37 | /**
38 | * Executable file type. A possible value of {@link #e_type}.
39 | */
40 | public static final int ET_EXEC = 2;
41 | /**
42 | * Shared object file type. A possible value of {@link #e_type}.
43 | */
44 | public static final int ET_DYN = 3;
45 | /**
46 | * Core file file type. A possible value of {@link #e_type}.
47 | */
48 | public static final int ET_CORE = 4;
49 |
50 | /**
51 | * 32-bit objects. A possible value of {@link #ei_class}.
52 | */
53 | public static final byte CLASS_32 = 1;
54 | /**
55 | * 64-bit objects. A possible value of {@link #ei_class}.
56 | */
57 | public static final byte CLASS_64 = 2;
58 |
59 | /**
60 | * System V application binary interface. A possible value of {@link #ei_osabi}.
61 | */
62 | public static final byte ABI_SYSTEMV = 0x00;
63 | /**
64 | * HP-UX application binary interface. A possible value of {@link #ei_osabi}.
65 | */
66 | public static final byte ABI_HPUX = 0x01;
67 | /**
68 | * NetBSD application binary interface. A possible value of {@link #ei_osabi}.
69 | */
70 | public static final byte ABI_NETBSD = 0x02;
71 | /**
72 | * Linux application binary interface. A possible value of {@link #ei_osabi}.
73 | */
74 | public static final byte ABI_LINUX = 0x03;
75 | /**
76 | * GNU Hurd application binary interface. A possible value of {@link #ei_osabi}.
77 | */
78 | public static final byte ABI_GNUHERD = 0x04;
79 | /**
80 | * Solaris application binary interface. A possible value of {@link #ei_osabi}.
81 | */
82 | public static final byte ABI_SOLARIS = 0x06;
83 | /**
84 | * AIX application binary interface. A possible value of {@link #ei_osabi}.
85 | */
86 | public static final byte ABI_AIX = 0x07;
87 | /**
88 | * IRIX application binary interface. A possible value of {@link #ei_osabi}.
89 | */
90 | public static final byte ABI_IRIX = 0x08;
91 | /**
92 | * FreeBSD application binary interface. A possible value of {@link #ei_osabi}.
93 | */
94 | public static final byte ABI_FREEBSD = 0x09;
95 | /**
96 | * Tru64 application binary interface. A possible value of {@link #ei_osabi}.
97 | */
98 | public static final byte ABI_TRU64 = 0x0A;
99 | /**
100 | * Novell Modesto application binary interface. A possible value of {@link #ei_osabi}.
101 | */
102 | public static final byte ABI_MODESTO = 0x0B;
103 | /**
104 | * OpenBSD application binary interface. A possible value of {@link #ei_osabi}.
105 | */
106 | public static final byte ABI_OPENBSD = 0x0C;
107 | /**
108 | * OpenVMS application binary interface. A possible value of {@link #ei_osabi}.
109 | */
110 | public static final byte ABI_OPENVMS = 0x0D;
111 | /**
112 | * NonStop Kernel application binary interface. A possible value of {@link #ei_osabi}.
113 | */
114 | public static final byte ABI_NONSTOP = 0x0E;
115 | /**
116 | * AROS application binary interface. A possible value of {@link #ei_osabi}.
117 | */
118 | public static final byte ABI_AROS = 0x0F;
119 | /**
120 | * Fenix OS application binary interface. A possible value of {@link #ei_osabi}.
121 | */
122 | public static final byte ABI_FENIX = 0x10;
123 | /**
124 | * CloudABI application binary interface. A possible value of {@link #ei_osabi}.
125 | */
126 | public static final byte ABI_CLOUD = 0x11;
127 | /**
128 | * Stratus Technologies OpenVOS application binary interface. A possible value of {@link #ei_osabi}.
129 | */
130 | public static final byte ABI_OPENVOS = 0x12;
131 |
132 | /**
133 | * LSB data encoding. A possible value of {@link #ei_data}.
134 | */
135 | public static final byte DATA_LSB = 1;
136 | /**
137 | * MSB data encoding. A possible value of {@link #ei_data}.
138 | */
139 | public static final byte DATA_MSB = 2;
140 |
141 | /**
142 | * No architecture type. A possible value of {@link #e_machine}.
143 | */
144 | public static final int ARCH_NONE = 0;
145 | /**
146 | * AT&T architecture type. A possible value of {@link #e_machine}.
147 | */
148 | public static final int ARCH_ATT = 1;
149 | /**
150 | * SPARC architecture type. A possible value of {@link #e_machine}.
151 | */
152 | public static final int ARCH_SPARC = 2;
153 | /**
154 | * Intel 386 architecture type. A possible value of {@link #e_machine}.
155 | */
156 | public static final int ARCH_i386 = 3;
157 | /**
158 | * Motorola 68000 architecture type. A possible value of {@link #e_machine}.
159 | */
160 | public static final int ARCH_68k = 4;
161 | /**
162 | * Motorola 88000 architecture type. A possible value of {@link #e_machine}.
163 | */
164 | public static final int ARCH_88k = 5;
165 | /**
166 | * Intel 860 architecture type. A possible value of {@link #e_machine}.
167 | */
168 | public static final int ARCH_i860 = 7;
169 | /**
170 | * MIPS architecture type. A possible value of {@link #e_machine}.
171 | */
172 | public static final int ARCH_MIPS = 8;
173 | public static final int ARCH_ARM = 0x28;
174 | public static final int ARCH_X86_64 = 0x3E;
175 | public static final int ARCH_AARCH64 = 0xB7;
176 |
177 | /**
178 | * Byte identifying the size of objects, either {@link #CLASS_32} or {link {@value #CLASS_64}.
179 | */
180 | public final byte ei_class;
181 |
182 | /**
183 | * Returns a byte identifying the data encoding of the processor specific data. This byte will be either
184 | * DATA_INVALID, DATA_LSB or DATA_MSB.
185 | */
186 | public final byte ei_data;
187 |
188 | /**
189 | * Set to 1 for the original and current (as of writing) version of ELF.
190 | */
191 | public final byte ei_version;
192 |
193 | /**
194 | * Identifies the target operating system ABI.
195 | */
196 | public final byte ei_osabi;
197 |
198 | /**
199 | * Further specifies the ABI version. Its interpretation depends on the target ABI.
200 | */
201 | public final byte es_abiversion;
202 |
203 | /**
204 | * Identifies the object file type. One of the ET_* constants in the class.
205 | */
206 | public final short e_type; // Elf32_Half
207 |
208 | /**
209 | * The required architecture. One of the ARCH_* constants in the class.
210 | */
211 | public final short e_machine; // Elf32_Half
212 | /**
213 | * Version
214 | */
215 | public final int e_version; // Elf32_Word
216 | /**
217 | * Virtual address to which the system first transfers control. If there is no entry point for the file the value is
218 | * 0.
219 | */
220 | public final long e_entry; // Elf32_Addr
221 | /**
222 | * e_phoff. Program header table offset in bytes. If there is no program header table the value is 0.
223 | */
224 | public final long e_phoff; // Elf32_Off
225 | /**
226 | * e_shoff. Section header table offset in bytes. If there is no section header table the value is 0.
227 | */
228 | public final long e_shoff; // Elf32_Off
229 | /**
230 | * e_flags. Processor specific flags.
231 | */
232 | public final int e_flags; // Elf32_Word
233 | /**
234 | * e_ehsize. ELF header size in bytes.
235 | */
236 | public final short e_ehsize; // Elf32_Half
237 | /**
238 | * e_phentsize. Size of one entry in the file's program header table in bytes. All entries are the same size.
239 | */
240 | public final short e_phentsize; // Elf32_Half
241 | /**
242 | * e_phnum. Number of {@link ElfSegment} entries in the program header table, 0 if no entries.
243 | */
244 | public final short e_phnum; // Elf32_Half
245 | /**
246 | * e_shentsize. Section header entry size in bytes - all entries are the same size.
247 | */
248 | public final short e_shentsize; // Elf32_Half
249 | /**
250 | * e_shnum. Number of entries in the section header table, 0 if no entries.
251 | */
252 | public final short e_shnum; // Elf32_Half
253 |
254 | /**
255 | * Elf{32,64}_Ehdr#e_shstrndx. Index into the section header table associated with the section name string table.
256 | * SH_UNDEF if there is no section name string table.
257 | */
258 | public final short e_shstrndx; // Elf32_Half
259 |
260 | /**
261 | * MemoizedObject array of section headers associated with this ELF file.
262 | */
263 | private final MemoizedObject(1U << bit) & bitmask
.
17 | */
18 | public static final int NT_GNU_HWCAP = 2;
19 | /**
20 | * A possible value of the {@link #n_type} for a note containing build ID bits as generated by "ld --build-id".
21 | *
24 | */
25 | public final class ElfRelocation {
26 | /**
27 | * The location at which to apply the relocation. For a relocatable file,
28 | * this is the byte offset from the beginning of the section. For an
29 | * executable or shared object, the value is the virtual address.
30 | */
31 | public final long r_offset; // Elf32_Addr or Elf64_Addr
32 |
33 | /**
34 | * This member gives both the symbol table index to which the relocation
35 | * must be made, and the type of relocation to apply. Relocation types are
36 | * processor specific.
37 | */
38 | public final long r_info; // Elf32_Word or Elf64_Xword
39 | private final ElfFile elfFile;
40 |
41 | ElfRelocation(ElfParser parser, long offset) {
42 | parser.seek(offset);
43 |
44 | r_offset = parser.readIntOrLong();
45 | r_info = parser.readIntOrLong();
46 | elfFile = parser.elfFile;
47 | }
48 |
49 | /**
50 | * Corresponds to the ELF32_R_TYPE / ELF64_R_TYPE macros.
51 | *
52 | * @see ElfRelocationTypes
53 | */
54 | public long getType() {
55 | return elfFile.is32Bits() ? (r_info & 0xFF) : ((int) r_info);
56 | }
57 |
58 | /**
59 | * The symbol table index, with respect to which the relocation must be made.
60 | * Use {@link #getSymbol()} to get the resolved {@link ElfSymbol} from this index.
61 | *
14 | * typedef struct {
15 | * Elf32_Addr r_offset;
16 | * Elf32_Word r_info;
17 | * } Elf32_Rel;
18 | *
19 | * typedef struct {
20 | * Elf64_Addr r_offset;
21 | * Elf64_Xword r_info;
22 | * } Elf64_Rel;
23 | *
27 | */
28 | public final class ElfRelocationAddend {
29 | /**
30 | * This member gives the location at which to apply the
31 | * relocation action. For a relocatable file, the value is
32 | * the byte offset from the beginning of the section to the
33 | * storage unit affected by the relocation. For an
34 | * executable file or shared object, the value is the virtual
35 | * address of the storage unit affected by the relocation.
36 | */
37 | public final long r_offset;
38 |
39 | /**
40 | * This member gives both the symbol table index with respect
41 | * to which the relocation must be made and the type of
42 | * relocation to apply. Relocation types are processor-
43 | * specific. When the text refers to a relocation entry's
44 | * relocation type or symbol table index, it means the result
45 | * of applying ELF[32|64]_R_TYPE or ELF[32|64]_R_SYM,
46 | * respectively, to the entry's r_info member.
47 | */
48 | public final long r_info;
49 |
50 | /**
51 | * This member specifies a constant addend used to compute
52 | * the value to be stored into the relocatable field.
53 | */
54 | public final long r_addend; // int32_t or int64_t
55 | private final ElfFile elfFile;
56 |
57 | ElfRelocationAddend(ElfParser parser, long offset) {
58 | parser.seek(offset);
59 |
60 | r_offset = parser.readIntOrLong();
61 | r_info = parser.readIntOrLong();
62 | r_addend = parser.readIntOrLong();
63 | elfFile = parser.elfFile;
64 | }
65 |
66 | /**
67 | * Corresponds to the ELF32_R_TYPE / ELF64_R_TYPE macros.
68 | *
69 | * @see ElfRelocationTypes
70 | */
71 | public long getType() {
72 | return elfFile.is32Bits() ? (r_info & 0xFF) : ((int) r_info);
73 | }
74 |
75 | /**
76 | * The symbol table index, with respect to which the relocation must be made.
77 | * Use {@link #getSymbol()} to get the resolved {@link ElfSymbol} from this index.
78 | *
15 | * typedef struct {
16 | * Elf32_Addr r_offset;
17 | * uint32_t r_info;
18 | * int32_t r_addend;
19 | * } Elf32_Rela;
20 | *
21 | * typedef struct {
22 | * Elf64_Addr r_offset;
23 | * uint64_t r_info;
24 | * int64_t r_addend;
25 | * } Elf64_Rela;
26 | *
9 | * typedef struct {
10 | * uint32_t st_name;
11 | * Elf32_Addr st_value;
12 | * uint32_t st_size;
13 | * unsigned char st_info;
14 | * unsigned char st_other;
15 | * uint16_t st_shndx;
16 | * } Elf32_Sym;
17 | *
18 | * typedef struct {
19 | * uint32_t st_name;
20 | * unsigned char st_info;
21 | * unsigned char st_other;
22 | * uint16_t st_shndx;
23 | * Elf64_Addr st_value;
24 | * uint64_t st_size;
25 | * } Elf64_Sym;
26 | *
27 | */
28 | public final class ElfSymbol {
29 |
30 | enum Visibility {
31 | /**
32 | * The visibility of symbols with the STV_DEFAULT attribute is as specified by the symbol's binding type.
33 | *
8 | *
11 | */
12 | public class ElfSymbolTableSection extends ElfSection {
13 |
14 | public final ElfSymbol[] symbols;
15 |
16 | public ElfSymbolTableSection(ElfParser parser, ElfSectionHeader header) {
17 | super(parser, header);
18 |
19 | int num_entries = (int) (header.sh_size / header.sh_entsize);
20 | symbols = new ElfSymbol[num_entries];
21 | for (int i = 0; i < num_entries; i++) {
22 | final long symbolOffset = header.sh_offset + (i * header.sh_entsize);
23 | symbols[i] = new ElfSymbol(parser, symbolOffset, header.sh_type);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/MappedFile.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | import java.nio.MappedByteBuffer;
4 | import java.nio.ByteBuffer;
5 |
6 | public class MappedFile implements BackingFile{
7 | private final MappedByteBuffer mappedByteBuffer;
8 |
9 | public MappedFile(MappedByteBuffer mappedByteBuffer) {
10 | this.mappedByteBuffer = mappedByteBuffer;
11 | this.mappedByteBuffer.position((int) 0);
12 | }
13 |
14 | public void seek(long offset) {
15 | this.mappedByteBuffer.position((int)(offset)); // we may be limited to sub-4GB mapped filess
16 | }
17 |
18 | public void skip(int bytesToSkip) {
19 | mappedByteBuffer.position(mappedByteBuffer.position() + bytesToSkip);
20 | }
21 |
22 | public short readUnsignedByte() {
23 | int val = -1;
24 | byte temp = mappedByteBuffer.get();
25 | val = temp & 0xFF; // bytes are signed in Java =_= so assigning them to a longer type risks sign extension.
26 | if (val < 0) throw new ElfException("Trying to read outside file");
27 | return (short) val;
28 | }
29 |
30 | public int read(byte[] data) {
31 | mappedByteBuffer.get(data);
32 | return data.length;
33 | }
34 |
35 | public byte get() {
36 | return mappedByteBuffer.get();
37 | }
38 |
39 | public int write(byte[] data) {
40 | mappedByteBuffer.put(data);
41 | return data.length;
42 | }
43 | public void put(byte data) {
44 | mappedByteBuffer.put(data);
45 | }
46 |
47 | public ByteBuffer getBuffer() {
48 | return mappedByteBuffer;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/net/fornwall/jelf/MemoizedObject.java:
--------------------------------------------------------------------------------
1 | package net.fornwall.jelf;
2 |
3 | /**
4 | * A memoized object. Override {@link #computeValue} in subclasses; call {@link #getValue} in using code.
5 | */
6 | abstract class MemoizedObject