#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <assert.h>
static off_t lisp_rel_section_offset;
static ssize_t lisp_rel_section_size;
off_t search_for_elf_core(int fd)
{
Elf64_Ehdr ehdr;
if (lseek(fd, 0, SEEK_SET) != 0 ||
read(fd, &ehdr, sizeof ehdr) != sizeof ehdr) {
fprintf(stderr, "failed to read elf header\n");
return 0;
}
unsigned long result = 0;
char* shdrs = 0;
char * shstrtab_strbuf = 0;
int nbytes = ehdr.e_shentsize * ehdr.e_shnum;
if ((shdrs = malloc(nbytes)) == NULL ||
lseek(fd, ehdr.e_shoff, SEEK_SET) != (Elf64_Sxword)ehdr.e_shoff ||
read(fd, shdrs, nbytes) != nbytes)
goto done;
Elf64_Shdr* shdr = (Elf64_Shdr*)(shdrs + ehdr.e_shentsize * ehdr.e_shstrndx);
if ((shstrtab_strbuf = malloc(shdr->sh_size)) == NULL ||
lseek(fd, shdr->sh_offset, SEEK_SET) != (Elf64_Sxword)shdr->sh_offset ||
read(fd, shstrtab_strbuf, shdr->sh_size) != (Elf64_Sxword)shdr->sh_size)
goto done;
int i;
for(i=1;i<ehdr.e_shnum;++i) {
Elf64_Shdr* h = (Elf64_Shdr*)(shdrs + ehdr.e_shentsize * i);
if (!strcmp(&shstrtab_strbuf[h->sh_name], "lisp.core")) {
assert(!result);
result = h->sh_offset;
if (lisp_rel_section_offset) break;
} else if (!strcmp(&shstrtab_strbuf[h->sh_name], "lisp.rel")) {
assert(!lisp_rel_section_offset);
lisp_rel_section_offset = h->sh_offset;
lisp_rel_section_size = h->sh_size;
if (result) break;
}
}
done:
if (shstrtab_strbuf) free(shstrtab_strbuf);
if (shdrs) free(shdrs);
return result;
}
int apply_pie_relocs(long code_space_translation,
long dynamic_space_translation,
int fd)
{
if (dynamic_space_translation != 0 || lisp_rel_section_size == 0)
return 0;
int n_relocs = lisp_rel_section_size / sizeof (long);
unsigned long **ptrs = malloc(n_relocs * sizeof (long));
if (!ptrs) return 0;
int success = 0;
if (lseek(fd, lisp_rel_section_offset, SEEK_SET) == lisp_rel_section_offset &&
read(fd, ptrs, lisp_rel_section_size) == lisp_rel_section_size) {
int i;
for (i = 1; i<n_relocs; ++i) {
unsigned long *vaddr = ptrs[i];
*vaddr += code_space_translation;
}
success = 1;
}
free(ptrs);
return success;
}