#ifndef RLD
#include <mach-o/ldsyms.h>
#include <mach-o/swap.h>
#include <string.h>
#ifdef __DYNAMIC__
#include <mach-o/dyld.h>
#endif
#ifndef __OPENSTEP__
#include <crt_externs.h>
#else
#if !defined(__DYNAMIC__)
#define DECLARE_VAR(var, type) \
extern type var
#define SETUP_VAR(var)
#define USE_VAR(var) var
#else
#define STRINGIFY(a) # a
#define DECLARE_VAR(var, type) \
static type * var ## _pointer = NULL
#define SETUP_VAR(var) \
if ( var ## _pointer == NULL) { \
_dyld_lookup_and_bind( STRINGIFY(_ ## var), \
(uint32_t *) & var ## _pointer, NULL); \
}
#define USE_VAR(var) (* var ## _pointer)
#endif
#endif
const struct section *
getsectbynamefromheader(
struct mach_header *mhp,
const char *segname,
const char *sectname)
{
struct segment_command *sgp;
struct section *sp;
uint32_t 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);
}
const struct section_64 *
getsectbynamefromheader_64(
struct mach_header_64 *mhp,
const char *segname,
const char *sectname)
{
struct segment_command_64 *sgp;
struct section_64 *sp;
uint32_t i, j;
sgp = (struct segment_command_64 *)
((char *)mhp + sizeof(struct mach_header_64));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == LC_SEGMENT_64)
if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
mhp->filetype == MH_OBJECT){
sp = (struct section_64 *)((char *)sgp +
sizeof(struct segment_command_64));
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_64 *)((char *)sp +
sizeof(struct section_64));
}
}
sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize);
}
return((struct section_64 *)0);
}
const struct section *
getsectbynamefromheaderwithswap(
struct mach_header *mhp,
const char *segname,
const char *sectname,
int fSwap)
{
struct segment_command *sgp;
struct section *sp;
uint32_t i, j;
sgp = (struct segment_command *)
((char *)mhp + sizeof(struct mach_header));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) {
if (fSwap) {
#ifdef __LITTLE_ENDIAN__
swap_segment_command(sgp, NX_BigEndian);
#else
swap_segment_command(sgp, NX_LittleEndian);
#endif
}
if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
mhp->filetype == MH_OBJECT){
sp = (struct section *)((char *)sgp +
sizeof(struct segment_command));
if (fSwap) {
#ifdef __LITTLE_ENDIAN__
swap_section(sp, sgp->nsects, NX_BigEndian);
#else
swap_section(sp, sgp->nsects, NX_LittleEndian);
#endif
}
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);
} else {
sgp = (struct segment_command *)((char *)sgp +
(fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize));
}
}
return((struct section *)0);
}
#ifndef __LP64__
const struct section *
getsectbyname(
const char *segname,
const char *sectname)
{
static struct mach_header *mhp = NULL;
#ifndef __OPENSTEP__
if(mhp == NULL)
mhp = _NSGetMachExecuteHeader();
#else
DECLARE_VAR(_mh_execute_header, struct mach_header);
SETUP_VAR(_mh_execute_header);
mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header));
#endif
return(getsectbynamefromheader(mhp, segname, sectname));
}
#else
const struct section_64 *
getsectbyname(
const char *segname,
const char *sectname)
{
static struct mach_header_64 *mhp = NULL;
if(mhp == NULL)
mhp = _NSGetMachExecuteHeader();
return(getsectbynamefromheader_64(mhp, segname, sectname));
}
#endif
char *
getsectdata(
const char *segname,
const char *sectname,
unsigned long *size)
{
#ifndef __LP64__
const struct section *sp;
#else
const struct section_64 *sp;
#endif
sp = getsectbyname(segname, sectname);
if(sp == NULL){
*size = 0;
return(NULL);
}
*size = sp->size;
return((char *)(sp->addr));
}
#ifndef __LP64__
uint8_t *
getsectiondata(
const struct mach_header *mhp,
const char *segname,
const char *sectname,
unsigned long *size)
{
struct segment_command *sgp, *zero;
struct section *sp, *find;
uint32_t i, j;
zero = 0;
find = 0;
sp = 0;
sgp = (struct segment_command *)
((char *)mhp + sizeof(struct mach_header));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == LC_SEGMENT){
if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){
zero = sgp;
if(find != 0)
goto done;
}
if(find == 0 &&
strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){
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){
find = sp;
if(zero != 0)
goto done;
}
sp = (struct section *)((char *)sp +
sizeof(struct section));
}
}
}
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return(0);
done:
*size = sp->size;
return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr));
}
uint8_t *
getsegmentdata(
const struct mach_header *mhp,
const char *segname,
unsigned long *size)
{
struct segment_command *sgp, *zero, *find;
uint32_t i;
zero = 0;
find = 0;
sgp = (struct segment_command *)
((char *)mhp + sizeof(struct mach_header));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == LC_SEGMENT){
if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){
zero = sgp;
if(find != 0)
goto done;
}
if(find == 0 &&
strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){
find = sgp;
if(zero != 0)
goto done;
}
}
sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
}
return(0);
done:
*size = sgp->vmsize;
return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr));
}
#else
uint8_t *
getsectiondata(
const struct mach_header_64 *mhp,
const char *segname,
const char *sectname,
unsigned long *size)
{
struct segment_command_64 *sgp, *zero;
struct section_64 *sp, *find;
uint32_t i, j;
zero = 0;
find = 0;
sp = 0;
sgp = (struct segment_command_64 *)
((char *)mhp + sizeof(struct mach_header_64));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == LC_SEGMENT_64){
if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){
zero = sgp;
if(find != 0)
goto done;
}
if(find == 0 &&
strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){
sp = (struct section_64 *)((char *)sgp +
sizeof(struct segment_command_64));
for(j = 0; j < sgp->nsects; j++){
if(strncmp(sp->sectname, sectname,
sizeof(sp->sectname)) == 0 &&
strncmp(sp->segname, segname,
sizeof(sp->segname)) == 0){
find = sp;
if(zero != 0)
goto done;
}
sp = (struct section_64 *)((char *)sp +
sizeof(struct section_64));
}
}
}
sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize);
}
return(0);
done:
*size = sp->size;
return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr));
}
uint8_t *
getsegmentdata(
const struct mach_header_64 *mhp,
const char *segname,
unsigned long *size)
{
struct segment_command_64 *sgp, *zero, *find;
uint32_t i;
zero = 0;
find = 0;
sgp = (struct segment_command_64 *)
((char *)mhp + sizeof(struct mach_header_64));
for(i = 0; i < mhp->ncmds; i++){
if(sgp->cmd == LC_SEGMENT_64){
if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){
zero = sgp;
if(find != 0)
goto done;
}
if(find == 0 &&
strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){
find = sgp;
if(zero != 0)
goto done;
}
}
sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize);
}
return(0);
done:
*size = sgp->vmsize;
return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr));
}
#endif
char *
getsectdatafromheader(
struct mach_header *mhp,
const char *segname,
const char *sectname,
unsigned long *size)
{
const struct section *sp;
sp = getsectbynamefromheader(mhp, segname, sectname);
if(sp == NULL){
*size = 0;
return(NULL);
}
*size = sp->size;
return((char *)((uintptr_t)(sp->addr)));
}
char *
getsectdatafromheader_64(
struct mach_header_64 *mhp,
const char *segname,
const char *sectname,
unsigned long *size)
{
const struct section_64 *sp;
sp = getsectbynamefromheader_64(mhp, segname, sectname);
if(sp == NULL){
*size = 0;
return(NULL);
}
*size = sp->size;
return((char *)((uintptr_t)(sp->addr)));
}
#ifdef __DYNAMIC__
void *
getsectdatafromFramework(
const char *FrameworkName,
const char *segname,
const char *sectname,
unsigned long *size)
{
uint32_t i, n;
uintptr_t vmaddr_slide;
#ifndef __LP64__
struct mach_header *mh;
const struct section *s;
#else
struct mach_header_64 *mh;
const struct section_64 *s;
#endif
char *name, *p;
n = _dyld_image_count();
for(i = 0; i < n ; i++){
name = _dyld_get_image_name(i);
p = strrchr(name, '/');
if(p != NULL && p[1] != '\0')
name = p + 1;
if(strcmp(name, FrameworkName) != 0)
continue;
mh = _dyld_get_image_header(i);
vmaddr_slide = _dyld_get_image_vmaddr_slide(i);
#ifndef __LP64__
s = getsectbynamefromheader(mh, segname, sectname);
#else
s = getsectbynamefromheader_64(mh, segname, sectname);
#endif
if(s == NULL){
*size = 0;
return(NULL);
}
*size = s->size;
return((void *)(s->addr + vmaddr_slide));
}
*size = 0;
return(NULL);
}
#endif
#endif