ONLamp.com
oreilly.comSafari Books Online.Conferences.

advertisement


Linux Compatibility on BSD for the PPC Platform: Part 2

by Emmanuel Dreyfus
05/17/2001

Managing dynamic executables

In this article, we'll take a closer look at the problems that prevent dynamic Linux binaries from working in compatibility mode on the NetBSD/PowerPC platform. This includes the way the arguments are passed to the Linux program, and ELF auxilliary table handling.

Passing arguments to the program

The first problem here is Linux's ld.so did not get its command-line arguments. In fact, no program running in Linux emulation -- either statically linked or dynamically linked -- was actually able to get its arguments. This could be outlined by building this sample program on a Linux box (statically, of course), and trying to run it on the NetBSD box:

/*
* arg.c -- An argument printer
*/
#include <stdio.h>
int main (int argc, char **argv) {
int i;
for (i=0; i<= argc; i++) {
printf ("argc[%d]=%s\n", i, argv[i]);
if (argc > 1)
return atoi (argv[1]);
return 0;
}

This programs tests argument and return value passing between the kernel and the emulated executable. When running it, we get no output at all. The program got a null argc, which demonstrated the problem passing command-line arguments.

The arguments are passed to the program using the stack. When preparing the program launch, the kernel sets up the stack so the program will be able to find argc, argv, and envp. To inspect this mechanism a bit deeper, we can use a stack dumper, like the following piece of code :

/*
* sd.c -- A stack dumper
*/
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>

extern long end;
extern long etext;
extern long edata;
extern char **environ;

void stackdump (long, char **);

int main (int argc, char **argv) {
 long sign = 0x89abcdef;

 printf ("argc=0x%p\n", &argc);
 printf ("argv=0x%p\n", &argv);
 printf ("environ=0x%p\n", &environ);
 stackdump (sign, argv);

 return 0;
}

void stackdump (long arg, char **argv) {
  unsigned long i,j;
  long signature = 0x01234567;
 
  if (0)
    printf ("%lx %lx\n", arg, signature);

  printf ("etext=0x%lx\nedata=0x%lx\nend=0x%lx\n", etext, edata, end);
  for (i = (((long)argv-0x400)/16)*16; i <= 0x7fffffff; i=i+16) {
    printf ("%08lx ",i);
    for (j=0; j <= 15; j=j+2) {
      printf ("%02x", (*(char*)(i+j)));
      printf ("%02x ", (*(char*)(i+j+1)));
    }
    for (j = 0; j <= 15; j++) {
      if (isprint (*(char*)(i+j)))
        printf ("%c", *(char*)(i+j));
      else
        printf (".");
    }
    printf ("\n");
  }
}

This program also uses global and local variables to help study argument passing. It dumps the stack from an arbitrary address until it reaches the end of the stack and crashes, because pages after the stack are not accessible when running in user mode. We do not really care about this crash because it displays what we are looking for. However, this can be a problem if you are working on a terminal that is unable to scroll back and want to pipe the stack dump's output to more(1) or less (1).

If you want to do this, you will have to modify the program so it catches the SIGSEGV signal. You will also have to ensure that linux_sendsig() in linux_machdep.c does not crash anything. Most likely, you will keep that function empty. The easy solution is certainly to get a terminal that has a scrollback feature.

Pages: 1, 2, 3, 4

Next Pagearrow





Sponsored by: