Files bigger than max(off64_t) on Solaris, eg “/proc/../as”

64bitprocprocesssolarisx86

How do I read or seek from a file that's bigger than the maximum off64_t? The problem arises because the address space of a process is represented in the /proc/.../as file, which is a huge sparse file for 64-bit processes. It's really very big: on a sample process on Solaris x86-64, argv's address is 0xFFFFFD7FFFxxxxxx, that is, the very top of the address space is used. Pointers are unsigned, but an off64_t is signed, so can't reach anything in the top half of the address space file.

This obviously depends on the layout of the address space. On 32-bit systems, this isn't a problem (a long offset isn't big enough, but an off64_t easily works), and on x86-64 on linux (for example), the top of the process is 0x7fffxxxxxxxx (48 bits), so again an off64_t can refer to anything in the process's address space.

So, it's a shame that Solaris on x86-64 seems to use the whole 64-bit address space, when 50 bits is more than enough. Sun's examples of using psinfo_t.pr_argv just don't seem to work except on SPARC and x86. Is there any way around this problem?

Best Answer

There are on Solaris x86-64 some very large files, whose size exceeds 263, that is, the maximum size representable in an off64_t. This includes the file representing a process's address space in proc (/proc/<pid>/as).

To deal with these files:

  1. Don't use fopen, fseek, etc. Don't trust the libc stream routines, which (on the versions of Solaris I tested) mangle badly the "illegal" offsets.
  2. Use open64, read.
  3. To seek:

    static off64_t lseeku64(int file, uint64_t offset /* eg from pr_argv */)
    {
    #ifndef __sun
      if (offset > 0x7FFFFFFFFFFFFFFFllu) return -1;
    #endif
      return lseek64(file, offset, SEEK_SET);
    }
    

    That is, on Solaris, we know that we can do this cast because of inspection of the OpenSolaris sources, but we should avoid assuming it works on other platforms with psinfo and pr_argv (eg AIX).

    But, pass in your very large offset, and it does all "just work".

Related Question