#ifdef SHLIB
#include "shlib.h"
#endif
#import <stdio.h>
#import <stdlib.h>
#import <stdarg.h>
#import <string.h>
#import <errno.h>
#ifndef __OPENSTEP__
#import <crt_externs.h>
#endif
#import <mach/mach.h>
#import "stuff/openstep_mach.h"
#include <unistd.h>
#ifdef _POSIX_THREADS
#include <pthread.h>
#else
#import <mach/cthreads.h>
#endif
#import <mach/mach_error.h>
#import "stuff/bool.h"
#import "mach-o/dyld.h"
#import "stuff/ofile.h"
#import "stuff/arch.h"
#import "stuff/errors.h"
#import "ofi.h"
__private_extern__ char *progname = NULL;
__private_extern__ unsigned long errors = 0;
#ifdef _POSIX_THREADS
static pthread_mutex_t ofi_error_printing_mutex = PTHREAD_MUTEX_INITIALIZER;
#else
static mutex_t ofi_error_printing_mutex = NULL;
#endif
#ifdef __MACH30__
static thread_port_t thread_printing_error = MACH_PORT_NULL;
#else
static port_t thread_printing_error = MACH_PORT_NULL;
#endif
#ifdef _POSIX_THREADS
static pthread_mutex_t ofi_alloc_mutex = PTHREAD_MUTEX_INITIALIZER;
#else
static mutex_t ofi_alloc_mutex = NULL;
#endif
#define N_OFI 10
struct ofi_list {
struct ofi list[N_OFI];
enum bool used[N_OFI];
struct ofi_list *next;
};
static struct ofi_list *ofi_lists = NULL;
static struct ofi * ofi_alloc(
void);
static enum bool ofi_free(
struct ofi *ofi);
static enum bool ofi_valid(
struct ofi *ofi);
static NSObjectFileImageReturnCode NSCreateImageFromFile(
enum bool coreFile,
const char *pathName,
NSObjectFileImage *objectFileImage);
NSObjectFileImageReturnCode
NSCreateObjectFileImageFromFile(
const char *pathName,
NSObjectFileImage *objectFileImage)
{
return(NSCreateImageFromFile(FALSE, pathName, objectFileImage));
}
NSObjectFileImageReturnCode
NSCreateCoreFileImageFromFile(
const char *pathName,
NSObjectFileImage *objectFileImage)
{
return(NSCreateImageFromFile(TRUE, pathName, objectFileImage));
}
static
NSObjectFileImageReturnCode
NSCreateImageFromFile(
enum bool coreFile,
const char *pathName,
NSObjectFileImage *objectFileImage)
{
struct arch_flag host_arch_flag;
NSObjectFileImageReturnCode o;
struct ofi *ofi;
#ifndef __OPENSTEP__
static char ***NXArgv_pointer = NULL;
if(NXArgv_pointer == NULL)
NXArgv_pointer = _NSGetArgv();
progname = (*NXArgv_pointer)[0];
#else
#ifndef __DYNAMIC__
extern char **NXArgv;
progname = NXArgv[0];
#else
static char ***NXArgv_pointer = NULL;
if(NXArgv_pointer == NULL)
_dyld_lookup_and_bind("_NXArgv",
(unsigned long *)&NXArgv_pointer, NULL);
progname = (*NXArgv_pointer)[0];
#endif
#endif
*objectFileImage = NULL;
if(get_arch_from_host(&host_arch_flag, NULL) == 0){
error("can't determine the host architecture (fix "
"get_arch_from_host() )");
o = NSObjectFileImageFailure;
goto done;
}
ofi = ofi_alloc();
if(ofi == NULL){
error("can't allocate memory for NSObjectFileImage");
o = NSObjectFileImageFailure;
goto done;
}
o = ofile_map(pathName, &host_arch_flag, NULL, &(ofi->ofile), FALSE);
if(o != NSObjectFileImageSuccess){
(void)ofi_free(ofi);
goto done;
}
if(ofi->ofile.file_type != OFILE_Mach_O &&
(ofi->ofile.file_type != OFILE_FAT ||
ofi->ofile.arch_type != OFILE_Mach_O)){
o = NSObjectFileImageInappropriateFile;
ofile_unmap(&(ofi->ofile));
(void)ofi_free(ofi);
goto done;
}
if(ofi->ofile.mh->filetype == MH_FVMLIB ||
(ofi->ofile.mh->filetype == MH_CORE && coreFile == FALSE) ||
ofi->ofile.mh->filetype == MH_DYLIB ||
ofi->ofile.mh->filetype == MH_DYLINKER){
o = NSObjectFileImageInappropriateFile;
ofile_unmap(&(ofi->ofile));
(void)ofi_free(ofi);
goto done;
}
if(coreFile == FALSE && ofi->ofile.mh->filetype != MH_BUNDLE){
if(ofi->ofile.mh->filetype == MH_OBJECT ||
ofi->ofile.mh->filetype == MH_EXECUTE ||
ofi->ofile.mh->filetype == MH_PRELOAD){
o = NSObjectFileImageInappropriateFile;
ofile_unmap(&(ofi->ofile));
(void)ofi_free(ofi);
goto done;
}
else{
o = NSObjectFileImageInappropriateFile;
ofile_unmap(&(ofi->ofile));
(void)ofi_free(ofi);
goto done;
}
}
*objectFileImage = (NSObjectFileImage)ofi;
done:
if(thread_printing_error == mach_thread_self()){
thread_printing_error = MACH_PORT_NULL;
#ifdef _POSIX_THREADS
pthread_mutex_unlock(&ofi_error_printing_mutex);
#else
mutex_unlock(ofi_error_printing_mutex);
#endif
}
return(o);
}
NSObjectFileImageReturnCode
NSCreateObjectFileImageFromMemory(
void *address,
unsigned long size,
NSObjectFileImage *objectFileImage)
{
#ifndef __OPENSTEP__
static char ***NXArgv_pointer = NULL;
if(NXArgv_pointer == NULL)
NXArgv_pointer = _NSGetArgv();
progname = (*NXArgv_pointer)[0];
#else
#ifndef __DYNAMIC__
extern char **NXArgv;
progname = NXArgv[0];
#else
static char ***NXArgv_pointer = NULL;
if(NXArgv_pointer == NULL)
_dyld_lookup_and_bind("_NXArgv",
(unsigned long *)&NXArgv_pointer, NULL);
progname = (*NXArgv_pointer)[0];
#endif
#endif
return(NSObjectFileImageFailure);
}
static
struct ofi *
ofi_alloc(void)
{
struct ofi_list **p, *ofi_list;
unsigned long i;
#ifdef _POSIX_THREADS
pthread_mutex_lock(&ofi_alloc_mutex);
#else
if(ofi_alloc_mutex == NULL)
ofi_alloc_mutex = mutex_alloc();
mutex_lock(ofi_alloc_mutex);
#endif
for(p = &ofi_lists; ; p = &((*p)->next)){
if(*p == NULL){
ofi_list = malloc(sizeof(struct ofi_list));
if(ofi_list == NULL){
#ifdef _POSIX_THREADS
pthread_mutex_unlock(&ofi_alloc_mutex);
#else
mutex_unlock(ofi_alloc_mutex);
#endif
return(NULL);
}
*p = ofi_list;
memset(ofi_list, '\0', sizeof(struct ofi_list));
ofi_list->used[0] = TRUE;
#ifdef _POSIX_THREADS
pthread_mutex_unlock(&ofi_alloc_mutex);
#else
mutex_unlock(ofi_alloc_mutex);
#endif
return(ofi_list->list);
}
ofi_list = *p;
for(i = 0; i < N_OFI; i++){
if(ofi_list->used[i] == FALSE){
memset(ofi_list->list + i, '\0', sizeof(struct ofi));
ofi_list->used[i] = TRUE;
#ifdef _POSIX_THREADS
pthread_mutex_unlock(&ofi_alloc_mutex);
#else
mutex_unlock(ofi_alloc_mutex);
#endif
return(ofi_list->list + i);
}
}
}
#ifdef _POSIX_THREADS
pthread_mutex_unlock(&ofi_alloc_mutex);
#else
mutex_unlock(ofi_alloc_mutex);
#endif
return(NULL);
}
static
enum bool
ofi_free(
struct ofi *ofi)
{
struct ofi_list **p, *ofi_list, *prev;
unsigned long i, used;
enum bool return_value;
#ifdef _POSIX_THREADS
pthread_mutex_lock(&ofi_alloc_mutex);
#else
if(ofi_alloc_mutex == NULL)
ofi_alloc_mutex = mutex_alloc();
mutex_lock(ofi_alloc_mutex);
#endif
return_value = FALSE;
prev = NULL;
for(p = &ofi_lists; *p != NULL; p = &((*p)->next)){
ofi_list = *p;
used = 0;
for(i = 0; i < N_OFI; i++){
if(ofi_list->used[i] == TRUE){
if(ofi == ofi_list->list + i){
ofi_list->used[i] = FALSE;
memset(ofi_list->list + i, '\0', sizeof(struct ofi));
return_value = TRUE;
}
else{
used++;
}
}
}
if(used == 0){
if(prev == NULL){
ofi_lists = ofi_list->next;
}
else{
prev->next = ofi_list->next;
}
free(ofi_list);
break;
}
prev = ofi_list;
}
#ifdef _POSIX_THREADS
pthread_mutex_unlock(&ofi_alloc_mutex);
#else
mutex_unlock(ofi_alloc_mutex);
#endif
return(return_value);
}
static
enum bool
ofi_valid(
struct ofi *ofi)
{
struct ofi_list *ofi_list;
unsigned long i;
for(ofi_list = ofi_lists; ofi_list != NULL; ofi_list = ofi_list->next){
for(i = 0; i < N_OFI; i++){
if(ofi_list->list + i == ofi)
return(TRUE);
}
}
return(FALSE);
}
__private_extern__
void
vprint(
const char *format,
va_list ap)
{
#ifndef _POSIX_THREADS
if(ofi_error_printing_mutex == NULL)
ofi_error_printing_mutex = mutex_alloc();
#endif
if(thread_printing_error != mach_thread_self()){
#ifdef _POSIX_THREADS
pthread_mutex_lock(&ofi_error_printing_mutex);
#else
mutex_lock(ofi_error_printing_mutex);
#endif
thread_printing_error = mach_thread_self();
}
vfprintf(stderr, format, ap);
}
__private_extern__
void
print(
const char *format,
...)
{
va_list ap;
va_start(ap, format);
vprint(format, ap);
va_end(ap);
}
__private_extern__
void
error(
const char *format,
...)
{
va_list ap;
va_start(ap, format);
print("%s: ", progname);
vprint(format, ap);
print("\n");
va_end(ap);
errors++;
}
__private_extern__
void
system_error(
const char *format,
...)
{
va_list ap;
va_start(ap, format);
print("%s: ", progname);
vprint(format, ap);
print(" (%s)\n", strerror(errno));
va_end(ap);
errors++;
}
__private_extern__
void
my_mach_error(
kern_return_t r,
char *format,
...)
{
va_list ap;
va_start(ap, format);
print("%s: ", progname);
vprint(format, ap);
print(" (%s)\n", mach_error_string(r));
va_end(ap);
errors++;
}
__private_extern__
char *
savestr(
const char *s)
{
long len;
char *r;
len = strlen(s) + 1;
r = (char *)malloc(len);
if(r == NULL)
return(NULL);
strcpy(r, s);
return(r);
}
enum bool
NSDestroyObjectFileImage(
NSObjectFileImage objectFileImage)
{
struct ofi *ofi;
ofi = (struct ofi *)objectFileImage;
if(ofi_valid(ofi) == FALSE)
return(FALSE);
ofile_unmap(&(ofi->ofile));
if(ofi_free(ofi) == FALSE)
return(FALSE);
return(TRUE);
}
unsigned long
NSSymbolDefinitionCountInObjectFileImage(
NSObjectFileImage objectFileImage)
{
return(0);
}
const char *
NSSymbolDefinitionNameInObjectFileImage(
NSObjectFileImage objectFileImage,
unsigned long ordinal)
{
return(NULL);
}
unsigned long
NSSymbolReferenceCountInObjectFileImage(
NSObjectFileImage objectFileImage)
{
return(0);
}
const char *
NSSymbolReferenceNameInObjectFileImage(
NSObjectFileImage objectFileImage,
unsigned long ordinal,
enum bool *tentative_definition)
{
return(NULL);
}
enum bool
NSIsSymbolDefinedInObjectFileImage(
NSObjectFileImage objectFileImage,
const char *symbolName)
{
return(FALSE);
}
void *
NSGetSectionDataInObjectFileImage(
NSObjectFileImage objectFileImage,
const char *segmentName,
const char *sectionName)
{
return(NULL);
}