Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added aix support #31

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions src/whereami.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,112 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
return length;
}

#elif defined(_AIX)

#include <dlfcn.h>
#include <procinfo.h>
#include <sys/ldr.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>

WAI_NOINLINE WAI_FUNCSPEC int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length);

WAI_FUNCSPEC
int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
{
/* We assume that this gets called before the program would potentially change the work dir */
struct procsinfo processBuffer;
processBuffer.pi_pid = getpid();
size_t argsBufferLength = 64*1024;
char *argsBuffer = (char *)WAI_MALLOC(argsBufferLength);
char *realpathBuffer = (char *)WAI_MALLOC(PATH_MAX);
if (!argsBuffer || !realpathBuffer)
goto error;

if (getargs(&processBuffer, sizeof(processBuffer), argsBuffer, argsBufferLength) != 0)
goto error;

const char *firstNullPosition = memchr(argsBuffer, 0, argsBufferLength);
if (!firstNullPosition || firstNullPosition == argsBuffer)
goto error;

const char *fullPath = realpath(argsBuffer, realpathBuffer);
if (!fullPath || strlen(fullPath) >= capacity)
goto error;

strcpy(out, fullPath);
WAI_FREE(argsBuffer);
WAI_FREE(realpathBuffer);
if (dirname_length) {
*dirname_length = strrchr(out, '/') - out;
}
return strlen(out);

error:
WAI_FREE(argsBuffer);
WAI_FREE(realpathBuffer);
return -1;
}

WAI_NOINLINE WAI_FUNCSPEC
int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
{
char *allocedMem = NULL;
int allocSize = 64*1024;
struct ld_info *info = NULL;
int length = -1;
int retcode = -1;
for (; allocSize <= 1024*1024; allocSize *= 2) {
allocedMem = (char *)WAI_MALLOC(allocSize);
if (!allocedMem) {
return -1;
}
retcode = loadquery(L_GETINFO, allocedMem, allocSize);
info = (struct ld_info *)allocedMem;
if (retcode != -1 || errno != ENOMEM)
break;
WAI_FREE(allocedMem);
allocedMem = NULL;
}

if (retcode != -1) {
void *addressInLib = WAI_RETURN_ADDRESS();
for(;;) {
if (info->ldinfo_textorg < addressInLib && (info->ldinfo_textorg + info->ldinfo_textsize) > addressInLib) {
char *resolved = info->ldinfo_filename;
length = (int)strlen(resolved);
if (length <= capacity)
{
memcpy(out, resolved, length);

if (dirname_length)
{
int i;

for (i = length - 1; i >= 0; --i)
{
if (out[i] == '/')
{
*dirname_length = i;
break;
}
}
}
}
break;
}
if (!info->ldinfo_next)
break;
info = (struct ld_info *)((char *)info + info->ldinfo_next);
}
}
if (allocedMem) {
munmap(allocedMem, allocSize);
}
return length;
}

#else

#error unsupported platform
Expand Down