+#define GET_ELF_UINT16(arr) (endianess ? (((uint32_t) arr[0] << 8) | (((uint32_t) arr[1]))) : ((uint32_t) arr[0] | (((uint32_t) arr[1]) << 8)))
+
+#define GET_ELF_UINT32(arr) (endianess ? (((uint32_t) arr[0] << 24) | (((uint32_t) arr[1]) << 16) | (((uint32_t) arr[2]) << 8) | (((uint32_t) arr[3]))) \
+ : ((uint32_t) arr[0] | (((uint32_t) arr[1]) << 8) | (((uint32_t) arr[2]) << 16) | (((uint32_t) arr[3]) << 24)))
+
+static void elf_get_symbols (void *object, long offset, int endianess) {
+
+ struct elf_exec *hdr = (struct elf_exec *) object;
+
+ unsigned long e_shnum = GET_ELF_UINT16 (hdr->e_shnum);
+ unsigned long e_shoff = GET_ELF_UINT32 (hdr->e_shoff);
+ unsigned long e_shentsize = GET_ELF_UINT16 (hdr->e_shentsize);
+
+ unsigned long sh_link, sh_offset, sh_entsize, sh_size;
+ unsigned long sym_strtab_size, i, j, st_name;
+
+ struct elf_shdr strtabhdr;
+ struct elf_shdr shdr;
+ struct elf_sym elf_symbol;
+
+ struct strtab *strtab;
+ char *sym_strtab;
+
+ for (i = 1; i < e_shnum; i++) {
+
+ memcpy (&shdr, (char *) object + e_shoff + i * e_shentsize, sizeof (shdr));
+
+ if (GET_ELF_UINT32 (shdr.sh_type) != 2) {
+ continue;
+ }
+
+ sh_link = GET_ELF_UINT32 (shdr.sh_link);
+ sh_offset = GET_ELF_UINT32 (shdr.sh_offset);
+
+ if (sh_link == 0 || sh_link >= e_shnum) {
+ continue;
+ }
+
+ memcpy (&strtabhdr, (char *) object + e_shoff + sh_link * e_shentsize, sizeof (strtabhdr));
+
+ if (GET_ELF_UINT32 (strtabhdr.sh_type) != 3) {
+ continue;
+ }
+
+ sym_strtab_size = GET_ELF_UINT32 (strtabhdr.sh_size);
+ sym_strtab = (char *) object + GET_ELF_UINT32 (strtabhdr.sh_offset);
+
+ if ((sh_entsize = GET_ELF_UINT32 (shdr.sh_entsize)) < sizeof (elf_symbol)) {
+ continue;
+ }
+
+ sh_size = GET_ELF_UINT32 (shdr.sh_size);
+
+ for (j = 1; j < sh_size / sh_entsize; j++) {
+
+ memcpy (&elf_symbol, (char *) object + sh_offset + j * sh_entsize, sizeof (elf_symbol));
+
+ if ((st_name = GET_ELF_UINT32 (elf_symbol.st_name)) >= sym_strtab_size) {
+ continue;
+ }
+
+ if (GET_ELF_UINT16 (elf_symbol.st_shndx) == 0 || (elf_symbol.st_info[0] >> 4) != 1) {
+ continue;
+ }
+
+ if (sym_strtab[st_name] != '\0') {
+
+ strtab = xmalloc (sizeof (*strtab));
+ strtab->offset = offset;
+
+ strtab->name = xstrdup (sym_strtab + st_name);
+ strtab->length = strlen (strtab->name);
+
+ add_strtab (&gstrtab, strtab);
+
+ }
+
+ }
+
+ }
+
+}
+