Can a range of virtual addresses be used?

I have an Ada program written for a specific (embedded, multiprocessor, 32-bit) architecture. I am trying to use this same code in a 64bit RHEL simulation as a shared object (as there are multiple versions and I have a requirement to select a version at runtime).

The problem is that there are several places in the code where the people who wrote it (not me ...) used Unchecked_Conversions to convert System.Addresses to 32-bit integers. Not only that, but there are several routines with hard-coded memory addresses. I can make minor changes to this code, but completely porting it to x86_64 isn't really an option. There are routines that handle interrupts, scheduling CPU tasks, etc.

This code has worked in the past when it was statically linked to a previous version of the simulation (consisting of Fortran / C / C ++). Now, however, the main executable starts up, then loads the shared object based on some inputs. This shared object then checks some other inputs and loads the corresponding Ada shared object.

Looking at the code, it is obvious that it should work fine if I can store logical memory addresses between 0 and 2147483647 (32-bit signed int). Is there a way to force the shared object loader to leave space in the lower ranges for the Ada code, or perhaps make the Ada code "think" that it is addressed between 0 and 2147483647?


source to share

1 answer

Is there a way to force the shared object loader to leave space in the lower ranges for the Ada code

The good news is that the bootloader will leave the lower ranges untouched.

The bad news is that it won't load any shared object there. The interface you can use does not affect the placement of shared objects.

However, dlopen from memory (which we have implemented in our private glibc fork) will allow you to do this. But this is not publicly available.

Your other possible options:

  • if you can put the whole process in a 32-bit address space then your solution is trivial: just create everything with -m32


  • use prelink

    to move the library to the desired address. Since this address should almost always be available, the loader will most likely load the library there.

  • link the loader with a custom implementation mmap

    that discovers the library of interest through some side channel and runs mmap

    syscall with MAP_32BIT

    , or

  • run the program in the sandbox ptrace

    . Such a sandbox can intercept mmap

    syscall and or-in again MAP_32BIT

    when desired.

or perhaps make the Ada code "think" it is addressed between 0 and 2 147 483 647?

I don't understand how this is possible. If the library stores the address of a function or a global one in a 32-bit memory location, then loads that address and plays it out ... it's going to get a 32-bit truncated address and SIGSEGV

on dereference.



All Articles