#include <memory.h>
#include <libelf.h>
#include <sys/link.h>
#include <decl.h>
#include <msg.h>
#include <string.h>
typedef struct {
Elf64_Xword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
} Elf64_Rel;
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
typedef struct {
Elf64_Half si_boundto;
Elf64_Half si_flags;
} Elf64_Syminfo;
enum
{
A_M7, A_M6, A_M5, A_M4, A_M3, A_M2, A_M1, A_M0,
A_sizeof
};
enum
{
H_M1, H_M0,
H_sizeof
};
enum
{
L_M7, L_M6, L_M5, L_M4, L_M3, L_M2, L_M1, L_M0,
L_sizeof
};
enum
{
M1_value_M7, M1_value_M6, M1_value_M5, M1_value_M4, M1_value_M3, M1_value_M2, M1_value_M1, M1_value_M0,
M1_info_M7, M1_info_M6, M1_info_M5, M1_info_M4, M1_info_M3, M1_info_M2, M1_info_M1, M1_info_M0,
M1_poffset_M7, M1_poffset_M6, M1_poffset_M5, M1_poffset_M4, M1_poffset_M3, M1_poffset_M2, M1_poffset_M1, M1_poffset_M0,
M1_repeat_M1, M1_repeat_M0,
M1_stride_M1, M1_stride_M0,
M1_sizeof
};
enum
{
MP1_value_L0, MP1_value_L1, MP1_value_L2, MP1_value_L3, MP1_value_L4, MP1_value_L5, MP1_value_L6, MP1_value_L7,
MP1_info_L0, MP1_info_L1, MP1_info_L2, MP1_info_L3, MP1_info_L4, MP1_info_L5, MP1_info_L6, MP1_info_L7,
MP1_poffset_L0, MP1_poffset_L1, MP1_poffset_L2, MP1_poffset_L3, MP1_poffset_L4, MP1_poffset_L5, MP1_poffset_L6, MP1_poffset_L7,
MP1_repeat_L0, MP1_repeat_L1,
MP1_stride_L0, MP1_stride_L1,
MP1_padding_L0, MP1_padding_L1, MP1_padding_L2, MP1_padding_L3
};
enum
{
MP1_value_M7, MP1_value_M6, MP1_value_M5, MP1_value_M4, MP1_value_M3, MP1_value_M2, MP1_value_M1, MP1_value_M0,
MP1_info_M7, MP1_info_M6, MP1_info_M5, MP1_info_M4, MP1_info_M3, MP1_info_M2, MP1_info_M1, MP1_info_M0,
MP1_poffset_M7, MP1_poffset_M6, MP1_poffset_M5, MP1_poffset_M4, MP1_poffset_M3, MP1_poffset_M2, MP1_poffset_M1, MP1_poffset_M0,
MP1_repeat_M1, MP1_repeat_M0,
MP1_stride_M1, MP1_stride_M0,
MP1_padding_M3, MP1_padding_M2, MP1_padding_M1, MP1_padding_M0,
MP1_sizeof
};
enum
{
O_M7, O_M6, O_M5, O_M4, O_M3, O_M2, O_M1, O_M0,
O_sizeof
};
enum
{
W_M3, W_M2, W_M1, W_M0,
W_sizeof
};
enum
{
X_M7, X_M6, X_M5, X_M4, X_M3, X_M2, X_M1, X_M0,
X_sizeof
};
enum
{
D1_tag_M7, D1_tag_M6, D1_tag_M5, D1_tag_M4, D1_tag_M3, D1_tag_M2, D1_tag_M1, D1_tag_M0,
D1_val_M7, D1_val_M6, D1_val_M5, D1_val_M4, D1_val_M3, D1_val_M2, D1_val_M1, D1_val_M0,
D1_sizeof
};
#define E1_Nident 16
enum {
E1_ident_M_Z = E1_Nident - 1,
E1_type_M1, E1_type_M0,
E1_machine_M1, E1_machine_M0,
E1_version_M3, E1_version_M2, E1_version_M1, E1_version_M0,
E1_entry_M7, E1_entry_M6, E1_entry_M5, E1_entry_M4, E1_entry_M3, E1_entry_M2, E1_entry_M1, E1_entry_M0,
E1_phoff_M7, E1_phoff_M6, E1_phoff_M5, E1_phoff_M4, E1_phoff_M3, E1_phoff_M2, E1_phoff_M1, E1_phoff_M0,
E1_shoff_M7, E1_shoff_M6, E1_shoff_M5, E1_shoff_M4, E1_shoff_M3, E1_shoff_M2, E1_shoff_M1, E1_shoff_M0,
E1_flags_M3, E1_flags_M2, E1_flags_M1, E1_flags_M0,
E1_ehsize_M1, E1_ehsize_M0,
E1_phentsize_M1, E1_phentsize_M0,
E1_phnum_M1, E1_phnum_M0,
E1_shentsize_M1, E1_shentsize_M0,
E1_shnum_M1, E1_shnum_M0,
E1_shstrndx_M1, E1_shstrndx_M0,
E1_sizeof
};
enum
{
N1_namesz_M3, N1_namesz_M2, N1_namesz_M1, N1_namesz_M0,
N1_descsz_M3, N1_descsz_M2, N1_descsz_M1, N1_descsz_M0,
N1_type_M3, N1_type_M2, N1_type_M1, N1_type_M0,
N1_sizeof
};
enum
{
P1_type_M3, P1_type_M2, P1_type_M1, P1_type_M0,
P1_flags_M3, P1_flags_M2, P1_flags_M1, P1_flags_M0,
P1_offset_M7, P1_offset_M6, P1_offset_M5, P1_offset_M4, P1_offset_M3, P1_offset_M2, P1_offset_M1, P1_offset_M0,
P1_vaddr_M7, P1_vaddr_M6, P1_vaddr_M5, P1_vaddr_M4, P1_vaddr_M3, P1_vaddr_M2, P1_vaddr_M1, P1_vaddr_M0,
P1_paddr_M7, P1_paddr_M6, P1_paddr_M5, P1_paddr_M4, P1_paddr_M3, P1_paddr_M2, P1_paddr_M1, P1_paddr_M0,
P1_filesz_M7, P1_filesz_M6, P1_filesz_M5, P1_filesz_M4, P1_filesz_M3, P1_filesz_M2, P1_filesz_M1, P1_filesz_M0,
P1_memsz_M7, P1_memsz_M6, P1_memsz_M5, P1_memsz_M4, P1_memsz_M3, P1_memsz_M2, P1_memsz_M1, P1_memsz_M0,
P1_align_M7, P1_align_M6, P1_align_M5, P1_align_M4, P1_align_M3, P1_align_M2, P1_align_M1, P1_align_M0,
P1_sizeof
};
enum
{
R1_offset_M7, R1_offset_M6, R1_offset_M5, R1_offset_M4, R1_offset_M3, R1_offset_M2, R1_offset_M1, R1_offset_M0,
R1_info_M7, R1_info_M6, R1_info_M5, R1_info_M4, R1_info_M3, R1_info_M2, R1_info_M1, R1_info_M0,
R1_sizeof
};
enum
{
RA1_offset_M7, RA1_offset_M6, RA1_offset_M5, RA1_offset_M4, RA1_offset_M3, RA1_offset_M2, RA1_offset_M1, RA1_offset_M0,
RA1_info_M7, RA1_info_M6, RA1_info_M5, RA1_info_M4, RA1_info_M3, RA1_info_M2, RA1_info_M1, RA1_info_M0,
RA1_addend_M7, RA1_addend_M6, RA1_addend_M5, RA1_addend_M4, RA1_addend_M3, RA1_addend_M2, RA1_addend_M1, RA1_addend_M0,
RA1_sizeof
};
enum
{
SH1_name_M3, SH1_name_M2, SH1_name_M1, SH1_name_M0,
SH1_type_M3, SH1_type_M2, SH1_type_M1, SH1_type_M0,
SH1_flags_M7, SH1_flags_M6, SH1_flags_M5, SH1_flags_M4, SH1_flags_M3, SH1_flags_M2, SH1_flags_M1, SH1_flags_M0,
SH1_addr_M7, SH1_addr_M6, SH1_addr_M5, SH1_addr_M4, SH1_addr_M3, SH1_addr_M2, SH1_addr_M1, SH1_addr_M0,
SH1_offset_M7, SH1_offset_M6, SH1_offset_M5, SH1_offset_M4, SH1_offset_M3, SH1_offset_M2, SH1_offset_M1, SH1_offset_M0,
SH1_size_M7, SH1_size_M6, SH1_size_M5, SH1_size_M4, SH1_size_M3, SH1_size_M2, SH1_size_M1, SH1_size_M0,
SH1_link_M3, SH1_link_M2, SH1_link_M1, SH1_link_M0,
SH1_info_M3, SH1_info_M2, SH1_info_M1, SH1_info_M0,
SH1_addralign_M7, SH1_addralign_M6, SH1_addralign_M5, SH1_addralign_M4, SH1_addralign_M3, SH1_addralign_M2, SH1_addralign_M1, SH1_addralign_M0,
SH1_entsize_M7, SH1_entsize_M6, SH1_entsize_M5, SH1_entsize_M4, SH1_entsize_M3, SH1_entsize_M2, SH1_entsize_M1, SH1_entsize_M0,
SH1_sizeof
};
enum
{
ST1_name_M3, ST1_name_M2, ST1_name_M1, ST1_name_M0,
ST1_info_M,
ST1_other_M,
ST1_shndx_M1, ST1_shndx_M0,
ST1_value_M7, ST1_value_M6, ST1_value_M5, ST1_value_M4, ST1_value_M3, ST1_value_M2, ST1_value_M1, ST1_value_M0,
ST1_size_M7, ST1_size_M6, ST1_size_M5, ST1_size_M4, ST1_size_M3, ST1_size_M2, ST1_size_M1, ST1_size_M0,
ST1_sizeof
};
enum
{
SI1_boundto_M1, SI1_boundto_M0,
SI1_flags_M1, SI1_flags_M0,
SI1_sizeof
};
enum
{
VD1_version_M1, VD1_version_M0,
VD1_flags_M1, VD1_flags_M0,
VD1_ndx_M1, VD1_ndx_M0,
VD1_cnt_M1, VD1_cnt_M0,
VD1_hash_M3, VD1_hash_M2, VD1_hash_M1, VD1_hash_M0,
VD1_aux_M3, VD1_aux_M2, VD1_aux_M1, VD1_aux_M0,
VD1_next_M3, VD1_next_M2, VD1_next_M1, VD1_next_M0,
VD1_sizeof
};
enum
{
VDA1_name_M3, VDA1_name_M2, VDA1_name_M1, VDA1_name_M0,
VDA1_next_M3, VDA1_next_M2, VDA1_next_M1, VDA1_next_M0,
VDA1_sizeof
};
enum
{
VN1_version_M1, VN1_version_M0,
VN1_cnt_M1, VN1_cnt_M0,
VN1_file_M3, VN1_file_M2, VN1_file_M1, VN1_file_M0,
VN1_aux_M3, VN1_aux_M2, VN1_aux_M1, VN1_aux_M0,
VN1_next_M3, VN1_next_M2, VN1_next_M1, VN1_next_M0,
VN1_sizeof
};
enum
{
VNA1_hash_M3, VNA1_hash_M2, VNA1_hash_M1, VNA1_hash_M0,
VNA1_flags_M1, VNA1_flags_M0,
VNA1_other_M1, VNA1_other_M0,
VNA1_name_M3, VNA1_name_M2, VNA1_name_M1, VNA1_name_M0,
VNA1_next_M3, VNA1_next_M2, VNA1_next_M1, VNA1_next_M0,
VNA1_sizeof
};
static const struct {
size_t s_filesz,
s_memsz;
} fmsize [EV_CURRENT] [ELF_T_NUM] =
{
{
{ 1, 1 },
{ A_sizeof, sizeof (Elf64_Addr) },
{ D1_sizeof, sizeof (Elf64_Dyn) },
{ E1_sizeof, sizeof (Elf64_Ehdr) },
{ H_sizeof, sizeof (Elf64_Half) },
{ O_sizeof, sizeof (Elf64_Off) },
{ P1_sizeof, sizeof (Elf64_Phdr) },
{ RA1_sizeof, sizeof (Elf64_Rela) },
{ R1_sizeof, sizeof (Elf64_Rel) },
{ SH1_sizeof, sizeof (Elf64_Shdr) },
{ W_sizeof, sizeof (Elf64_Sword) },
{ ST1_sizeof, sizeof (Elf64_Sym) },
{ W_sizeof, sizeof (Elf64_Word) },
{ 1, 1 },
{ 1, 1 },
{ X_sizeof, sizeof (Elf64_Sxword) },
{ X_sizeof, sizeof (Elf64_Xword) },
{ SI1_sizeof, sizeof (Elf64_Syminfo) },
{ 1, 1},
},
};
static const Elf_Type mtype[EV_CURRENT][SHT_NUM] =
{
{
ELF_T_BYTE,
ELF_T_BYTE,
ELF_T_SYM,
ELF_T_BYTE,
ELF_T_RELA,
ELF_T_WORD,
ELF_T_DYN,
ELF_T_NOTE,
ELF_T_BYTE,
ELF_T_REL,
ELF_T_BYTE,
ELF_T_SYM,
ELF_T_BYTE,
ELF_T_BYTE,
ELF_T_ADDR,
ELF_T_ADDR,
ELF_T_ADDR,
ELF_T_WORD,
ELF_T_WORD
},
};
size_t
elf64_fsize(Elf_Type type, size_t count, unsigned ver)
{
if (--ver >= EV_CURRENT) {
_elf_seterr(EREQ_VER, 0);
return (0);
}
if ((unsigned)type >= ELF_T_NUM) {
_elf_seterr(EREQ_TYPE, 0);
return (0);
}
return (fmsize[ver][type].s_filesz * count);
}
size_t
_elf64_msize(Elf_Type type, unsigned ver)
{
return (fmsize[ver - 1][type].s_memsz);
}
Elf_Type
_elf64_mtype(Elf * elf, Elf64_Word shtype, unsigned ver)
{
#pragma unused(elf)
if (shtype < SHT_NUM)
return (mtype[ver - 1][shtype]);
return (ELF_T_BYTE);
}
static Elf_Data *
xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode)
{
size_t cnt, dsz, ssz;
unsigned type;
unsigned dver, sver;
unsigned _encode;
if (dst == 0 || src == 0)
return (0);
if (--encode >= (ELFDATANUM - 1)) {
_elf_seterr(EREQ_ENCODE, 0);
return (0);
}
if ((dver = dst->d_version - 1) >= EV_CURRENT ||
(sver = src->d_version - 1) >= EV_CURRENT) {
_elf_seterr(EREQ_VER, 0);
return (0);
}
if ((type = src->d_type) >= ELF_T_NUM) {
_elf_seterr(EREQ_TYPE, 0);
return (0);
}
dsz = fmsize[dver][type].s_memsz;
ssz = fmsize[sver][type].s_filesz;
cnt = src->d_size / ssz;
if (dst->d_size < dsz * cnt) {
_elf_seterr(EREQ_DSZ, 0);
return (0);
}
ELFACCESSDATA(_encode, _elf_encode)
if ((_encode == (encode + 1)) && (dsz == ssz)) {
if (src->d_buf && src->d_buf != dst->d_buf)
(void) memcpy(dst->d_buf, src->d_buf, src->d_size);
dst->d_type = src->d_type;
dst->d_size = src->d_size;
return (dst);
} else {
_elf_seterr(EREQ_NOTSUP, 0);
return (0);
}
}
Elf_Data *
elf64_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned encode)
{
return (xlate(dst, src, encode));
}