Question

I'm facing an issue with the Free Pascal shared library startup code on Android. The Free Pascal RTL sources have the following fragment:

type
  TAuxiliaryValue = cuInt32;

  TInternalUnion = record
    a_val: cuint32;           //* Integer value */
      {* We use to have pointer elements added here.  We cannot do that,
         though, since it does not work when using 32-bit definitions
         on 64-bit platforms and vice versa.  *}
  end;

  Elf32_auxv_t = record
    a_type: cuint32;              //* Entry type */
    a_un: TInternalUnion;
  end;
  TElf32AuxiliaryVector = Elf32_auxv_t;
  PElf32AuxiliaryVector = ^TElf32AuxiliaryVector;

var
  psysinfo: LongWord = 0;

procedure InitSyscallIntf;
var
  ep: PPChar;
  auxv: PElf32AuxiliaryVector;
begin

  psysinfo := 0;
  ep := envp;
  while ep^ <> nil do
    Inc(ep);

  Inc(ep);

  auxv := PElf32AuxiliaryVector(ep);

  repeat
    if auxv^.a_type = AT_SYSINFO then begin
      psysinfo := auxv^.a_un.a_val;
      if psysinfo <> 0 then
        sysenter_supported := 1; // descision factor in asm syscall routines
      Break;
    end;
    Inc(auxv);
  until auxv^.a_type = AT_NULL;
end;

The procedure InitSyscallIntf is being invoked as a part of the SO startup sequence. The envp is a unit-level variable that's initialized earlier in the startup sequence to the value of libc's environ. What this looks like to me, the code is trying to scan the environ array past the null pointer (which I thought denoted the end of the environment block), then tries to read the memory that's past.

What are they expecting to find past the end of the environ array? Probably they're making some assumptions about the structure of memory of a loaded ELF file - can I see a reference?

Was it helpful?

Solution 2

The link posted by Seva is what it is looking at, and in that it is looking if the sysenter instruction is supported.

This instruction allows for faster syscalls, and on Linux and FreeBSD kernel based systems, generally Free Pascal program access the kernel directly, not via libc.

See rtl/linux/i386/* an rtl/linux/x86_64 for the syscall wrapper routines, and you'll see the test for sysenter there.

OTHER TIPS

Looks like they were going by this. There's a set of two-DWORD data chunks called auxiliary vectors past the end of environment. The first DWORD in a vector is its type, the second one is value. The types are documented in linux/auxvec.h; there are about 20 of them.

Specifically, the FPC startup is looking for the vector of type AT_SYSINFO (32).

The aux vectors are past the end of environment block, but a copy of the aux vector block is available as a file under /proc/me/auxv.

According to Startup state of a Linux/i386 ELF binary the segment layout of an ELF binary has the program name after the environment array.

Actually, I'm not sure if that's what your program is accessing. That's the environment data, the environment array (the pointers to those strings) is in the initial stack frame. The above page doesn't show anything specific after that, I assume it's the local data for the main() function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top