Skip to content

Commit

Permalink
Land #777: AtU8 UTF8 atoms chunk decompilation
Browse files Browse the repository at this point in the history
  • Loading branch information
KronicDeth authored Aug 7, 2017
2 parents 53407b5 + 9ce3506 commit 1f34fa3
Show file tree
Hide file tree
Showing 9 changed files with 627 additions and 16 deletions.
10 changes: 9 additions & 1 deletion src/org/elixir_lang/beam/Beam.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.elixir_lang.beam.chunk.Chunk.TypeID.ATOM;
import static org.elixir_lang.beam.chunk.Chunk.TypeID.ATU8;
import static org.elixir_lang.beam.chunk.Chunk.TypeID.EXPT;
import static org.elixir_lang.beam.chunk.Chunk.length;
import static org.elixir_lang.beam.chunk.Chunk.typeID;
Expand Down Expand Up @@ -166,7 +168,13 @@ public Atoms atoms() {
Chunk chunk = chunk(ATOM);

if (chunk != null) {
atoms = Atoms.from(chunk);
atoms = Atoms.from(chunk, ATOM, Charset.forName("LATIN1"));
} else {
chunk = chunk(ATU8);

if (chunk != null) {
atoms = Atoms.from(chunk, ATU8, Charset.forName("UTF-8"));
}
}

return atoms;
Expand Down
9 changes: 8 additions & 1 deletion src/org/elixir_lang/beam/Decompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import java.util.SortedSet;

import static org.elixir_lang.beam.chunk.Chunk.TypeID.ATOM;
import static org.elixir_lang.psi.call.name.Function.DEF;
import static org.elixir_lang.psi.call.name.Function.DEFMACRO;
import static org.elixir_lang.psi.call.name.Module.ELIXIR_PREFIX;
Expand All @@ -36,7 +37,7 @@ public class Decompiler implements BinaryFileDecompiler {

@NotNull
private static CharSequence decompiled(@Nullable Beam beam) {
StringBuilder decompiled = new StringBuilder("Decompilated Error");
StringBuilder decompiled = new StringBuilder("# Decompilation Error: ");

if (beam != null) {
Atoms atoms = beam.atoms();
Expand All @@ -57,8 +58,14 @@ private static CharSequence decompiled(@Nullable Beam beam) {
appendExports(decompiled, beam, atoms);

decompiled.append("end\n");
} else {
decompiled.append("No module name found in ").append(ATOM).append(" chunk in BEAM");
}
} else {
decompiled.append("No ").append(ATOM).append(" chunk found in BEAM");
}
} else {
decompiled.append("BEAM format could not be read");
}

return decompiled;
Expand Down
21 changes: 8 additions & 13 deletions src/org/elixir_lang/beam/chunk/Atoms.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.elixir_lang.beam.chunk.Chunk.TypeID.ATOM;
import static org.elixir_lang.beam.chunk.Chunk.unsignedByte;
import static org.elixir_lang.beam.chunk.Chunk.unsignedInt;

Expand All @@ -18,13 +18,9 @@ public class Atoms {
*/

@NotNull
private List<String> atomList;
private final List<String> atomList;

/*
* Constructors
*/

public Atoms(@NotNull List<String> atomList) {
private Atoms(@NotNull List<String> atomList) {
this.atomList = Collections.unmodifiableList(atomList);
}

Expand All @@ -33,23 +29,23 @@ public Atoms(@NotNull List<String> atomList) {
*/

@Nullable
public static Atoms from(@NotNull Chunk chunk) {
public static Atoms from(@NotNull Chunk chunk, @NotNull Chunk.TypeID typeID, @NotNull Charset charset) {
Atoms atoms = null;

if (chunk.typeID.equals(ATOM.toString()) && chunk.data.length >= 4) {
if (chunk.typeID.equals(typeID.toString()) && chunk.data.length >= 4) {
int offset = 0;
Pair<Long, Integer> atomCountByteCount = unsignedInt(chunk.data, offset);
long atomCount = atomCountByteCount.first;
offset += atomCountByteCount.second;

List<String> atomList = new ArrayList<String>();
List<String> atomList = new ArrayList<>();

for (long i = 0; i < atomCount; i++) {
Pair<Integer, Integer> atomLengthByteCount = unsignedByte(chunk.data[offset]);
int atomLength = atomLengthByteCount.first;
offset += atomLengthByteCount.second;

String entry = new String(chunk.data, offset, atomLength);
String entry = new String(chunk.data, offset, atomLength, charset);
offset += atomLength;
atomList.add(entry);
}
Expand All @@ -65,9 +61,8 @@ public static Atoms from(@NotNull Chunk chunk) {
*/

/**
*
* @param index 1-based index. 1 is reserved for {#link moduleName}
* @return atom if
* @return atom if it exists
*/
@Nullable
public String get(int index) {
Expand Down
1 change: 1 addition & 0 deletions src/org/elixir_lang/beam/chunk/Chunk.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static Pair<Long, Integer> unsignedInt(@NotNull byte[] bytes, int offset) {

public enum TypeID {
ATOM("Atom"),
ATU8("AtU8"),
EXPT("ExpT");

private final String typeID;
Expand Down
Binary file not shown.
21 changes: 21 additions & 0 deletions testData/org/elixir_lang/beam/decompiler/OTP20/Elixir.AtU8Test.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Source code recreated from a .beam file by IntelliJ Elixir
defmodule AtU8Test do

# Macros

def __info__(p0) do
# body not decompiled
end

def module_info() do
# body not decompiled
end

def module_info(p0) do
# body not decompiled
end

def こんにちは世界() do
# body not decompiled
end
end
Binary file not shown.
Loading

0 comments on commit 1f34fa3

Please sign in to comment.