定义

Linux平台的一种可执行文件格式,Executable and Linkable Format(可执行 和 可链接 格式 )

的文件

特点

C/C++语言编译生成,动静态。x86汇编、arm汇编。执行速度快,逆行成本高。

生成方式

//call ndk-build.cmd NDK_PROJECT_PATH=. NDK_APPLICATION_MK=jni\\Application.mk
//Application.mk、 Android.mk、xx.c源文件
gcc test.c -c test.o && gcc test.c -o test

Main.java

package com.pediy.test;

public class Main {

public static void main(String[] args) {

String soPath = "so/libhello-jni.so";
ParseSo parseSo = new ParseSo(soPath);

//��ELF�ļ�ͷ��Ϣ
System.out.println("++++++++++++++++++++++Elf Header+++++++++++++++++");
parseSo.readElfHeader(0);

//������ͷ����Ϣ
System.out.println("++++++++++++++++++++++Program Header Table+++++++++++++++++");
int pHeaderOffset = Utils.byte2Int(parseSo.type_32.hdr.e_phoff);
int pHeaderCount = Utils.byte2Int(parseSo.type_32.hdr.e_phnum);
// parseSo.readProgramHeaderList(pHeaderOffset, pHeaderCount);

//����ͷ����Ϣ
System.out.println("++++++++++++++++++++++Section Header Table+++++++++++++++++");
int sHeaderOffset = Utils.byte2Int(parseSo.type_32.hdr.e_shoff);
int sHeaderCount = Utils.byte2Int(parseSo.type_32.hdr.e_shnum);
parseSo.readSectionHeaderList(sHeaderOffset, sHeaderCount);


//�����ű�
System.out.println("++++++++++++++++++++++Symbol Table+++++++++++++++++");
parseSo.printSymbolTableList();

}
}

ParseSo.java

package com.pediy.test;

import static com.pediy.test.ElfType32.*;

public class ParseSo {
public byte[] byteArr;
public ElfType32 type_32 = new ElfType32();
public ElfType64 type_64 = new ElfType64();
public String soPath;

public ParseSo(String pSoPath) {
soPath = pSoPath;
byteArr = Utils.readFile(soPath);
if (byteArr == null)
System.out.println("read file byte failed...");
}

public void readElfHeader(int offset){
if (offset < 0){
System.out.println("ELf Header offset error");
return;
}

// public byte[] e_ident = new byte[16];
// public byte[] e_type = new byte[2];
// public byte[] e_machine = new byte[2];
// public byte[] e_version = new byte[4];
// public byte[] e_entry = new byte[4];
// public byte[] e_phoff = new byte[4];
// public byte[] e_shoff = new byte[4];
// public byte[] e_flags = new byte[4];
// public byte[] e_ehsize = new byte[2];
// public byte[] e_phentsize = new byte[2];
// public byte[] e_phnum = new byte[2];
// public byte[] e_shentsize = new byte[2];
// public byte[] e_shnum = new byte[2];
// public byte[] e_shstrndx = new byte[2];

int off = 0;

for (int i=0; i<type_32.hdr.em.size(); i++){
System.arraycopy(byteArr, off, type_32.hdr.em.get(i), 0, type_32.hdr.em.get(i).length);
off += type_32.hdr.em.get(i).length;
}

System.out.println(type_32.hdr.toString());

}


public void readProgramHeaderList(int offset, int count){
int pHeaderSize = Utils.byte2Short(type_32.hdr.e_phentsize); //����ͷ�ṹ���С

for (int i=0; i<count; i++){
type_32.phdrList.add(readProgramHeader(offset+pHeaderSize*i));
System.out.println("");
System.out.println("ProgramHeader index:" +i+ " :");
System.out.println(type_32.phdrList.get(i));
}
}

public ElfType32.elf32_phdr readProgramHeader(int offset){
// public byte[] p_type = new byte[4];
// public byte[] p_offset = new byte[4];
// public byte[] p_vaddr = new byte[4];
// public byte[] p_paddr = new byte[4];
// public byte[] p_filesz = new byte[4];
// public byte[] p_memsz = new byte[4];
// public byte[] p_flags = new byte[4];
// public byte[] p_align = new byte[4];
ElfType32.elf32_phdr phdr = new ElfType32.elf32_phdr();
System.arraycopy(byteArr, offset+0, phdr.p_type, 0, phdr.p_type.length);
System.arraycopy(byteArr, offset+4, phdr.p_offset, 0, phdr.p_offset.length);
System.arraycopy(byteArr, offset+8, phdr.p_vaddr, 0, phdr.p_vaddr.length);
System.arraycopy(byteArr, offset+12, phdr.p_paddr, 0, phdr.p_paddr.length);
System.arraycopy(byteArr, offset+16, phdr.p_filesz, 0, phdr.p_filesz.length);
System.arraycopy(byteArr, offset+20, phdr.p_memsz, 0, phdr.p_memsz.length);
System.arraycopy(byteArr, offset+24, phdr.p_flags, 0, phdr.p_flags.length);
System.arraycopy(byteArr, offset+28, phdr.p_align, 0, phdr.p_align.length);

return phdr;
}


public void readSectionHeaderList(int offset, int count){
int sHeaderSize = Utils.byte2Short(type_32.hdr.e_shentsize);
int strIndex = Utils.byte2Int(type_32.hdr.e_shstrndx);

readSectionHeader(offset + sHeaderSize*strIndex);

for(int i=0; i<count; i++){
if(i == strIndex)
continue;

System.out.println("");
System.out.println("SectionHeader index:" +i+ " :");
type_32.shdrList.add(readSectionHeader(offset + sHeaderSize*i));
}
}


public ElfType32.elf32_shdr readSectionHeader(int offset){
// public byte[] sh_name = new byte[4];
// public byte[] sh_type = new byte[4];
// public byte[] sh_flags = new byte[4];
// public byte[] sh_addr = new byte[4];
// public byte[] sh_offset = new byte[4];
// public byte[] sh_size = new byte[4];
// public byte[] sh_link = new byte[4];
// public byte[] sh_info = new byte[4];
// public byte[] sh_addralign = new byte[4];
// public byte[] sh_entsize = new byte[4];
ElfType32.elf32_shdr shdr = new ElfType32.elf32_shdr();
System.arraycopy(byteArr, offset+0, shdr.sh_name, 0, shdr.sh_name.length);
System.arraycopy(byteArr, offset+4, shdr.sh_type, 0, shdr.sh_type.length);
System.arraycopy(byteArr, offset+8, shdr.sh_flags, 0, shdr.sh_flags.length);
System.arraycopy(byteArr, offset+12, shdr.sh_addr, 0, shdr.sh_addr.length);
System.arraycopy(byteArr, offset+16, shdr.sh_offset, 0, shdr.sh_offset.length);
System.arraycopy(byteArr, offset+20, shdr.sh_size, 0, shdr.sh_size.length);
System.arraycopy(byteArr, offset+24, shdr.sh_link, 0, shdr.sh_link.length);
System.arraycopy(byteArr, offset+28, shdr.sh_info, 0, shdr.sh_info.length);
System.arraycopy(byteArr, offset+32, shdr.sh_addralign, 0, shdr.sh_addralign.length);
System.arraycopy(byteArr, offset+36, shdr.sh_entsize, 0, shdr.sh_entsize.length);

switch (Utils.byte2Int(shdr.sh_type)){
case ElfType32.SHT_STRTAB:{
ElfStringTable elfStringTable = new ElfStringTable(byteArr, Utils.byte2Int(shdr.sh_offset), Utils.byte2Int(shdr.sh_size));
type_32.elfStringTables.add(elfStringTable);
break;
}
case ElfType32.SHT_DYNSYM:{ //���ű�

int baseOffset = Utils.byte2Int(shdr.sh_offset);
int symCount = Utils.byte2Int(shdr.sh_size)/16;

// public byte[] st_name_ndx = new byte[4];
// public byte[] st_value = new byte[4];
// public byte[] st_size = new byte[4];
// public byte[] st_info = new byte[1];
// public byte[] st_other = new byte[1];
// public byte[] st_shndx = new byte[2];

for (int i=0; i<symCount; i++){
ElfSymbolTable elfSymbolTable = new ElfSymbolTable();
System.arraycopy(byteArr, baseOffset+0+i*16, elfSymbolTable.st_name_ndx, 0, elfSymbolTable.st_name_ndx.length);
System.arraycopy(byteArr, baseOffset+4+i*16, elfSymbolTable.st_value, 0, elfSymbolTable.st_value.length);
System.arraycopy(byteArr, baseOffset+8+i*16, elfSymbolTable.st_size, 0, elfSymbolTable.st_size.length);
System.arraycopy(byteArr, baseOffset+12+i*16, elfSymbolTable.st_info, 0, elfSymbolTable.st_info.length);
System.arraycopy(byteArr, baseOffset+13+i*16, elfSymbolTable.st_other, 0, elfSymbolTable.st_other.length);
System.arraycopy(byteArr, baseOffset+14+i*16, elfSymbolTable.st_shndx, 0, elfSymbolTable.st_shndx.length);

switch (elfSymbolTable.getBinding()){
case STB_LOCAL:
case STB_GLOBAL:{

}
}
switch (elfSymbolTable.getType()){
case STT_NOTYPE:{

}
}

type_32.elfSymbolTableList.add(elfSymbolTable);
}

}

default:
break;

}

String tmp = type_32.elfStringTables.get(0).getCStringByOffset(Utils.byte2Int(shdr.sh_name));
String pri = "sh_name: "+tmp /*Utils.byte2Int(sh_name)*/
+"\nsh_type:"+Utils.bytes2HexString(shdr.sh_type)
+"\nsh_flags:"+Utils.bytes2HexString(shdr.sh_flags)
+"\nsh_add:"+Utils.bytes2HexString(shdr.sh_addr)
+"\nsh_offset:"+Utils.bytes2HexString(shdr.sh_offset)
+"\nsh_size:"+Utils.bytes2HexString(shdr.sh_size)
+"\nsh_link:"+Utils.bytes2HexString(shdr.sh_link)
+"\nsh_info:"+Utils.bytes2HexString(shdr.sh_info)
+"\nsh_addralign:"+Utils.bytes2HexString(shdr.sh_addralign)
+"\nsh_entsize:"+ Utils.bytes2HexString(shdr.sh_entsize);
System.out.println(pri);

return shdr;
}

public void printSymbolTableList(){
for (int i=0; i<type_32.elfSymbolTableList.size(); i++){
System.out.println("");
int symName = Utils.byte2Int(type_32.elfSymbolTableList.get(i).st_name_ndx);
System.out.println("symbol index: " + i + " :");
System.out.println(type_32.elfStringTables.get(1).getCStringByOffset(symName));
}
}
}

ElfType32.java、ElfType64.java、ElfStringTable.java、ElfSymbolTable.java就省略了,官网都能找到。