Newer
Older
/*
This code was written by Fred Gilham, and has been placed in the
public domain. It is provided "as-is" and without warantee of any
kind.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <elf.h>
#include "os.h"
static char elf_magic_string[] = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3};
/* Note: FreeBSD has nice macros that let you use Elf_Ehdr
etc. declarations; unfortunately Linux doesn't have this so you
have to do Elf32_Ehdr etc. Bad for moving to 64 bits.... */
#if defined(__linux__) || defined(sparc) || defined(__NetBSD__)
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
#endif
static Elf_Ehdr eh;
/* Names of the Lisp image ELF sections. These names must be the same
as the corresponding names found in the linker script and the
process-core utility. */
static char *core_section_names[] = {"CORDYN", "CORSTA", "CORRO"};
static void
eread(int d, void *buf, size_t nbytes, const char *func)
{
int res = read(d, buf, nbytes);
if (res == -1) {
perror(func);
exit(-1);
}
if (res < nbytes) {
fprintf(stderr, "Short read in %s!\n", func);
exit(-1);
}
}
static void
elseek(int d, off_t o, const char *func)
{
if (lseek(d, o, SEEK_SET) == -1) {
perror(func);
exit(-1);
}
}
/* Read the ELF header from a file descriptor and stuff it into a
structure. Make sure it is really an elf header etc. */
static void
read_elf_header(int fd, Elf_Ehdr *ehp)
{
eread(fd, ehp, sizeof(Elf_Ehdr), "read_elf_header");
if (strncmp(ehp->e_ident, elf_magic_string, 4)) {
fprintf(stderr, "Bad ELF magic number --- not an elf file. Exiting in %s.\n", "read_elf_header");
exit(-1);
}
}
static void
read_section_header_entry(int fd, Elf_Shdr *shp)
{
eread(fd, shp, eh.e_shentsize, "read_section_header_entry");
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
}
/*
Map the built-in lisp core sections.
NOTE! We need to do this without using malloc because the memory
layout is not set until some time after this is done.
*/
void
map_core_sections(char *exec_name)
{
int exec_fd;
Elf_Shdr sh; /* A section header entry. */
Elf_Shdr strsecent;
char nambuf[10];
int soff;
int strsecoff; /* File offset to string table section. */
int sections_remaining = 3;
int i, j;
if (!(exec_fd = open(exec_name, O_RDONLY))) {
perror("Can't open executable!");
exit(-1);
}
read_elf_header(exec_fd, &eh);
/* Find the section name string section. Save its file offset. */
soff = eh.e_shoff + eh.e_shstrndx * eh.e_shentsize;
elseek(exec_fd, soff, "map_core_sections");
read_section_header_entry(exec_fd, &strsecent);
strsecoff = strsecent.sh_offset;
for (i = 0; i < eh.e_shnum && sections_remaining > 0; i++) {
/* Read an entry from the section header table. */
elseek(exec_fd, eh.e_shoff + i * eh.e_shentsize, "map_core_sections");
read_section_header_entry(exec_fd, &sh);
/* Read the name from the string section. */
elseek(exec_fd, strsecoff + sh.sh_name, "map_core_sections");
eread(exec_fd, nambuf, 6, "map_core_sections");
if (sh.sh_type == SHT_PROGBITS) {
/* See if this section is one of the lisp core sections. */
for (j = 0; j < 3; j++) {
if (!strncmp(nambuf, core_section_names[j], 6)) {
/* Found a core section. Map it! */
if (os_map(exec_fd, sh.sh_offset, (os_vm_address_t)sh.sh_addr, sh.sh_size) == -1) {
fprintf(stderr, "Can't map section %s\n", core_section_names[j]);
exit(-1);
}
sections_remaining--;
/* Found a core section, don't check the other core section names. */
break;
}
}
}
}
close(exec_fd);
if (sections_remaining != 0) {
fprintf(stderr, "Couldn't map all core sections! Exiting!\n");
exit(-1);
}
}