#include <string.h>
#include "decl.h"
#include "msg.h"
#define EDATA_CLASS(edata) \
(((Dnode *)(edata))->db_scn->s_elf->ed_class)
#define EDATA_ELF(edata) \
(((Dnode *)(edata))->db_scn->s_elf)
#define EDATA_SCN(edata) \
(((Dnode *)(edata))->db_scn)
#define EDATA_READLOCKS(edata) \
READLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
#define EDATA_READUNLOCKS(edata) \
READUNLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
int
gelf_getclass(Elf *elf)
{
if (elf == NULL)
return (0);
return (elf->ed_class);
}
GElf_Ehdr *
gelf_getehdr(Elf *elf, GElf_Ehdr *dst)
{
int class;
if (elf == NULL)
return (NULL);
class = gelf_getclass(elf);
if (class == ELFCLASS32) {
Elf32_Ehdr * e = elf32_getehdr(elf);
if (e == NULL)
return (NULL);
ELFRLOCK(elf);
(void) memcpy(dst->e_ident, e->e_ident, EI_NIDENT);
dst->e_type = e->e_type;
dst->e_machine = e->e_machine;
dst->e_version = e->e_version;
dst->e_entry = (Elf64_Addr)e->e_entry;
dst->e_phoff = (Elf64_Off)e->e_phoff;
dst->e_shoff = (Elf64_Off)e->e_shoff;
dst->e_flags = e->e_flags;
dst->e_ehsize = e->e_ehsize;
dst->e_phentsize = e->e_phentsize;
dst->e_phnum = e->e_phnum;
dst->e_shentsize = e->e_shentsize;
dst->e_shnum = e->e_shnum;
dst->e_shstrndx = e->e_shstrndx;
ELFUNLOCK(elf);
return (dst);
} else if (class == ELFCLASS64) {
Elf64_Ehdr * e = elf64_getehdr(elf);
if (e == NULL)
return (NULL);
ELFRLOCK(elf);
*dst = *e;
ELFUNLOCK(elf);
return (dst);
}
_elf_seterr(EREQ_CLASS, 0);
return (NULL);
}
GElf_Shdr *
gelf_getshdr(Elf_Scn *scn, GElf_Shdr *dst)
{
if (scn == NULL)
return (NULL);
if (scn->s_elf->ed_class == ELFCLASS32) {
Elf32_Shdr *s = elf32_getshdr(scn);
if (s == NULL)
return (NULL);
READLOCKS(scn->s_elf, scn);
dst->sh_name = s->sh_name;
dst->sh_type = s->sh_type;
dst->sh_flags = (Elf64_Xword)s->sh_flags;
dst->sh_addr = (Elf64_Addr)s->sh_addr;
dst->sh_offset = (Elf64_Off)s->sh_offset;
dst->sh_size = (Elf64_Xword)s->sh_size;
dst->sh_link = s->sh_link;
dst->sh_info = s->sh_info;
dst->sh_addralign = (Elf64_Xword)s->sh_addralign;
dst->sh_entsize = (Elf64_Xword)s->sh_entsize;
READUNLOCKS(scn->s_elf, scn);
return (dst);
} else if (scn->s_elf->ed_class == ELFCLASS64) {
Elf64_Shdr *s = elf64_getshdr(scn);
if (s == NULL)
return (NULL);
READLOCKS(scn->s_elf, scn);
*dst = *(Elf64_Shdr *)s;
READUNLOCKS(scn->s_elf, scn);
return (dst);
}
_elf_seterr(EREQ_CLASS, 0);
return (NULL);
}
GElf_Sym *
gelf_getsym(Elf_Data * data, int ndx, GElf_Sym * dst)
{
int class;
size_t entsize;
if (data == NULL)
return (NULL);
class = EDATA_CLASS(data);
if (class == ELFCLASS32)
entsize = sizeof (Elf32_Sym);
else if (class == ELFCLASS64)
entsize = sizeof (GElf_Sym);
else {
_elf_seterr(EREQ_CLASS, 0);
return (NULL);
}
EDATA_READLOCKS(data);
if ((entsize * ndx) >= data->d_size) {
_elf_seterr(EREQ_RAND, 0);
dst = NULL;
} else if (class == ELFCLASS32) {
Elf32_Sym *s;
s = &(((Elf32_Sym *)data->d_buf)[ndx]);
dst->st_name = s->st_name;
dst->st_value = (Elf64_Addr)s->st_value;
dst->st_size = (Elf64_Xword)s->st_size;
dst->st_info = ELF64_ST_INFO(ELF32_ST_BIND(s->st_info),
ELF32_ST_TYPE(s->st_info));
dst->st_other = s->st_other;
dst->st_shndx = s->st_shndx;
} else
*dst = ((GElf_Sym *)data->d_buf)[ndx];
EDATA_READUNLOCKS(data);
return (dst);
}