#if !defined(KERNEL_PRELOAD)
#include <kern/mach_header.h>
extern struct mach_header _mh_execute_header;
struct section *getsectbynamefromheader(
struct mach_header *header,
char *seg_name,
char *sect_name);
struct segment_command *getsegbynamefromheader(
struct mach_header *header,
char *seg_name);
vm_offset_t getlastaddr(void)
{
struct segment_command *sgp;
vm_offset_t last_addr = 0;
struct mach_header *header = &_mh_execute_header;
int i;
sgp = (struct segment_command *)
((char *)header + sizeof(struct mach_header));
for (i = 0; i < header->ncmds; i++){
if ( sgp->cmd == LC_SEGMENT) {
if (sgp->vmaddr + sgp->vmsize > last_addr)
last_addr = sgp->vmaddr + sgp->vmsize;
}
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return last_addr;
}
#if FIXME
struct mach_header **
getmachheaders(void)
{
extern struct mach_header _mh_execute_header;
struct mach_header **tl;
tl = (struct mach_header **)malloc(2*sizeof(struct mach_header *));
tl[0] = &_mh_execute_header;
tl[1] = (struct mach_header *)0;
return tl;
}
#endif
void *
getsectdatafromheader(
struct mach_header *mhp,
char *segname,
char *sectname,
int *size)
{
const struct section *sp;
void *result;
sp = getsectbynamefromheader(mhp, segname, sectname);
if(sp == (struct section *)0){
*size = 0;
return((char *)0);
}
*size = sp->size;
result = (void *)sp->addr;
return result;
}
void *
getsegdatafromheader(
struct mach_header *mhp,
char *segname,
int *size)
{
const struct segment_command *sc;
void *result;
sc = getsegbynamefromheader(mhp, segname);
if(sc == (struct segment_command *)0){
*size = 0;
return((char *)0);
}
*size = sc->vmsize;
result = (void *)sc->vmaddr;
return result;
}
struct section *
getsectbynamefromheader(
struct mach_header *mhp,
char *segname,
char *sectname)
{
struct segment_command *sgp;
struct section *sp;
long i, j;
sgp = (struct segment_command *)
((char *)mhp + sizeof(struct mach_header));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == LC_SEGMENT)
if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
mhp->filetype == MH_OBJECT){
sp = (struct section *)((char *)sgp +
sizeof(struct segment_command));
for(j = 0; j < sgp->nsects; j++){
if(strncmp(sp->sectname, sectname,
sizeof(sp->sectname)) == 0 &&
strncmp(sp->segname, segname,
sizeof(sp->segname)) == 0)
return(sp);
sp = (struct section *)((char *)sp +
sizeof(struct section));
}
}
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return((struct section *)0);
}
struct segment_command *getsegbynamefromheader(
struct mach_header *header,
char *seg_name)
{
struct segment_command *sgp;
int i;
sgp = (struct segment_command *)
((char *)header + sizeof(struct mach_header));
for (i = 0; i < header->ncmds; i++){
if ( sgp->cmd == LC_SEGMENT
&& !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
return sgp;
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return (struct segment_command *)0;
}
static struct {
struct segment_command seg;
struct section sect;
} fvm_data = {
{
LC_SEGMENT, sizeof(fvm_data), "__USER", 0, 0, 0, 0, VM_PROT_READ, VM_PROT_READ, 1, 0 },
{
"", "__USER", 0, 0, 0, 4, 0, 0, 0 }
};
struct segment_command *fvm_seg;
static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
static vm_offset_t getsizeofmacho(struct mach_header *header);
struct segment_command *firstseg(void)
{
return firstsegfromheader(&_mh_execute_header);
}
struct segment_command *firstsegfromheader(struct mach_header *header)
{
struct segment_command *sgp;
int i;
sgp = (struct segment_command *)
((char *)header + sizeof(struct mach_header));
for (i = 0; i < header->ncmds; i++){
if (sgp->cmd == LC_SEGMENT)
return sgp;
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return (struct segment_command *)0;
}
struct segment_command *nextseg(struct segment_command *sgp)
{
struct segment_command *this;
this = nextsegfromheader(&_mh_execute_header, sgp);
if (!this && sgp != fvm_seg)
this = fvm_seg;
return this;
}
struct segment_command *nextsegfromheader(
struct mach_header *header,
struct segment_command *seg)
{
struct segment_command *sgp;
int i;
sgp = (struct segment_command *)
((char *)header + sizeof(struct mach_header));
for (i = 0; i < header->ncmds; i++) {
if (sgp == seg)
break;
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
if (i == header->ncmds)
return (struct segment_command *)0;
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
for (; i < header->ncmds; i++) {
if (sgp->cmd == LC_SEGMENT)
return sgp;
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return (struct segment_command *)0;
}
struct segment_command *getsegbyname(char *seg_name)
{
struct segment_command *this;
this = getsegbynamefromheader(&_mh_execute_header, seg_name);
if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
this = fvm_seg;
return this;
}
struct section *
getsectbyname(
char *segname,
char *sectname)
{
return(getsectbynamefromheader(
(struct mach_header *)&_mh_execute_header, segname, sectname));
}
struct section *firstsect(struct segment_command *sgp)
{
struct section *sp;
if (!sgp || sgp->nsects == 0)
return (struct section *)0;
return (struct section *)(sgp+1);
}
struct section *nextsect(struct segment_command *sgp, struct section *sp)
{
struct section *fsp = firstsect(sgp);
if (sp - fsp >= sgp->nsects-1)
return (struct section *)0;
return sp+1;
}
static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
{
struct fvmfile_command *fvp;
int i;
fvp = (struct fvmfile_command *)
((char *)header + sizeof(struct mach_header));
for (i = 0; i < header->ncmds; i++){
if (fvp->cmd == LC_FVMFILE)
return fvp;
fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
}
return (struct fvmfile_command *)0;
}
struct segment_command *getfakefvmseg(void)
{
struct segment_command *sgp = getsegbyname("__USER");
struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
struct section *sp;
if (sgp)
return sgp;
if (!fvp)
return (struct segment_command *)0;
fvm_seg = &fvm_data.seg;
sgp = fvm_seg;
sp = &fvm_data.sect;
sgp->vmaddr = fvp->header_addr;
sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
strcpy(sp->sectname, fvp->name.ptr);
sp->addr = sgp->vmaddr;
sp->size = sgp->vmsize;
#if DEBUG
printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
sp->sectname, sp->addr, sp->size);
#endif DEBUG
}
static vm_offset_t getsizeofmacho(struct mach_header *header)
{
struct segment_command *sgp;
struct section *sp;
vm_offset_t last_addr;
last_addr = 0;
for ( sgp = firstsegfromheader(header)
; sgp
; sgp = nextsegfromheader(header, sgp))
{
if (sgp->fileoff + sgp->filesize > last_addr)
last_addr = sgp->fileoff + sgp->filesize;
}
return last_addr;
}
#endif