This is NeXTunixfasl.c in view mode; [Download] [Up]
/*
* FASL loader using rld() for NeXT
*
* Written by Noritake YONEZAWA (yonezawa@lsi.tmg.nec.co.jp)
* February 14, 1992
*
* Modified by Noritake YONEZAWA (yonezawa@lsi.tmg.nec.co.jp)
* May 1, 1995
* June 5, 1995
* June 6, 1995
*/
#include <mach/mach.h>
#include <mach-o/loader.h>
#include <mach-o/rld.h>
#include <ar.h>
#include <nlist.h>
#include <sys/types.h>
#include <sys/file.h>
#include <strings.h>
static unsigned long object_size, object_start;
static unsigned long
my_address_func(size, headers_size)
unsigned long size;
unsigned long headers_size;
{
return (object_start =
(unsigned long)alloc_contblock(object_size = size + headers_size));
}
static void
load_mach_o(filename)
char *filename;
{
FILE *fp;
struct mach_header header;
char *hdrbuf;
struct load_command *load_command;
struct segment_command *segment_command;
struct section *section;
int len, cmd, seg;
if ((fp = fopen(filename, "r")) == NULL)
FEerror("Can't read Mach-O object file", 0);
len = fread((char *)&header, sizeof(struct mach_header), 1, fp);
if (len == 1 && header.magic == MH_MAGIC) {
hdrbuf = (char *)malloc(header.sizeofcmds);
len = fread(hdrbuf, header.sizeofcmds, 1, fp);
if (len != 1)
FEerror("failure reading Mach-O load commands", 0);
load_command = (struct load_command *) hdrbuf;
for (cmd = 0; cmd < header.ncmds; ++cmd) {
if (load_command->cmd == LC_SEGMENT) {
segment_command = (struct segment_command *) load_command;
section = (struct section *) ((char *)(segment_command + 1));
for (seg = 0; seg < segment_command->nsects; ++seg, ++section) {
if (section->size != 0 && section->offset != 0) {
#ifdef DEBUG
fprintf(stderr, "section: %s, addr: 0x%08x, size: %d\n",
section->sectname, section->addr, section->size);
fflush(stderr);
#endif
fseek(fp, section->offset, 0);
fread((char *)section->addr, section->size, 1, fp);
}
}
}
load_command = (struct load_command *)
((char *)load_command + load_command->cmdsize);
}
free(hdrbuf);
}
(void)fclose(fp);
}
int
seek_to_end_ofile(fp)
FILE *fp;
{
struct mach_header mach_header;
char *hdrbuf;
struct load_command *load_command;
struct segment_command *segment_command;
struct section *section;
struct symtab_command *symtab_command;
struct symseg_command *symseg_command;
int len, cmd, seg;
int end_sec, end_ofile;
end_ofile = 0;
fseek(fp, 0L, 0);
len = fread((char *)&mach_header, sizeof(struct mach_header), 1, fp);
if (len == 1 && mach_header.magic == MH_MAGIC) {
hdrbuf = (char *)malloc(mach_header.sizeofcmds);
len = fread(hdrbuf, mach_header.sizeofcmds, 1, fp);
if (len != 1) {
fprintf(stderr, "seek_to_end_ofile(): failure reading Mach-O load commands\n");
return 0;
}
load_command = (struct load_command *) hdrbuf;
for (cmd = 0; cmd < mach_header.ncmds; ++cmd) {
switch (load_command->cmd) {
case LC_SEGMENT:
segment_command = (struct segment_command *) load_command;
section = (struct section *) ((char *)(segment_command + 1));
for (seg = 0; seg < segment_command->nsects; ++seg, ++section) {
end_sec = section->offset + section->size;
if (end_sec > end_ofile)
end_ofile = end_sec;
}
break;
case LC_SYMTAB:
symtab_command = (struct symtab_command *) load_command;
end_sec = symtab_command->symoff + symtab_command->nsyms * sizeof(struct nlist);
if (end_sec > end_ofile)
end_ofile = end_sec;
end_sec = symtab_command->stroff + symtab_command->strsize;
if (end_sec > end_ofile)
end_ofile = end_sec;
break;
case LC_SYMSEG:
symseg_command = (struct symseg_command *) load_command;
end_sec = symseg_command->offset + symseg_command->size;
if (end_sec > end_ofile)
end_ofile = end_sec;
break;
}
load_command = (struct load_command *)
((char *)load_command + load_command->cmdsize);
}
free(hdrbuf);
fseek(fp, end_ofile, 0);
return 1;
}
return 0;
}
static char *library_search_path[] =
{"/lib", "/usr/lib", "/usr/local/lib", NULL};
#define strdup(string) strcpy((char *)malloc(strlen(string)+1),(string))
static char *
expand_library_filename(filename)
char *filename;
{
int fd;
char **dir;
char libname[256];
char fullname[256];
if (filename[0] == '-' && filename[1] == 'l') {
filename++;
filename++;
strcpy(libname, "lib");
strcat(libname, filename);
strcat(libname, ".a");
for (dir = library_search_path; *dir; dir++) {
strcpy(fullname, *dir);
strcat(fullname, "/");
strcat(fullname, libname);
#ifdef DEBUG
fprintf(stderr, "%s\n", fullname);
fflush(stderr);
#endif
if ((fd = open(fullname, O_RDONLY, 0)) > 0) {
close(fd);
return (strdup(fullname));
}
}
return (strdup(libname));
}
return (strdup(filename));
}
static char **
make_ofile_list(faslfile, argstr)
char *faslfile, *argstr;
{
char filename[256];
char *dst;
int i;
char **ofile_list;
ofile_list = (char **)calloc(1, sizeof(char *));
ofile_list[0] = strdup(faslfile);
i = 1;
if (argstr != NULL) {
for (;; i++) {
while ((*argstr == ' ') && (*argstr != '\0'))
argstr++;
if (*argstr == '\0')
break;
dst = filename;
while ((*argstr != ' ') && (*argstr != '\0'))
*dst++ = *argstr++;
*dst = '\0';
ofile_list = (char **)realloc((void *)ofile_list,
(i + 1) * sizeof(char *));
ofile_list[i] = expand_library_filename(filename);
}
}
ofile_list = (char **)realloc((void *)ofile_list, (i + 1) * sizeof(char *));
ofile_list[i] = NULL;
return (ofile_list);
}
static void
free_ofile_list(ofile_list)
char **ofile_list;
{
int i;
for (i = 1;; i++) {
if (ofile_list[i] == NULL)
break;
(void)free(ofile_list[i]);
}
(void)free(ofile_list);
}
#ifdef DEBUG
static void
print_ofile_list(ofile_list)
char **ofile_list;
{
int i;
if (ofile_list == NULL)
return;
fprintf(stderr, "ofiles: ");
for (i = 0;; i++) {
if (ofile_list[i] == NULL)
break;
fprintf(stderr, "(%s)", ofile_list[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
}
#endif
int
fasload(pathname)
object pathname;
{
FILE *fp;
object *old_vs_base = vs_base;
object *old_vs_top = vs_top;
object memory;
object fasl_data;
object stream;
char entryname[100];
char filename[256];
char tempfilename[40];
char **ofiles;
NXStream *err_stream;
void (*entry) ();
struct mach_header *hdr;
stream = open_stream(pathname, smm_input, Cnil, sKerror);
fp = stream->sm.sm_fp;
seek_to_end_ofile(fp);
fasl_data = read_fasl_vector(stream);
vs_push(fasl_data);
pathname = coerce_to_pathname(stream);
coerce_to_filename(stream, filename);
if ((err_stream = NXOpenFile(fileno(stderr), NX_WRITEONLY)) == 0)
FEerror("NXOpenFile() failed", 0);
sprintf(tempfilename, "/tmp/fasltemp%d", getpid());
rld_address_func(my_address_func);
ofiles = make_ofile_list(filename, NULL);
#ifdef DEBUG
print_ofile_list(ofiles);
#endif
if (!rld_load(err_stream, &hdr, ofiles, tempfilename)) {
free_ofile_list(ofiles);
NXFlush(err_stream);
NXClose(err_stream);
FEerror("rld_load() failed", 0);
}
free_ofile_list(ofiles);
load_mach_o(tempfilename);
unlink(tempfilename);
strcpy(entryname, "_init_code");
if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
strcpy(entryname, "_init_");
bcopy(pathname->pn.pn_name->st.st_self,
entryname + 6, pathname->pn.pn_name->st.st_fillp);
entryname[6 + pathname->pn.pn_name->st.st_fillp] = 0;
if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
NXFlush(err_stream);
NXClose(err_stream);
FEerror("Can't find init code", 0);
}
}
(void)rld_unload_all(err_stream, 0);
NXFlush(err_stream);
NXClose(err_stream);
#ifdef DEBUG
{
extern char *mach_brkpt, *mach_maplimit, *core_end;
fprintf(stderr, "mach_brkpt : 0x%08x\n", mach_brkpt);
fprintf(stderr, "mach_maplimit : 0x%08x\n", mach_maplimit);
fprintf(stderr, "core_end : 0x%08x\n", core_end);
fprintf(stderr, "hdr : 0x%08x\n", hdr);
fprintf(stderr, "object_start : 0x%08x\n", object_start);
fprintf(stderr, "object_size : %d\n", object_size);
fprintf(stderr, "&%s : 0x%08x\n", entryname, entry);
fflush(stderr);
}
#endif
memory = alloc_object(t_cfdata);
memory->cfd.cfd_self = 0;
memory->cfd.cfd_fillp = 0;
memory->cfd.cfd_size = object_size;
memory->cfd.cfd_start = (char *)object_start;
vs_push(memory);
#ifdef CLEAR_CACHE
CLEAR_CACHE;
#endif
call_init(entry - object_start, memory, fasl_data,0);
if (symbol_value(sLAload_verboseA) != Cnil)
printf("start address -T 0x%08x ", entry);
vs_base = old_vs_base;
vs_top = old_vs_top;
close_stream(stream);
return object_size;
}
int
faslink(pathname, ldargstring)
object pathname, ldargstring;
{
FILE *fp;
object *old_vs_base = vs_base;
object *old_vs_top = vs_top;
object memory;
object fasl_data;
object stream;
char entryname[100];
char filename[256];
char ldargstr[256];
char tempfilename[40];
char **ofiles;
NXStream *err_stream;
void (*entry) ();
struct mach_header *hdr;
stream = open_stream(pathname, smm_input, Cnil, sKerror);
fp = stream->sm.sm_fp;
seek_to_end_ofile(fp);
fasl_data = read_fasl_vector(stream);
vs_push(fasl_data);
pathname = coerce_to_pathname(stream);
coerce_to_filename(stream, filename);
coerce_to_filename(ldargstring, ldargstr);
if ((err_stream = NXOpenFile(fileno(stderr), NX_WRITEONLY)) == 0)
FEerror("NXOpenFile() failed", 0);
sprintf(tempfilename, "/tmp/fasltemp%d", getpid());
rld_address_func(my_address_func);
ofiles = make_ofile_list(filename, ldargstr);
#ifdef DEBUG
print_ofile_list(ofiles);
#endif
if (!rld_load(err_stream, &hdr, ofiles, tempfilename)) {
free_ofile_list(ofiles);
NXFlush(err_stream);
NXClose(err_stream);
FEerror("rld_load() failed", 0);
}
free_ofile_list(ofiles);
load_mach_o(tempfilename);
unlink(tempfilename);
strcpy(entryname, "_init_code");
if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
strcpy(entryname, "_init_");
bcopy(pathname->pn.pn_name->st.st_self,
entryname + 6, pathname->pn.pn_name->st.st_fillp);
entryname[6 + pathname->pn.pn_name->st.st_fillp] = 0;
if (!rld_lookup(err_stream, entryname, (unsigned long *)&entry)) {
NXFlush(err_stream);
NXClose(err_stream);
FEerror("Can't find init code", 0);
}
}
(void)rld_unload_all(err_stream, 0);
NXFlush(err_stream);
NXClose(err_stream);
#ifdef DEBUG
{
extern char *mach_brkpt, *mach_maplimit, *core_end;
fprintf(stderr, "mach_brkpt : 0x%08x\n", mach_brkpt);
fprintf(stderr, "mach_maplimit : 0x%08x\n", mach_maplimit);
fprintf(stderr, "core_end : 0x%08x\n", core_end);
fprintf(stderr, "hdr : 0x%08x\n", hdr);
fprintf(stderr, "object_start : 0x%08x\n", object_start);
fprintf(stderr, "object_size : %d\n", object_size);
fprintf(stderr, "&%s : 0x%08x\n", entryname, entry);
fflush(stderr);
}
#endif
memory = alloc_object(t_cfdata);
memory->cfd.cfd_self = 0;
memory->cfd.cfd_fillp = 0;
memory->cfd.cfd_size = object_size;
memory->cfd.cfd_start = (char *)object_start;
vs_push(memory);
#ifdef CLEAR_CACHE
CLEAR_CACHE;
#endif
call_init(entry - object_start, memory, fasl_data,0);
if (symbol_value(sLAload_verboseA) != Cnil)
printf("start address -T 0x%08x \n", entry);
vs_base = old_vs_base;
vs_top = old_vs_top;
close_stream(stream);
return object_size;
}
siLfaslink()
{
bds_ptr old_bds_top;
int i;
object package;
check_arg(2);
check_type_or_pathname_string_symbol_stream(&vs_base[0]);
check_type_string(&vs_base[1]);
vs_base[0] = coerce_to_pathname(vs_base[0]);
vs_base[0]->pn.pn_type = FASL_string;
vs_base[0] = namestring(vs_base[0]);
package = symbol_value(sLApackageA);
old_bds_top = bds_top;
bds_bind(sLApackageA, package);
i = faslink(vs_base[0], vs_base[1]);
bds_unwind(old_bds_top);
vs_top = vs_base;
vs_push(make_fixnum(i));
}
#define FASLINK
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.